diff options
Diffstat (limited to 'management')
| -rw-r--r-- | management/commands/_private.py | 32 | ||||
| -rw-r--r-- | management/commands/timetables.py | 64 | 
2 files changed, 62 insertions, 34 deletions
| diff --git a/management/commands/_private.py b/management/commands/_private.py index 8767aa8..65772a4 100644 --- a/management/commands/_private.py +++ b/management/commands/_private.py @@ -14,15 +14,21 @@ class Week:      def get_day(self, id):          return self.start + datetime.timedelta(id) +    @property +    def year(self): +        return self.start.year +  def add_time(date, time):      delta = datetime.timedelta(hours=time.hour, minutes=time.minute)      return date + delta -def delete_courses_in_week(year, week): -    start = timezone.make_aware(datetime.datetime.strptime("{0}-W{1:02d}-1".format(year, week), "%Y-W%W-%w")) +def delete_courses_in_week(timetable, year, week): +    start = timezone.make_aware(datetime.datetime.strptime( +        "{0}-W{1:02d}-1".format(year, week), "%Y-W%W-%w"))      end = start + datetime.timedelta(weeks=1) -    Course.objects.filter(begin__gte=start, begin__lt=end).delete() +    Course.objects.filter(begin__gte=start, begin__lt=end, +                          timetable=timetable).delete()  def get_from_db_or_create(cls, name, timetable=None):      obj = cls.objects.all().filter(name=name) @@ -37,7 +43,7 @@ def get_from_db_or_create(cls, name, timetable=None):      return obj -def get_events(soup, weeks, week, timetable): +def get_events(soup, weeks, year, week, timetable):      for event in soup.find_all("event"):          title = None          type_ = None @@ -45,12 +51,19 @@ def get_events(soup, weeks, week, timetable):          rooms = None          notes = None -        if weeks[event.rawweeks.text].number == week and event.resources.group is not None and event.starttime is not None and event.endtime is not None: +        if weeks[event.rawweeks.text].number == week and \ +           weeks[event.rawweeks.text].year == year and \ +           event.resources.group is not None and \ +           event.starttime is not None and event.endtime is not None:              date = weeks[event.rawweeks.text].get_day(int(event.day.text)) -            begin = add_time(date, datetime.datetime.strptime(event.starttime.text, "%H:%M")) -            end = add_time(date, datetime.datetime.strptime(event.endtime.text, "%H:%M")) -            groups = [get_from_db_or_create(Group, item.text, timetable) for item in event.resources.group.find_all("item")] +            begin = add_time(date, datetime.datetime.strptime( +                event.starttime.text, "%H:%M")) +            end = add_time(date, datetime.datetime.strptime( +                event.endtime.text, "%H:%M")) + +            groups = [get_from_db_or_create(Group, item.text, timetable) +                      for item in event.resources.group.find_all("item")]              if event.notes is not None:                  notes = event.notes.text @@ -67,7 +80,8 @@ def get_events(soup, weeks, week, timetable):                  type_ = event.category.text              if event.resources.room is not None: -                rooms = [get_from_db_or_create(Room, item.text) for item in event.resources.room.find_all("item")] +                rooms = [get_from_db_or_create(Room, item.text) +                         for item in event.resources.room.find_all("item")]              yield title, type_, groups, rooms, notes, begin, end diff --git a/management/commands/timetables.py b/management/commands/timetables.py index 37a5201..9882759 100644 --- a/management/commands/timetables.py +++ b/management/commands/timetables.py @@ -10,43 +10,57 @@ from ._private import delete_courses_in_week, get_events, get_weeks, get_xml, We  import datetime  import requests +@transaction.atomic +def process_timetable_week(timetable, year, week, soup, weeks_in_soup): +    delete_courses_in_week(timetable, year, week) +    for name, type_, groups, rooms, notes, begin, end in get_events(soup, weeks_in_soup, year, week, timetable): +        course = Course.objects.create(timetable=timetable, begin=begin, end=end) +        course.name = name +        course.type = type_ +        course.notes = notes + +        course.groups.add(*groups) +        if rooms is not None: +            course.rooms.add(*rooms) + +        course.save() + +def process_timetable(timetable, year, weeks): +    soup = get_xml(timetable.url) +    weeks_in_soup = get_weeks(soup) + +    for week in weeks: +        process_timetable_week(timetable, year, week, soup, weeks_in_soup) +  class Command(BaseCommand):      help = "Fetches registered celcat timetables"      def add_arguments(self, parser):          parser.add_argument("--week", type=int, choices=range(1, 54), nargs="+") +        parser.add_argument("--year", type=int, nargs=1) -    def __get_weeks(self, weeks): -        if weeks is None: -            year, week, day = timezone.now().isocalendar() +    def handle(self, *args, **options): +        year = None +        if options["week"] is None: +            _, week, day = timezone.now().isocalendar()              if day >= 6:                  year, week, _ = (timezone.now() + datetime.timedelta(weeks=1)).isocalendar() - -            yield year, week +            weeks = [week]          else: -            year = timezone.now().year -            for week in weeks: -                yield year, week - -    @transaction.atomic -    def handle(self, *args, **options): -        for year, week in self.__get_weeks(options["week"]): -            delete_courses_in_week(year, week) - -            for timetable in Timetable.objects.all(): -                self.stdout.write("Processing {0}, week {1}".format(timetable, week)) +            weeks = options["week"] -                soup = get_xml(timetable.url) -                weeks = get_weeks(soup) - -                for name, type_, groups, rooms, notes, begin, end in get_events(soup, weeks, week, timetable): -                    course = Course.objects.create(name=name, type=type_, notes=notes, timetable=timetable, begin=begin, end=end) +        if options["year"] is None and year is None: +            year = timezone.now().year +        else: +            year = options["year"][0] -                    course.groups.add(*groups) -                    if rooms is not None: -                        course.rooms.add(*rooms) +        for timetable in Timetable.objects.all(): +            self.stdout.write("Processing {0}".format(timetable)) -                    course.save() +            try: +                process_timetable(timetable, year, weeks) +            except Exception as e: +                self.stderr.write(self.style.error("Failed to process {0}: {1}".format(timetable, e)))          self.stdout.write(self.style.SUCCESS("Done.")) | 
