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 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]