aboutsummaryrefslogtreecommitdiff
path: root/management/commands/timetables.py
diff options
context:
space:
mode:
authorAlban Gruin2018-04-25 21:18:25 +0200
committerAlban Gruin2018-04-25 21:18:25 +0200
commit1789cbf1dcf555b35785e47237fb0a1f95720a45 (patch)
treee1645a307ee790bdd50751c8bde5694890e0257b /management/commands/timetables.py
parent81046d1e44380fd961efbc308a85d134f33d2bab (diff)
parent4c82869e3a590c982c43958e3e4b0f9fad440678 (diff)
Merge branch 'futur'
Diffstat (limited to 'management/commands/timetables.py')
-rw-r--r--management/commands/timetables.py94
1 files changed, 55 insertions, 39 deletions
diff --git a/management/commands/timetables.py b/management/commands/timetables.py
index ff00c8f..f92ad4e 100644
--- a/management/commands/timetables.py
+++ b/management/commands/timetables.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 Alban Gruin
+# Copyright (C) 2017-2018 Alban Gruin
#
# celcatsanitizer is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
@@ -20,12 +20,16 @@ from django.core.management.base import BaseCommand
from django.db import transaction
from django.db.models import Min
-from edt.models import Course, Timetable
-from edt.utils import get_week, tz_now
-from ._private import delete_courses_in_week, get_events, get_update_date, get_weeks, get_xml
+from ...models import Course, Source
+from ...utils import get_week, tz_now
+
+from ._private import delete_courses_in_week, get_events, get_update_date, \
+ get_weeks, get_xml
+
@transaction.atomic
-def process_timetable_week(timetable, soup, weeks_in_soup, force, year=None, week=None):
+def process_timetable_week(source, soup, weeks_in_soup, force,
+ year=None, week=None):
if year is not None and week is not None:
begin, end = get_week(year, week)
@@ -40,75 +44,83 @@ def process_timetable_week(timetable, soup, weeks_in_soup, force, year=None, wee
else:
today = tz_now()
- # On récupère la mise à jour la plus ancienne dans les cours de l’emploi du temps
- last_update_date = Course.objects.filter(timetable=timetable)
+ # On récupère la mise à jour la plus ancienne dans les cours de
+ # l’emploi du temps
+ last_update_date = Course.objects.filter(source=source)
if today is not None:
- # Cette date concerne les éléments commençant à partir d’aujourd’hui si la valeur
- # n’est pas nulle.
+ # Cette date concerne les éléments commençant à partir
+ # d’aujourd’hui si la valeur n’est pas nulle.
last_update_date = last_update_date.filter(begin__gte=today)
if year is not None and week is not None:
- # Si jamais on traite une semaine spécifique, on limite les cours sélectionnés
- # à ceux qui commencent entre le début du traitement et la fin de la semaine
+ # Si jamais on traite une semaine spécifique, on limite les
+ # cours sélectionnés à ceux qui commencent entre le début du
+ # traitement et la fin de la semaine
last_update_date = last_update_date.filter(begin__lt=end)
- last_update_date = last_update_date.aggregate(Min("last_update")) \
- ["last_update__min"]
+ last_update_date = last_update_date.aggregate(
+ Min("last_update"))["last_update__min"]
# Date de mise à jour de Celcat, utilisée à des fins de statistiques
new_update_date = get_update_date(soup)
- # On ne fait pas la mise à jour si jamais la dernière date de MàJ est plus récente
- # que celle indiquée par Celcat.
- # Attention, le champ last_update de la classe Course représente l’heure à laquelle
- # le cours a été inséré dans la base de données, et non pas la date indiquée par
- # Celcat.
- if not force and last_update_date is not None and new_update_date is not None and \
- last_update_date >= new_update_date:
+ # On ne fait pas la mise à jour si jamais la dernière date de MàJ
+ # est plus récente que celle indiquée par Celcat. Attention, le
+ # champ last_update de la classe Course représente l’heure à
+ # laquelle le cours a été inséré dans la base de données, et non
+ # pas la date indiquée par Celcat.
+ if not force and last_update_date is not None and \
+ new_update_date is not None and last_update_date >= new_update_date:
return
if year is not None and week is not None:
# On efface la semaine à partir de maintenant si jamais
# on demande le traitement d’une seule semaine
- delete_courses_in_week(timetable, year, week, today)
+ delete_courses_in_week(source, year, week, today)
else:
# Sinon, on efface tous les cours à partir de maintenant.
# Précisément, on prend la plus grande valeur entre la première semaine
# présente dans Celcat et maintenant.
delete_from = min(weeks_in_soup.values())
if not force:
- # Si jamais on force la MàJ, on efface tout à partir de la première semaine
+ # Si jamais on force la MàJ, on efface tout à partir de la
+ # première semaine
delete_from = max(delete_from, today)
- Course.objects.filter(timetable=timetable, begin__gte=delete_from).delete()
+ Course.objects.filter(source=source, begin__gte=delete_from).delete()
# Tous les cours commençant sur la période traitée
# sont parsés, puis enregistrés dans la base de données.
- for course in get_events(timetable, soup, weeks_in_soup, today, year, week):
+ for course in get_events(source, soup, weeks_in_soup, today, year, week):
course.save()
# On renseigne la date de mise à jour de Celcat, à des fins de statistiques
- timetable.last_update_date = new_update_date
- timetable.save()
+ source.last_update_date = new_update_date
+ source.save()
+
-def process_timetable(timetable, force, year=None, weeks=None):
- soup = get_xml(timetable.url)
+def process_timetable(source, force, year=None, weeks=None):
+ soup = get_xml(source.url)
weeks_in_soup = get_weeks(soup)
if year is not None and weeks is not None:
for week in weeks:
- process_timetable_week(timetable, soup, weeks_in_soup, force, year, week)
+ process_timetable_week(source, soup, weeks_in_soup, force,
+ year, week)
else:
- process_timetable_week(timetable, soup, weeks_in_soup, force)
+ process_timetable_week(source, soup, weeks_in_soup, force)
class Command(BaseCommand):
help = "Fetches registered celcat timetables"
def add_arguments(self, parser):
- parser.add_argument("--all", const=True, default=False, action="store_const")
- parser.add_argument("--force", const=True, default=False, action="store_const")
- parser.add_argument("--week", type=int, choices=range(1, 54), nargs="+")
+ parser.add_argument("--all", const=True, default=False,
+ action="store_const")
+ parser.add_argument("--force", const=True, default=False,
+ action="store_const")
+ parser.add_argument("--week", type=int, choices=range(1, 54),
+ nargs="+")
parser.add_argument("--year", type=int, nargs=1)
def handle(self, *args, **options):
@@ -120,7 +132,8 @@ class Command(BaseCommand):
elif options["week"] is None:
_, week, day = tz_now().isocalendar()
if day >= 6:
- year, week, _ = (tz_now() + datetime.timedelta(weeks=1)).isocalendar()
+ year, week, _ = (tz_now() + datetime.timedelta(weeks=1)) \
+ .isocalendar()
weeks = [week]
else:
weeks = options["week"]
@@ -131,16 +144,18 @@ class Command(BaseCommand):
elif year is None:
year = options["year"][0]
- for timetable in Timetable.objects.all():
- self.stdout.write("Processing {0}".format(timetable))
+ for source in Source.objects.all():
+ self.stdout.write("Processing {0}".format(
+ source.formatted_timetables))
try:
- process_timetable(timetable, options["force"], year, weeks)
+ process_timetable(source, options["force"], year, weeks)
except KeyboardInterrupt:
break
except Exception:
self.stderr.write(
- self.style.ERROR("Failed to process {0}:".format(timetable))
+ self.style.ERROR("Failed to process {0}:".format(
+ source.formatted_timetables))
)
self.stderr.write(self.style.ERROR(traceback.format_exc()))
errcount += 1
@@ -148,4 +163,5 @@ class Command(BaseCommand):
if errcount == 0:
self.stdout.write(self.style.SUCCESS("Done."))
else:
- self.stdout.write(self.style.ERROR("Done with {0} errors.".format(errcount)))
+ self.stdout.write(self.style.ERROR("Done with {0} errors.".format(
+ errcount)))