aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/index.rst1
-rw-r--r--Documentation/usage/commands/printvalues.rst48
-rw-r--r--admin.py14
-rw-r--r--management/commands/__parsercommand.py26
-rw-r--r--management/commands/printvalues.py45
-rw-r--r--management/commands/timetables.py16
-rw-r--r--management/parsers/ups2018.py14
-rw-r--r--models.py17
-rw-r--r--templates/index.html2
-rw-r--r--templates/mention_list.html2
-rw-r--r--tests.py341
-rw-r--r--tests/data/2018/empty.html50
-rw-r--r--tests/data/2018/october.html50
-rw-r--r--tests/data/2018/september.html51
14 files changed, 642 insertions, 35 deletions
diff --git a/Documentation/index.rst b/Documentation/index.rst
index e8dd4f2..7073b0d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -61,6 +61,7 @@ Utilisation de celcatsanitizer
usage/installation
usage/commands/cleancourses
usage/commands/listtimetables
+ usage/commands/printvalues
usage/commands/reparse
usage/commands/timetables
usage/rest
diff --git a/Documentation/usage/commands/printvalues.rst b/Documentation/usage/commands/printvalues.rst
new file mode 100644
index 0000000..7d53d44
--- /dev/null
+++ b/Documentation/usage/commands/printvalues.rst
@@ -0,0 +1,48 @@
+===============
+``printvalues``
+===============
+
+``printvalues`` affiche le contenu brut d’un ou plusieurs cours, sans
+chercher à interpréter son contenu ou à l’enregistrer dans la base de
+données.
+
+Utilisation
+===========
+.. code:: shell
+
+ $ ./manage.py printvalues --source id [--limit nb]
+
+``--source`` permet de spécifier la source depuis laquelle les cours
+doivent être récupérés. ``id`` correspond à l’ID de la source,
+trouvable à l’aide de la commande :doc:`listtimetables`.
+
+``--limit`` permet de limiter le nombre de cours affichés. ``nb``
+correspond au nombre maximum de cours affichés.
+
+Format de sortie
+================
+::
+
+ {
+ "backColor": "#7D4F72",
+ "clickDisabled": true,
+ "doubleClickDisabled": true,
+ "end": "2019-01-28T09:45:00",
+ "html": "<div style=\"color:White \">(07:45-09:45)<br>COURS/TD<br>ELINF6Q1 - BIOLOGIE<br>L3 INFO s2 CMA<br>U3-307</div>",
+ "id": "76330023",
+ "moveDisabled": true,
+ "resizeDisabled": true,
+ "sort": [],
+ "start": "2019-01-28T07:45:00",
+ "tag": [
+ "celcat",
+ "sat_notvalid",
+ "1",
+ "reg_notmark",
+ "ELINF6Q1",
+ "7491453"
+ ],
+ "text": "(07:45-09:45)<br>COURS/TD<br>ELINF6Q1 - BIOLOGIE<br>L3 INFO s2 CMA<br>U3-307",
+ "toolTip": "(07:45-09:45)<br>COURS/TD<br>ELINF6Q1 - BIOLOGIE<br>L3 INFO s2 CMA<br>U3-307"
+ }
+ Done.
diff --git a/admin.py b/admin.py
index 0dc7987..5350aad 100644
--- a/admin.py
+++ b/admin.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Alban Gruin
+# Copyright (C) 2017-2019 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
@@ -14,7 +14,7 @@
# along with celcatsanitizer. If not, see <http://www.gnu.org/licenses/>.
from django.contrib import admin
-from .models import Course, Group, Room, Source, Timetable, Year
+from .models import Course, Group, Module, Room, Source, Timetable, Year
def make_hidden(modeladmin, request, queryset):
@@ -62,7 +62,7 @@ class GroupAdmin(admin.ModelAdmin):
actions = (make_hidden, make_visible,)
-@admin.register(Room)
+@admin.register(Room, Module)
class RoomAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("name",)}
list_display = ("name",)
@@ -72,10 +72,12 @@ class RoomAdmin(admin.ModelAdmin):
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
fieldsets = (
- (None, {"fields": ("name", "type", "source", "groups", "rooms",
- "last_update",)}),
+ (None, {"fields": ("name", "type", "source", "groups", "rooms",)}),
("Horaires", {"fields": ("begin", "end",)}),
- ("Remarques", {"fields": ("notes",)}),)
+ ("Remarques", {"fields": ("notes",)}),
+ ("Avancé", {"fields": ("celcat_id", "last_update",),
+ "classes": ("collapse",)}),)
list_display = ("name", "type", "source", "begin", "end",)
list_filter = ("type", "source__timetables", "groups",)
ordering = ("begin",)
+ readonly_fields = ("celcat_id", "last_update",)
diff --git a/management/commands/__parsercommand.py b/management/commands/__parsercommand.py
new file mode 100644
index 0000000..99480cc
--- /dev/null
+++ b/management/commands/__parsercommand.py
@@ -0,0 +1,26 @@
+# Copyright (C) 2019 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
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# celcatsanitizer is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with celcatsanitizer. If not, see <http://www.gnu.org/licenses/>.
+
+from importlib import import_module
+
+from django.conf import settings
+
+DEFAULT_PARSER = "edt.management.parsers.ups2017"
+
+
+class ParserCommand:
+ def get_parser(self):
+ parser_module = getattr(settings, "CS_PARSER", DEFAULT_PARSER)
+ return getattr(import_module(parser_module), "Parser")
diff --git a/management/commands/printvalues.py b/management/commands/printvalues.py
new file mode 100644
index 0000000..91dd18b
--- /dev/null
+++ b/management/commands/printvalues.py
@@ -0,0 +1,45 @@
+# Copyright (C) 2019 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
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# celcatsanitizer is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with celcatsanitizer. If not, see <http://www.gnu.org/licenses/>.
+
+from django.core.management.base import BaseCommand
+
+from ...models import Source
+from .__parsercommand import ParserCommand
+
+import json
+
+
+class Command(BaseCommand, ParserCommand):
+ help = "List values from courses from a source"
+
+ def add_arguments(self, parser):
+ parser.add_argument("--source", type=int, nargs=1, required=True)
+ parser.add_argument("--limit", type=int, nargs=1)
+
+ def handle(self, *args, **options):
+ source = Source.objects.get(pk=options["source"][0])
+ parser = self.get_parser()(source)
+ events = [event for month in parser.get_source() for event in month]
+
+ i = 0
+ limit = len(events)
+ if options["limit"] is not None:
+ limit = min(options["limit"][0], limit)
+
+ while i < limit:
+ self.stdout.write(json.dumps(events[i], indent=4, sort_keys=True))
+ i += 1
+
+ self.stdout.write(self.style.SUCCESS("Done."))
diff --git a/management/commands/timetables.py b/management/commands/timetables.py
index ee33f7e..f71accf 100644
--- a/management/commands/timetables.py
+++ b/management/commands/timetables.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Alban Gruin
+# Copyright (C) 2017-2019 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
@@ -13,20 +13,16 @@
# You should have received a copy of the GNU Affero General Public License
# along with celcatsanitizer. If not, see <http://www.gnu.org/licenses/>.
-from importlib import import_module
-
import datetime
import traceback
-from django.conf import settings
from django.core.management.base import BaseCommand
from django.db import transaction
from django.db.models import Min
from ...models import Course, Source
from ...utils import get_week, tz_now
-
-DEFAULT_PARSER = "edt.management.parsers.ups2017"
+from .__parsercommand import ParserCommand
def delete_courses_in_week(source, year, week, today):
@@ -122,7 +118,7 @@ def process_timetable(source, force, parser_cls, year=None, weeks=None):
process_timetable_week(source, force, parser)
-class Command(BaseCommand):
+class Command(BaseCommand, ParserCommand):
help = "Fetches registered celcat timetables"
def add_arguments(self, parser):
@@ -134,14 +130,10 @@ class Command(BaseCommand):
nargs="+")
parser.add_argument("--year", type=int, nargs=1)
- def __get_parser(self):
- parser_module = getattr(settings, "CS_PARSER", DEFAULT_PARSER)
- return getattr(import_module(parser_module), "Parser")
-
def handle(self, *args, **options):
year = None
errcount = 0
- parser = self.__get_parser()
+ parser = self.get_parser()
if options["all"]:
weeks = None
diff --git a/management/parsers/ups2018.py b/management/parsers/ups2018.py
index f1da5bf..afbfc4b 100644
--- a/management/parsers/ups2018.py
+++ b/management/parsers/ups2018.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2018 Alban Gruin
+# Copyright (C) 2018-2019 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
@@ -26,7 +26,7 @@ from django.utils import timezone
import lxml.html
import requests
-from ...models import Course, Group, Room
+from ...models import Course, Group, Module, Room
from ...utils import get_current_week, get_week
from .abstractparser import AbstractParser, ParserError
@@ -114,7 +114,8 @@ class Parser(AbstractParser):
return
course = Course.objects.create(
- source=self.source, begin=begin, end=end
+ source=self.source, begin=begin, end=end,
+ celcat_id=int(event["id"])
)
min_i = 0
@@ -136,6 +137,13 @@ class Parser(AbstractParser):
# par un dictionnaire classique.
names = OrderedDict.fromkeys(data[i - 1].split(';'))
course.name = ", ".join(names.keys())
+
+ module_names = [t for t in event["tag"]
+ if len(t) > 0 and
+ any(n.startswith(t) for n in names.keys())]
+ if len(module_names) > 0:
+ module, _ = Module.objects.get_or_create(name=module_names[0])
+ course.module = module
else:
course.name = "Sans nom"
if i - 2 >= min_i:
diff --git a/models.py b/models.py
index c8e7b3d..b59f2d8 100644
--- a/models.py
+++ b/models.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Alban Gruin
+# Copyright (C) 2017-2019 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
@@ -200,6 +200,18 @@ class Room(SlugModel):
verbose_name_plural = "salles"
+class Module(SlugModel):
+ name = models.CharField(max_length=255, unique=True, verbose_name="nom")
+ slug = models.SlugField(max_length=64, default="", unique=True)
+
+ def __str__(self):
+ return self.name
+
+ class Meta:
+ verbose_name = "module"
+ verbose_name_plural = "modules"
+
+
class CourseManager(Manager):
def get_courses(self, obj, **criteria):
qs = self.get_queryset()
@@ -246,6 +258,9 @@ class Course(models.Model):
last_update = models.DateTimeField(verbose_name="dernière mise à jour",
default=timezone.now)
+ celcat_id = models.IntegerField(verbose_name="ID Celcat", null=True)
+ module = models.ForeignKey(Module, on_delete=models.SET_NULL, null=True)
+
def __str__(self):
return self.name
diff --git a/templates/index.html b/templates/index.html
index e86038e..53cefd5 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -25,7 +25,7 @@
{% endblock %}
</div>
<footer>
- <p>(c) 2018 &ndash; Alban Gruin &ndash; <a href="{% url "django.contrib.flatpages.views.flatpage" url="contact/" %}">contacter</a> &ndash; celcatsanitizer {{ celcatsanitizer_version }} &ndash; <a href="{% url "django.contrib.flatpages.views.flatpage" url="a-propos/" %}">à propos</a><br />
+ <p>(c) 2019 &ndash; Alban Gruin &ndash; <a href="{% url "django.contrib.flatpages.views.flatpage" url="contact/" %}">contacter</a> &ndash; celcatsanitizer {{ celcatsanitizer_version }} &ndash; <a href="{% url "django.contrib.flatpages.views.flatpage" url="a-propos/" %}">à propos</a><br />
Design inspiré par <a href="https://bestmotherfucking.website/">https://bestmotherfucking.website/</a></p>
</footer>
</body>
diff --git a/templates/mention_list.html b/templates/mention_list.html
index 3b9d8e8..08d3d4a 100644
--- a/templates/mention_list.html
+++ b/templates/mention_list.html
@@ -1,6 +1,6 @@
{% extends "index.html" %}
{% block title %}{{ year }} &ndash; {% endblock %}
-{% block pagetitle %}{{ year }} &ndash; Choississez votre mention{% endblock %}
+{% block pagetitle %}{{ year }} &ndash; Choisissez votre mention{% endblock %}
{% block url %}{% url "groups" year.slug element.slug %}{% endblock %}
{% block navigation %}<a href="{% url "index" %}">Retour à la liste des années</a>{% endblock %}
diff --git a/tests.py b/tests.py
index 2568688..b411db3 100644
--- a/tests.py
+++ b/tests.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2017-2018 Alban Gruin
+# Copyright (C) 2017-2019 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
@@ -13,13 +13,46 @@
# You should have received a copy of the GNU Affero General Public License
# along with celcatsanitizer. If not, see <http://www.gnu.org/licenses/>.
+from unittest import mock
+
from django.test import TestCase
from django.utils import timezone
-from .models import Course, Group, Room, Source, Timetable, Year
+from .management.parsers.abstractparser import ParserError
+from .management.parsers.ups2018 import Parser as UPS2018Parser
+from .models import Course, Group, Module, Room, Source, Timetable, Year
+from .templatetags.rooms import format_rooms
from .utils import tz_now
import datetime
+import os
+
+
+def mock_requests_get(*args, **kwargs):
+ class MockedResponse:
+ def __init__(self, content=""):
+ self.encoding = "utf-8"
+ self.content = content
+ self.status = 200
+
+ def raise_for_status(self):
+ return
+
+ def mocked_response_from_file(filename):
+ module_dir = os.path.dirname(__file__)
+ filepath = os.path.join(module_dir, filename)
+ with open(filepath, "r") as response:
+ return MockedResponse(response.read())
+
+ if args[0] == "https://example.org/2018":
+ if "params" not in kwargs or not kwargs["params"]:
+ return mocked_response_from_file("tests/data/2018/september.html")
+ elif kwargs["params"].get("Date") == "20181001":
+ return mocked_response_from_file("tests/data/2018/october.html")
+ else:
+ return mocked_response_from_file("tests/data/2018/empty.html")
+
+ return MockedResponse("<html></html>")
class CourseTestCase(TestCase):
@@ -51,7 +84,7 @@ class CourseTestCase(TestCase):
for group in (cma, tda2, self.tpa21, cmb, tdb2, self.tpb21,):
course = Course.objects.create(
name="{0} course".format(group.name), type="cours",
- source=source, begin=dt, end=dt)
+ source=source, begin=dt, end=dt, celcat_id=0)
course.groups.add(group)
def test_get_courses_for_group(self):
@@ -300,13 +333,13 @@ class RoomTestCase(TestCase):
group = Group.objects.create(celcat_name="L1 info s2 CMA",
source=self.source)
- self.rooms = [Room.objects.create(name="0"),
- Room.objects.create(name="1"),
- Room.objects.create(name="2"),
- Room.objects.create(name="3"),
- Room.objects.create(name="4"),
- Room.objects.create(name="5"),
- Room.objects.create(name="6")]
+ self.rooms = [
+ Room.objects.create(name=str(i))
+ for i in range(5)
+ ] + [
+ Room.objects.create(name="Amphi {}".format(i))
+ for i in range(5, 7)
+ ]
hours = [({"begin": datetime.time(hour=14, minute=0)},),
({"begin": datetime.time(hour=16, minute=0)},),
@@ -326,10 +359,28 @@ class RoomTestCase(TestCase):
end = begin + datetime.timedelta(hours=rn.get("duration", 2))
course = Course.objects.create(source=self.source,
- begin=begin, end=end)
+ begin=begin, end=end,
+ celcat_id=0)
course.groups.add(group)
course.rooms.add(room)
+ def test_format(self):
+ amphis = self.rooms[-2:]
+
+ self.assertEqual(format_rooms([]), "")
+ self.assertEqual(format_rooms(self.rooms[:1]), "Salle 0")
+ self.assertEqual(format_rooms(self.rooms[:2]), "Salles 0, 1")
+ self.assertEqual(format_rooms([amphis[0]]), "Amphi 5")
+ self.assertEqual(format_rooms(amphis), "Amphi 5, Amphi 6")
+ self.assertEqual(format_rooms([amphis[0]] + self.rooms[:1]),
+ "Amphi 5, salle 0")
+ self.assertEqual(format_rooms([amphis[0]] + self.rooms[:2]),
+ "Amphi 5, salles 0, 1")
+ self.assertEqual(format_rooms(amphis + self.rooms[:1]),
+ "Amphi 5, Amphi 6, salle 0")
+ self.assertEqual(format_rooms(amphis + self.rooms[:2]),
+ "Amphi 5, Amphi 6, salles 0, 1")
+
def test_qsjps(self):
begin = timezone.make_aware(datetime.datetime.combine(
self.day, datetime.time(hour=15, minute=0)))
@@ -345,3 +396,271 @@ class RoomTestCase(TestCase):
self.assertNotIn(self.rooms[4], rooms)
self.assertIn(self.rooms[5], rooms)
self.assertIn(self.rooms[6], rooms)
+
+
+class UPS2018ParserTestCase(TestCase):
+ @mock.patch("requests.get", side_effect=mock_requests_get)
+ def setUp(self, *args, **kwargs):
+ source = Source.objects.create(url="https://example.org/2018")
+ self.room = Room.objects.create(name="Salle quelconque")
+ self.room2 = Room.objects.create(name="Salle quelconque 2")
+
+ self.group = Group(celcat_name="L3 Info s1 CMA")
+ self.group.source = source
+ self.group.save()
+
+ self.parser = UPS2018Parser(source)
+
+ def test_get_event(self):
+ get_event = self.parser._Parser__get_event
+ count = Course.objects.count()
+ module_count = Module.objects.count()
+
+ event = get_event(
+ {"start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00",
+ "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque;AAA"
+ "<br>L3 Info s1 CMA;L3 Info s1 TDA2<br>"
+ "Salle quelconque;Salle quelconque 2<br>Commentaire", "id": "0",
+ "tag": ["abc", "def", "AAA"]},
+ timezone.make_aware(datetime.datetime(2018, 9, 21)),
+ timezone.make_aware(datetime.datetime(2018, 9, 1)),
+ timezone.make_aware(datetime.datetime(2018, 10, 1)),
+ 2018, 38)
+
+ ngroup = Group.objects.filter(name="L3 Info s1 TDA2").first()
+ self.assertIsNotNone(ngroup)
+
+ self.assertEqual(event.name, "Cours quelconque, AAA")
+ self.assertEqual(event.type, "COURS/TD")
+ self.assertIn(self.group, event.groups.all())
+ self.assertIn(ngroup, event.groups.all())
+ self.assertEqual(event.groups.count(), 2)
+ self.assertIn(self.room, event.rooms.all())
+ self.assertIn(self.room2, event.rooms.all())
+ self.assertEqual(event.rooms.count(), 2)
+ self.assertEqual(event.notes, "Commentaire")
+ self.assertEqual(event.celcat_id, 0)
+ self.assertEqual(event.begin, timezone.make_aware(
+ datetime.datetime(2018, 9, 21, 10, 0, 0)))
+ self.assertEqual(event.end, timezone.make_aware(
+ datetime.datetime(2018, 9, 21, 12, 0, 0)))
+ self.assertEqual(event.module.name, "AAA")
+
+ count += 1
+ module_count += 1
+
+ self.assertEqual(count, Course.objects.count())
+ self.assertEqual(module_count, Module.objects.count())
+
+ events = [
+ {
+ "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque"
+ "<br>L3 Info s1 CMA<br>Salle quelconque",
+ "name": "Cours quelconque", "type": "COURS/TD",
+ "group": self.group,
+ "room": self.room,
+ "id": "1",
+ "tag": ["aaa", "Cours"],
+ "meta": 1
+ },
+ {
+ "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque"
+ "<br>L3 Info s1 TDA2<br>Salle quelconque 3",
+ "name": "Cours quelconque",
+ "type": "COURS/TD",
+ "group": ngroup,
+ "notes": "Salle quelconque 3",
+ "id": "2"
+ },
+ {
+ "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque"
+ "<br>L3 Info s1 CMA<br>Salle quelconque 3<br>Commentaire",
+ "name": "Cours quelconque",
+ "type": "COURS/TD",
+ "group": self.group,
+ "notes": "Salle quelconque 3\nCommentaire",
+ "id": "3"
+ },
+ {
+ "text": "(10:00-12:00)<br>COURS/TD"
+ "<br>L3 Info s1 CMA<br>Salle quelconque 3",
+ "name": "COURS/TD",
+ "group": self.group,
+ "notes": "Salle quelconque 3",
+ "id": "4"
+ },
+ {
+ "text": "COURS/TD<br>L3 Info s1 CMA<br>Salle quelconque 3",
+ "name": "COURS/TD",
+ "group": self.group,
+ "notes": "Salle quelconque 3",
+ "id": "5"
+ },
+ {
+ "text": "L3 Info s1 CMA<br>Salle quelconque",
+ "name": "Sans nom",
+ "group": self.group,
+ "room": self.room,
+ "id": "6"
+ },
+ {
+ "text": "L3 Info s1 CMA<br>Salle quelconque 3",
+ "name": "Sans nom",
+ "group": self.group,
+ "notes": "Salle quelconque 3",
+ "id": "7"
+ },
+ {
+ "text": "(10:00-12:00)<br>L3 Info s1 CMA<br>Salle quelconque",
+ "name": "Sans nom",
+ "group": self.group,
+ "room": self.room,
+ "id": "8"
+ }
+ ]
+
+ for e in events:
+ event = get_event(
+ {"start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00",
+ "text": e["text"], "id": e["id"], "tag": e.get("tag", [])},
+ timezone.make_aware(datetime.datetime(2018, 9, 21)),
+ timezone.make_aware(datetime.datetime(2018, 9, 1)),
+ timezone.make_aware(datetime.datetime(2018, 10, 1)),
+ 2018, 38)
+
+ self.assertEqual(event.name, e["name"])
+ self.assertIn(e["group"], event.groups.all())
+ self.assertEqual(event.groups.count(), 1)
+ self.assertEqual(str(event.celcat_id), e["id"])
+
+ if "type" in e:
+ self.assertEqual(event.type, e["type"])
+ else:
+ self.assertIsNone(event.type)
+
+ if "room" in e:
+ self.assertIn(e["room"], event.rooms.all())
+ self.assertEqual(event.rooms.count(), 1)
+ else:
+ self.assertEqual(event.rooms.count(), 0)
+
+ if "notes" in e:
+ self.assertEqual(event.notes, e["notes"])
+ else:
+ self.assertIsNone(event.notes)
+
+ if "tag" in e:
+ self.assertEqual(event.module.name, e["tag"][e["meta"]])
+ module_count += 1
+ else:
+ self.assertIsNone(event.module)
+
+ count += 1
+
+ self.assertEqual(count, Course.objects.count())
+ self.assertEqual(module_count, Module.objects.count())
+
+ event = get_event(
+ {"start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00",
+ "text": "Global Event"},
+ timezone.make_aware(datetime.datetime(2018, 9, 21)),
+ timezone.make_aware(datetime.datetime(2018, 9, 1)),
+ timezone.make_aware(datetime.datetime(2018, 10, 1)),
+ 2018, 38)
+ self.assertIsNone(event)
+ self.assertEqual(count, Course.objects.count())
+
+ event = get_event(
+ {"start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00",
+ "text": "L3 Info s1 CMA<br>Salle quelconque 2"},
+ timezone.make_aware(datetime.datetime(2018, 9, 21)),
+ timezone.make_aware(datetime.datetime(2018, 9, 1)),
+ timezone.make_aware(datetime.datetime(2018, 10, 1)),
+ 2018, 39)
+ self.assertIsNone(event)
+ self.assertEqual(count, Course.objects.count())
+
+ @mock.patch("requests.get", side_effect=mock_requests_get)
+ def test_get_events(self, *args, **kwargs):
+ self.parser.get_source()
+ courses = [
+ {"begin":
+ timezone.make_aware(datetime.datetime(2018, 9, 21, 10, 00, 00)),
+ "end":
+ timezone.make_aware(datetime.datetime(2018, 9, 21, 12, 00, 00)),
+ "id": 0},
+ {"begin":
+ timezone.make_aware(datetime.datetime(2018, 10, 22, 10, 00, 00)),
+ "end":
+ timezone.make_aware(datetime.datetime(2018, 10, 22, 12, 00, 00)),
+ "id": 2}
+ ]
+
+ for i, course in enumerate(self.parser.get_events(
+ timezone.make_aware(datetime.datetime(2018, 9, 21)))):
+ self.assertEqual(course.name, "Cours quelconque")
+ self.assertEqual(course.type, "COURS/TD")
+ self.assertIn(self.group, course.groups.all())
+ self.assertEqual(course.groups.count(), 1)
+ self.assertIn(self.room, course.rooms.all())
+ self.assertEqual(course.rooms.count(), 1)
+ self.assertIsNone(course.notes)
+ self.assertEqual(course.begin, courses[i]["begin"])
+ self.assertEqual(course.end, courses[i]["end"])
+ self.assertEqual(course.celcat_id, courses[i]["id"])
+ self.assertEqual(course.module, None)
+
+ self.assertEqual(i, len(courses) - 1)
+
+ @mock.patch("requests.get", side_effect=mock_requests_get)
+ def test_get_source(self, *args, **kwargs):
+ events = self.parser.get_source()
+ self.assertEquals(events, [
+ [{
+ "start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00",
+ "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque"
+ "<br>L3 Info s1 CMA<br>Salle quelconque",
+ "id": "0",
+ "tag": [],
+ }], [{
+ "start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00",
+ "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque"
+ "<br>L3 Info s1 CMA<br>Salle quelconque",
+ "id": "1",
+ "tag": [],
+ }, {
+ "start": "2018-10-22T10:00:00", "end": "2018-10-22T12:00:00",
+ "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque"
+ "<br>L3 Info s1 CMA<br>Salle quelconque",
+ "id": "2",
+ "tag": [],
+ }], [], [], [], [], [], [], [], [], []])
+
+ def test_get_update_date(self):
+ # Pas de date de mise à jour dans ce format
+ self.assertIsNone(self.parser.get_update_date())
+
+
+class UPS2018BrokenSourceTestCase(TestCase):
+ @mock.patch("requests.get")
+ def test_broken_source(self, mock_get):
+ mock_get.return_value = mock_requests_get("")
+
+ source = Source.objects.create(url="https://example.org/2018")
+ with self.assertRaises(ParserError):
+ UPS2018Parser(source)
+
+ @mock.patch("requests.get")
+ def test_half_broken_source(self, mock_get):
+ source = Source.objects.create(url="https://example.org/2018")
+ mock_get.side_effect = [
+ mock_requests_get(""),
+ mock_requests_get(source.url)
+ ]
+
+ parser = UPS2018Parser(source)
+ self.assertEqual(parser.months, [
+ "September, 2018", "October, 2018", "November, 2018",
+ "December, 2018", "January, 2019", "February, 2019", "March, 2019",
+ "April, 2019", "May, 2019", "June, 2019", "July, 2019"
+ ])
diff --git a/tests/data/2018/empty.html b/tests/data/2018/empty.html
new file mode 100644
index 0000000..dde78b6
--- /dev/null
+++ b/tests/data/2018/empty.html
@@ -0,0 +1,50 @@
+<script>
+function do_something() {
+alert("something");
+}
+</script>
+
+ <option value="August, 2017">August, 2017</option>
+ <option value="September, 2017">September, 2017</option>
+ <option value="October, 2017">October, 2017</option>
+ <option value="November, 2017">November, 2017</option>
+ <option value="December, 2017">December, 2017</option>
+ <option value="January, 2018">January, 2018</option>
+ <option value="February, 2018">February, 2018</option>
+ <option value="March, 2018">March, 2018</option>
+ <option value="April, 2018">April, 2018</option>
+ <option value="May, 2018">May, 2018</option>
+ <option value="June, 2018">June, 2018</option>
+ <option value="July, 2018">July, 2018</option>
+ <option value="August, 2018">August, 2018</option>
+ <option value="September, 2018">September, 2018</option>
+ <option value="October, 2018">October, 2018</option>
+ <option value="November, 2018">November, 2018</option>
+ <option value="December, 2018">December, 2018</option>
+ <option value="January, 2019">January, 2019</option>
+ <option value="February, 2019">February, 2019</option>
+ <option value="March, 2019">March, 2019</option>
+ <option value="April, 2019">April, 2019</option>
+ <option value="May, 2019">May, 2019</option>
+ <option value="June, 2019">June, 2019</option>
+ <option value="July, 2019">July, 2019</option>
+
+<script>
+function do_something_else() {
+var v = "a variable";
+var vv = "another_variable";
+do_something();
+}
+</script>
+
+<script>
+function courses() {
+var v = {};
+v.events.list = [];;
+}
+</script>
+
+<script>
+courses();
+do_something_else();
+</script>
diff --git a/tests/data/2018/october.html b/tests/data/2018/october.html
new file mode 100644
index 0000000..ab3da0b
--- /dev/null
+++ b/tests/data/2018/october.html
@@ -0,0 +1,50 @@
+<script>
+function do_something() {
+alert("something");
+}
+</script>
+
+ <option value="August, 2017">August, 2017</option>
+ <option value="September, 2017">September, 2017</option>
+ <option value="October, 2017">October, 2017</option>
+ <option value="November, 2017">November, 2017</option>
+ <option value="December, 2017">December, 2017</option>
+ <option value="January, 2018">January, 2018</option>
+ <option value="February, 2018">February, 2018</option>
+ <option value="March, 2018">March, 2018</option>
+ <option value="April, 2018">April, 2018</option>
+ <option value="May, 2018">May, 2018</option>
+ <option value="June, 2018">June, 2018</option>
+ <option value="July, 2018">July, 2018</option>
+ <option value="August, 2018">August, 2018</option>
+ <option value="September, 2018">September, 2018</option>
+ <option selected="selected" value="October, 2018">October, 2018</option>
+ <option value="November, 2018">November, 2018</option>
+ <option value="December, 2018">December, 2018</option>
+ <option value="January, 2019">January, 2019</option>
+ <option value="February, 2019">February, 2019</option>
+ <option value="March, 2019">March, 2019</option>
+ <option value="April, 2019">April, 2019</option>
+ <option value="May, 2019">May, 2019</option>
+ <option value="June, 2019">June, 2019</option>
+ <option value="July, 2019">July, 2019</option>
+
+<script>
+function do_something_else() {
+var v = "a variable";
+var vv = "another_variable";
+do_something();
+}
+</script>
+
+<script>
+function courses() {
+var v = {};
+v.events.list = [{"start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00", "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque<br>L3 Info s1 CMA<br>Salle quelconque", "id": "1", "tag": []}, {"start": "2018-10-22T10:00:00", "end": "2018-10-22T12:00:00", "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque<br>L3 Info s1 CMA<br>Salle quelconque", "id": "2", "tag": []}];;
+}
+</script>
+
+<script>
+courses();
+do_something_else();
+</script>
diff --git a/tests/data/2018/september.html b/tests/data/2018/september.html
new file mode 100644
index 0000000..c81fc3b
--- /dev/null
+++ b/tests/data/2018/september.html
@@ -0,0 +1,51 @@
+<script>
+function do_something() {
+alert("something");
+}
+</script>
+
+ <option value="August, 2017">August, 2017</option>
+ <option value="September, 2017">September, 2017</option>
+ <option value="October, 2017">October, 2017</option>
+ <option value="November, 2017">November, 2017</option>
+ <option value="December, 2017">December, 2017</option>
+ <option value="January, 2018">January, 2018</option>
+ <option value="February, 2018">February, 2018</option>
+ <option value="March, 2018">March, 2018</option>
+ <option value="April, 2018">April, 2018</option>
+ <option value="May, 2018">May, 2018</option>
+ <option value="June, 2018">June, 2018</option>
+ <option value="July, 2018">July, 2018</option>
+ <option value="August, 2018">August, 2018</option>
+ <option selected="selected" value="September, 2018">September, 2018</option>
+ <option value="October, 2018">October, 2018</option>
+ <option value="November, 2018">November, 2018</option>
+ <option value="December, 2018">December, 2018</option>
+ <option value="January, 2019">January, 2019</option>
+ <option value="February, 2019">February, 2019</option>
+ <option value="March, 2019">March, 2019</option>
+ <option value="April, 2019">April, 2019</option>
+ <option value="May, 2019">May, 2019</option>
+ <option value="June, 2019">June, 2019</option>
+ <option value="July, 2019">July, 2019</option>
+
+<script>
+ function do_something_else() {
+ var v = "a variable";
+ var vv = "another_variable";
+
+ do_something();
+ }
+</script>
+
+<script>
+function courses() {
+var v = {};
+v.events.list = [{"start": "2018-09-21T10:00:00", "end": "2018-09-21T12:00:00", "text": "(10:00-12:00)<br>COURS/TD<br>Cours quelconque<br>L3 Info s1 CMA<br>Salle quelconque", "id": "0", "tag": []}];;
+}
+</script>
+
+<script>
+courses();
+do_something_else();
+</script>