Changeset 7536 for main/waeup.sirp/trunk/src/waeup/sirp/students
- Timestamp:
- 30 Jan 2012, 07:41:17 (13 years ago)
- Location:
- main/waeup.sirp/trunk/src/waeup/sirp/students
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.sirp/trunk/src/waeup/sirp/students/batching.py
r7534 r7536 37 37 from waeup.sirp.students.interfaces import ( 38 38 IStudent, IStudentStudyCourse, 39 IStudentUpdateByRegNo, IStudentUpdateByMatricNo) 39 IStudentUpdateByRegNo, IStudentUpdateByMatricNo, 40 IStudentStudyLevel) 40 41 from waeup.sirp.students.workflow import IMPORTABLE_STATES 41 42 from waeup.sirp.utils.batching import BatchProcessor … … 268 269 return self.getParent(row, site) is not None 269 270 270 271 271 def entryExists(self, row, site): 272 272 return self.getEntry(row, site) is not None … … 274 274 def getEntry(self, row, site): 275 275 student = self.getParent(row, site) 276 if not student:276 if student is None: 277 277 return None 278 278 return student.get('studycourse') … … 306 306 return errs, inv_errs, conv_dict 307 307 308 class StudentStudyLevelProcessor(BatchProcessor): 309 """A batch processor for IStudentStudyLevel objects. 310 """ 311 grok.implements(IBatchProcessor) 312 grok.provides(IBatchProcessor) 313 grok.context(Interface) 314 util_name = 'studylevelimporter' 315 grok.name(util_name) 316 317 name = u'StudentStudyLevel Importer' 318 iface = IStudentStudyLevel 319 factory_name = 'waeup.StudentStudyLevel' 320 321 location_fields = [] 322 323 mode = None 324 325 @property 326 def available_fields(self): 327 return sorted(list(set( 328 ['student_id','reg_number','matric_number','level'] + getFields( 329 self.iface).keys()))) 330 331 def checkHeaders(self, headerfields, mode='ignore'): 332 if not 'reg_number' in headerfields and not 'student_id' \ 333 in headerfields and not 'matric_number' in headerfields: 334 raise FatalCSVError( 335 "Need at least columns student_id " + 336 "or reg_number or matric_number for import!") 337 if not 'level' in headerfields: 338 raise FatalCSVError( 339 "Need level for import!") 340 # Check for fields to be ignored... 341 not_ignored_fields = [x for x in headerfields 342 if not x.startswith('--')] 343 if len(set(not_ignored_fields)) < len(not_ignored_fields): 344 raise FatalCSVError( 345 "Double headers: each column name may only appear once.") 346 return True 347 348 def getParent(self, row, site): 349 if not 'students' in site.keys(): 350 return None 351 if 'student_id' in row.keys() and row['student_id']: 352 if row['student_id'] in site['students']: 353 student = site['students'][row['student_id']] 354 return student['studycourse'] 355 elif 'reg_number' in row.keys() and row['reg_number']: 356 reg_number = row['reg_number'] 357 #import pdb; pdb.set_trace() 358 cat = queryUtility(ICatalog, name='students_catalog') 359 results = list( 360 cat.searchResults(reg_number=(reg_number, reg_number))) 361 if results: 362 return results[0]['studycourse'] 363 elif 'matric_number' in row.keys() and row['matric_number']: 364 matric_number = row['matric_number'] 365 cat = queryUtility(ICatalog, name='students_catalog') 366 results = list( 367 cat.searchResults(matric_number=(matric_number, matric_number))) 368 if results: 369 return results[0]['studycourse'] 370 return None 371 372 def parentsExist(self, row, site): 373 return self.getParent(row, site) is not None 374 375 def entryExists(self, row, site): 376 return self.getEntry(row, site) is not None 377 378 def getEntry(self, row, site): 379 studycourse = self.getParent(row, site) 380 if studycourse is None: 381 return None 382 return studycourse.get(row['level']) 383 384 def addEntry(self, obj, row, site): 385 parent = self.getParent(row, site) 386 obj.level = int(row['level']) 387 parent[row['level']] = obj 388 return 389 390 def checkConversion(self, row, mode='ignore'): 391 """Validates all values in row. 392 """ 393 converter = IObjectConverter(self.iface) 394 errs, inv_errs, conv_dict = converter.fromStringDict( 395 row, self.factory_name) 396 # We have to check if level is a valid integer. 397 # This is not by the converter. 398 try: 399 level = int(row['level']) 400 if level not in range(0,600,10): 401 errs.append(('level','no valid integer')) 402 except ValueError: 403 errs.append(('level','no integer')) 404 return errs, inv_errs, conv_dict -
main/waeup.sirp/trunk/src/waeup/sirp/students/studycourse.py
r7533 r7536 72 72 73 73 class StudentStudyCourseFactory(grok.GlobalUtility): 74 """A factory for student s.74 """A factory for student study courses. 75 75 """ 76 76 grok.implements(IFactory) -
main/waeup.sirp/trunk/src/waeup/sirp/students/studylevel.py
r7304 r7536 21 21 """ 22 22 import grok 23 from zope.component.interfaces import IFactory 23 24 from waeup.sirp.students.interfaces import ( 24 25 IStudentStudyLevel, IStudentNavigation, ICourseTicket) … … 58 59 StudentStudyLevel = attrs_to_fields(StudentStudyLevel) 59 60 61 class StudentStudyLevelFactory(grok.GlobalUtility): 62 """A factory for student study levels. 63 """ 64 grok.implements(IFactory) 65 grok.name(u'waeup.StudentStudyLevel') 66 title = u"Create a new student study level.", 67 description = u"This factory instantiates new student study level instances." 68 69 def __call__(self, *args, **kw): 70 return StudentStudyLevel() 71 72 def getInterfaces(self): 73 return implementedBy(StudentStudyLevel) 74 60 75 class CourseTicket(grok.Model): 61 76 """This is a course ticket which allows the -
main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_batching.py
r7534 r7536 31 31 from waeup.sirp.university.department import Department 32 32 from waeup.sirp.students.batching import ( 33 StudentProcessor, StudentStudyCourseProcessor) 33 StudentProcessor, StudentStudyCourseProcessor, 34 StudentStudyLevelProcessor) 34 35 from waeup.sirp.students.student import Student 35 36 from waeup.sirp.testing import FunctionalLayer, FunctionalTestCase … … 69 70 70 71 STUDENT_HEADER_FIELDS_MIGRATION = STUDENT_SAMPLE_DATA_MIGRATION.split( 72 '\n')[0].split(',') 73 74 STUDYLEVEL_SAMPLE_DATA = open( 75 os.path.join(os.path.dirname(__file__), 'sample_studylevel_data.csv'), 76 'rb').read() 77 78 STUDYLEVEL_HEADER_FIELDS = STUDYLEVEL_SAMPLE_DATA.split( 71 79 '\n')[0].split(',') 72 80 … … 212 220 shutil.rmtree(os.path.dirname(fin_file)) 213 221 222 214 223 class StudentStudyCourseImporterTest(FunctionalTestCase): 215 224 … … 218 227 def setUp(self): 219 228 super(StudentStudyCourseImporterTest, self).setUp() 229 self.dc_root = tempfile.mkdtemp() 230 self.workdir = tempfile.mkdtemp() 220 231 app = University() 221 self.dc_root = tempfile.mkdtemp()222 232 app['datacenter'].setStoragePath(self.dc_root) 223 224 233 self.getRootFolder()['app'] = app 225 234 self.app = self.getRootFolder()['app'] 226 235 setSite(app) 227 228 self.workdir = tempfile.mkdtemp()229 self.importer = StudentStudyCourseProcessor()230 self.csv_file = os.path.join(231 self.workdir, 'sample_studycourse_data.csv')232 open(self.csv_file, 'wb').write(STUDYCOURSE_SAMPLE_DATA)233 236 234 237 # Import students with subobjects … … 249 252 self.app['faculties']['fac1']['dep1'].certificates.addCertificate( 250 253 self.certificate) 254 255 self.importer = StudentStudyCourseProcessor() 256 self.csv_file = os.path.join( 257 self.workdir, 'sample_studycourse_data.csv') 258 open(self.csv_file, 'wb').write(STUDYCOURSE_SAMPLE_DATA) 251 259 return 252 260 … … 283 291 shutil.rmtree(os.path.dirname(fin_file)) 284 292 293 class StudentStudyLevelImporterTest(FunctionalTestCase): 294 295 layer = FunctionalLayer 296 297 def setUp(self): 298 super(StudentStudyLevelImporterTest, self).setUp() 299 self.dc_root = tempfile.mkdtemp() 300 self.workdir = tempfile.mkdtemp() 301 app = University() 302 app['datacenter'].setStoragePath(self.dc_root) 303 self.getRootFolder()['app'] = app 304 self.app = self.getRootFolder()['app'] 305 setSite(app) 306 307 # Import students with subobjects 308 student_file = os.path.join(self.workdir, 'sample_student_data.csv') 309 open(student_file, 'wb').write(STUDENT_SAMPLE_DATA) 310 num, num_warns, fin_file, fail_file = StudentProcessor().doImport( 311 student_file, STUDENT_HEADER_FIELDS) 312 shutil.rmtree(os.path.dirname(fin_file)) 313 314 # Populate university 315 self.certificate = createObject('waeup.Certificate') 316 self.certificate.code = 'CERT1' 317 self.certificate.application_category = 'basic' 318 self.certificate.start_level = 200 319 self.certificate.end_level = 500 320 self.app['faculties']['fac1'] = Faculty() 321 self.app['faculties']['fac1']['dep1'] = Department() 322 self.app['faculties']['fac1']['dep1'].certificates.addCertificate( 323 self.certificate) 324 325 # Update study courses 326 studycourse_file = os.path.join( 327 self.workdir, 'sample_studycourse_data.csv') 328 open(studycourse_file, 'wb').write(STUDYCOURSE_SAMPLE_DATA) 329 importer = StudentStudyCourseProcessor() 330 num, num_warns, fin_file, fail_file = importer.doImport( 331 studycourse_file, STUDYCOURSE_HEADER_FIELDS,'update') 332 shutil.rmtree(os.path.dirname(fin_file)) 333 334 self.importer = StudentStudyLevelProcessor() 335 self.csv_file = os.path.join( 336 self.workdir, 'sample_studylevel_data.csv') 337 open(self.csv_file, 'wb').write(STUDYLEVEL_SAMPLE_DATA) 338 339 def tearDown(self): 340 super(StudentStudyLevelImporterTest, self).tearDown() 341 shutil.rmtree(self.workdir) 342 shutil.rmtree(self.dc_root) 343 clearSite() 344 return 345 346 def test_interface(self): 347 # Make sure we fulfill the interface contracts. 348 assert verifyObject(IBatchProcessor, self.importer) is True 349 assert verifyClass( 350 IBatchProcessor, StudentStudyLevelProcessor) is True 351 352 def test_import(self): 353 num, num_warns, fin_file, fail_file = self.importer.doImport( 354 self.csv_file, STUDYLEVEL_HEADER_FIELDS,'create') 355 self.assertEqual(num_warns,2) 356 assert self.importer.entryExists( 357 dict(reg_number='1', level='100'), self.app) is True 358 studylevel = self.importer.getEntry( 359 dict(reg_number='1', level='100'), self.app) 360 self.assertEqual(studylevel.__parent__.certificate.code, u'CERT1') 361 self.assertEqual(studylevel.level_session, 2008) 362 self.assertEqual(studylevel.level_verdict, 'A') 363 self.assertEqual(studylevel.level, 100) 364 shutil.rmtree(os.path.dirname(fin_file)) 365 366 285 367 def test_suite(): 286 368 suite = unittest.TestSuite() 287 369 for testcase in [ 288 370 StudentImporterTest,StudentStudyCourseImporterTest, 289 ]:371 StudentStudyLevelImporterTest,]: 290 372 suite.addTest(unittest.TestLoader().loadTestsFromTestCase( 291 373 testcase … … 293 375 ) 294 376 return suite 377 378
Note: See TracChangeset for help on using the changeset viewer.