def export_sections_enrollment(self, wb): self.task_progress.force('export_sections_enrollment', active=True) ws = wb.add_sheet("SectionEnrollment") row = 0 years = ISchoolYearContainer(self.context) total_years = len(years) for ny, year in enumerate( sorted(years.values(), key=lambda year: year.first)): total_terms = len(year) for nt, term in enumerate( sorted(year.values(), key=lambda term: term.first)): sections = ISectionContainer(term) total_sections = len(sections) for ns, section in enumerate( sorted(sections.values(), key=lambda section: section.__name__)): row = self.export_section_enrollment(ws, year, term, section, row=row) self.progress( 'export_sections_enrollment', normalized_progress( ny, total_years, nt, total_terms, ns, total_sections, )) self.finish('export_sections_enrollment')
def export_sections_enrollment(self, wb): self.task_progress.force('export_sections_enrollment', active=True) ws = wb.add_sheet("SectionEnrollment") row = 0 years = ISchoolYearContainer(self.context) total_years = len(years) for ny, year in enumerate(sorted(years.values(), key=lambda year: year.first)): total_terms = len(year) for nt, term in enumerate(sorted(year.values(), key=lambda term: term.first)): sections = ISectionContainer(term) total_sections = len(sections) for ns, section in enumerate(sorted(sections.values(), key=lambda section: section.__name__)): row = self.export_section_enrollment( ws, year, term, section, row=row) self.progress( 'export_sections_enrollment', normalized_progress( ny, total_years, nt, total_terms, ns, total_sections, )) self.finish('export_sections_enrollment')
def sections(self): if self.has_schoolyear: result = [] for term in self.schoolyear.values(): sections = ISectionContainer(term) result.extend(list(sections.values())) return result
def print_grades(self, ws, term_idx, total_terms): row = 1 sections = ISectionContainer(self.term).values() for ns, section in enumerate(sections): jd = ISectionJournalData(section, None) activities = IActivities(section) students = sorted(section.members, key=lambda s: s.username) if not students: self.write(ws, row, 0, section.__name__) row += 1 else: for nstud, student in enumerate(students): self.print_student(ws, row, section, jd, activities, student) row += 1 self.progress('worksheets', normalized_progress( term_idx, total_terms, ns, len(sections), nstud, len(students), )) self.progress('worksheets', normalized_progress( term_idx, total_terms, ns, len(sections), ))
def export_sections(self, wb): self.task_progress.force('export_sections', active=True) ws = wb.add_sheet("Sections") headers = [ "School Year", "Courses", "Term", "Section ID", "Previous ID", "Next ID", "Title", "Description", "Resources" ] for index, header in enumerate(headers): self.write_header(ws, 0, index, header) sections = [] for year in ISchoolYearContainer(self.context).values(): for term in year.values(): for section in ISectionContainer(term).values(): if not list(section.courses): continue courses = ', '.join([c.__name__ for c in section.courses]) sections.append((year, courses, term.first, term, section.__name__, section)) row = 1 sections.sort() n_sections = len(sections) for n, (year, courses, first, term, section_id, section) in enumerate(sections): self.format_section(year, courses, term, section, ws, row) self.progress('export_sections', normalized_progress(n, n_sections)) row += 1 self.finish('export_sections')
def deploy(self, course, term, template): # get the next index and title highest, title_index = 0, 0 template_title = self.alternate_title for sheet in self.deployed(course).values(): index = int(sheet.__name__[sheet.__name__.rfind('_') + 1:]) if index > highest: highest = index new_index = self.getNewIndex(sheet, template_title) if new_index > title_index: title_index = new_index root = IGradebookRoot(ISchoolToolApplication(None)) prefix = self.schoolyear.__name__ + '_' for sheet in root.deployed.values(): if sheet.__name__.startswith(prefix): new_index = self.getNewIndex(sheet, template_title) if new_index > title_index: title_index = new_index title = template_title if title_index: title += '-%s' % (title_index + 1) # copy worksheet template to the term or whole year if term: terms = [term] else: terms = self.schoolyear.values() for term in terms: deployedKey = 'course_%s_%s_%s' % (course.__name__, term.__name__, highest + 1) deployedWorksheet = Worksheet(title) self.deployed(course)[deployedKey] = deployedWorksheet copyActivities(removeSecurityProxy(template), deployedWorksheet) # now copy the template to all sections in the term sections = ISectionContainer(term) for section in sections.values(): if course not in section.courses: continue worksheetCopy = Worksheet(deployedWorksheet.title) worksheetCopy.deployed = True IActivities(section)[ deployedWorksheet.__name__] = worksheetCopy copyActivities(deployedWorksheet, worksheetCopy)
def createSection(self, term, course, instructor, periods, section_id=None, dry_run=True): """Create a section. `periods` is a list of tuples (day_id, period_id). A title is generated from the titles of `course` and `instructor`. If an existing section with the same title is found, it is used instead of creating a new one. The created section is returned, or None if dry_run is True. """ if dry_run: return None sections = ISectionContainer(term) section = Section() chooser = INameChooser(sections) auto_name = chooser.chooseName('', section) section.title = u"%s (%s)" % (course.title, auto_name) if section_id is None: section_id = auto_name sections[section_id] = section # Establish links to course and to teacher if course not in section.courses: section.courses.add(course) if instructor not in section.instructors: section.instructors.add(instructor) timetable_container = ITimetableContainer(self.schoolyear) timetables = [timetable_container[ttid] for ttid in sorted(periods)] schedules = IScheduleContainer(section) for timetable in timetables: selected = periods[timetable.__name__] schedule = SelectedPeriodsSchedule(timetable, term.first, term.last, title=timetable.title, timezone=timetable.timezone) for period in selected: schedule.addPeriod(period) schedules[timetable.__name__] = schedule return section
def export_section_timetables(self, wb): self.task_progress.force('export_section_timetables', active=True) ws = wb.add_sheet("SectionTimetables") year_sections = {} for year in ISchoolYearContainer(self.context).values(): sections = year_sections[year] = {} for term in year.values(): for section in ISectionContainer(term).values(): if not list(section.courses): continue timetables = [] for schedule in IScheduleContainer(section).values(): if schedule.timetable.__name__ is None: # LP: #1281335 continue parts = [schedule.timetable.__name__] if schedule.consecutive_periods_as_one: parts.append('yes') else: parts.append('no') for period in schedule.periods: day = period.__parent__ parts.append(day.title) parts.append(period.title) timetables.append(','.join(parts)) if not len(timetables): continue timetables = tuple(timetables) timetable_sections = sections.setdefault(timetables, []) timetable_sections.append( (term.first, term, section.__name__, section)) row = 0 for ny, (year, sections) in enumerate(sorted(year_sections.items())): for nt, (timetables, timetable_sections) in enumerate( sorted(sections.items())): row = self.format_timetable_sections(year, timetable_sections, ws, row) row = self.format_timetables_block(timetables, ws, row) self.progress( 'export_section_timetables', normalized_progress(ny, len(year_sections), nt, len(sections))) self.finish('export_section_timetables')
def handleSheet(self, sheet, index, visible): if index not in visible and not sheet.hidden: sheet.hidden = True elif index in visible and sheet.hidden: sheet.hidden = False else: return schoolyear = self.schoolyear for term in schoolyear.values(): deployedKey = 'course_%s_%s_%s' % (self.context.__name__, term.__name__, index) if sheet.__name__ == deployedKey: for section in ISectionContainer(term).values(): if self.context not in section.courses: continue activities = IActivities(section) activities[deployedKey].hidden = sheet.hidden return
def printYearSections(schoolyear, with_ids=False): def sectionName(term, section): return '%s in %s' % (translate(section.label), term.title) for term in listTerms(schoolyear): sections = ISectionContainer(term) for s_name in sorted(sections): print '*' * 50 section = sections[s_name] print sectionName(term, section) if with_ids: print ' ID:', section.__name__ s_next = section.next if s_next is not None: n_term = ITerm(s_next) print ' next:', sectionName(n_term, s_next) print ' students:' for member in sorted(section.members, key=lambda m: m.__name__): print ' ', member.title schedules = IScheduleContainer(section) for key in sorted(schedules): print_schedule(schedules[key])
def actualContext(self): current_term = getUtility(IDateManager).current_term if current_term is None: return ISchoolToolApplication(None) return ISectionContainer(current_term)
def importChunk(self, rows, line, dry_run=True): """Import a chunk of data that describes a section. You should run this method with dry_run=True before trying the real thing, or you might get in trouble. """ terms = self.listTerms() row = rows[0] if len(row) not in (2, 2 + len(terms)): err_msg = _( 'Wrong section header on line ${line_no} (it should contain a' ' course id, an instructor id and optional SchoolTool ' 'section IDs for each of the terms)', mapping={'line_no': line}) return section_ids = None if len(row) == 2: course_id, instructor_id = row[:2] else: course_id = row[0] instructor_id = row[1] section_ids = row[2:] course = ICourseContainer(self.schoolyear).get(course_id, None) if course is None: self.errors.courses.append(course_id) instructor = self.persons.get(instructor_id, None) if instructor is None: self.errors.persons.append(instructor_id) line_ofs = 1 finished = False timetables = ITimetableContainer(self.schoolyear) timetable = None periods = {} for row in rows[1:]: line_ofs += 1 if row == ['***']: finished = True break if len(row) == 1: tt = timetables.get(row[0]) if tt is None: err_msg = _( "Malformed line ${line_no}" " (it should contain either a timetable id or" " day id and a period id)", mapping={'line_no': line + line_ofs - 1}) self.errors.generic.append(err_msg) continue timetable = tt continue elif len(row) == 2: day_id, period_id = row else: err_msg = _( "Malformed line ${line_no}" " (it should contain either a timetable id or" " day id and a period id)", mapping={'line_no': line + line_ofs - 1}) self.errors.generic.append(err_msg) continue if timetable is None: err_msg = _( "Timetable id must be specified before" " day id and a period id" " at at line ${line_no}", mapping={'line_no': line + line_ofs - 1}) continue # check day_id ttday = None for day in timetable.periods.templates.values(): if day.title == day_id: ttday = day break if ttday is None: errkey = (timetable.__name__, day_id) if errkey not in self.errors.day_ids: self.errors.day_ids.append(errkey) continue ttperiod = None for period in ttday.values(): if period.title == period_id: ttperiod = period break # check period_id if ttperiod is None: errkey = (timetable.__name__, day_id, period_id) if period_id not in self.errors.periods: self.errors.periods.append(errkey) continue if timetable.__name__ not in periods: periods[timetable.__name__] = [] periods[timetable.__name__].append(period) if not finished: err_msg = _("Incomplete section description on line ${line}", mapping={'line': line}) self.errors.generic.append(err_msg) return if len(rows) == line_ofs: err_msg = _("No students in section (line ${line})", mapping={'line': line + line_ofs}) self.errors.generic.append(err_msg) return sections = [] for n, term in enumerate(terms): section_container = ISectionContainer(term) section_id = None if section_ids is not None: section_id = section_ids[n] if (section_id is not None and section_id in section_container): section = section_container[section_id] self.updateSection(section, term, course, instructor, periods, dry_run=dry_run) else: section = self.createSection(term, course, instructor, periods, section_id=section_id, dry_run=dry_run) self.importPersons(rows[line_ofs:], section, dry_run=dry_run) if section is not None: sections.append(section) if not self.errors.anyErrors(): for n, section in enumerate(sections[:-1]): section.next = sections[n + 1]
def setUpSections(term_list, sections_per_term=1): for term in term_list: sections = ISectionContainer(term) for n in range(sections_per_term): name = 'Sec%d'%(n+1) sections[name] = Section(name)