diff options
-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.")) |