From 0eeba2b335807c8c19c2dbfd0463aa4df1375d0e Mon Sep 17 00:00:00 2001 From: Alban Gruin Date: Sun, 15 Apr 2018 21:46:47 +0200 Subject: doc: Début de la nouvelle documentation avec Sphinx --- Documentation/.gitignore | 1 + Documentation/Makefile | 20 +++ Documentation/conf.py | 170 ++++++++++++++++++++++ Documentation/dev/contribute.rst | 3 + Documentation/dev/internals.rst | 3 + Documentation/dev/roadmap.rst | 20 +++ Documentation/dev/xml.rst | 143 +++++++++++++++++++ Documentation/index.rst | 74 ++++++++++ Documentation/usage/commands.rst | 30 ++++ Documentation/usage/installation.rst | 267 +++++++++++++++++++++++++++++++++++ Documentation/usage/versions.rst | 35 +++++ 11 files changed, 766 insertions(+) create mode 100644 Documentation/.gitignore create mode 100644 Documentation/Makefile create mode 100644 Documentation/conf.py create mode 100644 Documentation/dev/contribute.rst create mode 100644 Documentation/dev/internals.rst create mode 100644 Documentation/dev/roadmap.rst create mode 100644 Documentation/dev/xml.rst create mode 100644 Documentation/index.rst create mode 100644 Documentation/usage/commands.rst create mode 100644 Documentation/usage/installation.rst create mode 100644 Documentation/usage/versions.rst (limited to 'Documentation') diff --git a/Documentation/.gitignore b/Documentation/.gitignore new file mode 100644 index 0000000..1d535b9 --- /dev/null +++ b/Documentation/.gitignore @@ -0,0 +1 @@ +_*/ diff --git a/Documentation/Makefile b/Documentation/Makefile new file mode 100644 index 0000000..4c9ce86 --- /dev/null +++ b/Documentation/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = celcatsanitizer +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/Documentation/conf.py b/Documentation/conf.py new file mode 100644 index 0000000..bfd8e6a --- /dev/null +++ b/Documentation/conf.py @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- +# +# celcatsanitizer documentation build configuration file, created by +# sphinx-quickstart on Mon Apr 16 12:10:54 2018. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'celcatsanitizer' +copyright = u'2018, Alban Gruin' +author = u'Alban Gruin' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = u'dev' +# The full version, including alpha/beta/rc tags. +release = u'dev' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'fr' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'about.html', + 'navigation.html', + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + ] +} + + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'celcatsanitizerdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'celcatsanitizer.tex', u'celcatsanitizer Documentation', + u'Alban Gruin', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'celcatsanitizer', u'celcatsanitizer Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'celcatsanitizer', u'celcatsanitizer Documentation', + author, 'celcatsanitizer', 'One line description of project.', + 'Miscellaneous'), +] + + + diff --git a/Documentation/dev/contribute.rst b/Documentation/dev/contribute.rst new file mode 100644 index 0000000..faab4f5 --- /dev/null +++ b/Documentation/dev/contribute.rst @@ -0,0 +1,3 @@ +======================================= +Guide de contribution à celcatsanitizer +======================================= diff --git a/Documentation/dev/internals.rst b/Documentation/dev/internals.rst new file mode 100644 index 0000000..9800d06 --- /dev/null +++ b/Documentation/dev/internals.rst @@ -0,0 +1,3 @@ +========================================= +Fonctionnement interne de celcatsanitizer +========================================= diff --git a/Documentation/dev/roadmap.rst b/Documentation/dev/roadmap.rst new file mode 100644 index 0000000..a7db062 --- /dev/null +++ b/Documentation/dev/roadmap.rst @@ -0,0 +1,20 @@ +================ +Feuille de route +================ + +Version 0.14 +============ + - Optimisation des requêtes en utilisant des fonctionnalités + spécifiques à PostgreSQL si nécessaire + - Remplacement du moteur de templates de Django par Jinja2_. + +.. _Jinja2: http://jinja.pocoo.org/ + +Version 1.0 +=========== + - Paquetage permettant l’installation par ``pip``. + +Futures fonctionnalités +======================= + - Utilisation de l’aggrégat ``TruncWeek`` dès que Django le proposera + (*a priori*, dès la version 2.1). diff --git a/Documentation/dev/xml.rst b/Documentation/dev/xml.rst new file mode 100644 index 0000000..bb2ebd0 --- /dev/null +++ b/Documentation/dev/xml.rst @@ -0,0 +1,143 @@ +================================== +Format des emplois du temps Celcat +================================== + +Avant de pouvoir afficher les emplois du temps, il est nécessaire de +parser les fichiers XML générés par Celcat. + +On a besoin de plusieurs informations concernant le cours : + + - son nom ; + - son type ; + - sa semaine et son jour ; + - son début et sa fin ; + - son commentaire ; + - ses salles ; + - ses groupes ; + +Certaines de ces informations sont triviales à récupérer (comme son +nom, son type, son commentaire…), mais d’autres (telles que son jour +précis) est un peu plus délicat. + +Parser facilement le XML +======================== +Pour traiter le XML facilement, celcatsanitizer utilise la fameuse +librairie BeautifulSoup4. Pour récupérer le fichier, on utilise la +librairie requests. + +Les semaines +============ +La première chose à faire après avoir téléchargé le fichier est de +récupérer la liste des semaines présentes. Les dates sont encodées +d’une manière assez exotique : + +.. code:: xml + + + Semaine 42, Semaine commençant le 16/10/2017 + 42 + NNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN + + lundi + + + + + + + + + mardi + + + + + + + + mercredi + + + + + + + + + jeudi + + + + + + + + vendredi + + + + + + + +Vous voyez donc la date de début, le numéro de semaine, et la +mystérieuse valeur ````. Il s’agit d’un identifiant de +semaine. La propriété ``id`` du ```` ne semble pas être +nécessaire pour comprendre le reste du fichier. + +.. _ref-week-dict: + +On va donc créer un tableau des semaines en se servant des +```` comme clé, et le premier jour de la semaine comme +valeur. + +Les cours +========= +Voici un exemple de cours : + +.. code:: xml + + + 1 + 07:45-09:45 COURS/TD + 07:45 + 09:45 + COURS/TD + + NNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN + + + EDINF3F1 - Algorithmique et programmation + + L2 Info s1 TDA4 + + 1TP1-B08bis + +Les différents éléments sont : + +================= ===================== ============================= +Donnée indiquée Balise correspondante Plusieurs valeurs possibles ? +================= ===================== ============================= +Nom du cours ```` Oui +Groupes concernés ```` Oui +Salles ```` Oui +Type de cours ```` Non +Heure de début ```` Non +Heure de fin ```` Non +Jour ```` Non +Semaine ```` Non +Remarque ```` Non +================= ===================== ============================= + +Quand une donnée peut prendre plusieurs valeurs à la fois, les +différentes valeurs se trouvent dans des balises +````. celcatsanitizer traîte tous les groupes et toutes les +salles, mais ne lis qu’un seul nom de cours. + +Dans l’exemple donné plus haut, il n’y a pas de champ remarque. + +Pour trouver le jours du cours, on prend la semaine référencée par la +balise ````, on retrouve le début de la semaine +correspondante à l’aide du :ref:`dictionnaire des semaines +`, et on ajoute autant de jours qu’indiqué par la +balise ````. diff --git a/Documentation/index.rst b/Documentation/index.rst new file mode 100644 index 0000000..92ad7b7 --- /dev/null +++ b/Documentation/index.rst @@ -0,0 +1,74 @@ +=============== +celcatsanitizer +=============== + +Présentation de celcatsanitizer +=============================== +Qu’est-ce que celcatsanitizer ? +------------------------------- + +celcatsanitizer est un outil basé sur Django_ permettant de reformater +les emplois du temps générés par Celcat. + +Les emplois du temps, accessibles à travers un navigateur web, +deviennent ainsi plus lisibles (notamment sur les appareils mobiles), +plus rapides à charger et plus légères. + +Les pages générées par celcatsanitizer ont étées conçues pour être les +plus légères possibles, tout en restant lisibles et fournies en +informations. Les pages peuvent être chargées sans CSS, et peuvent +êtres rendues sans problèmes par une large gamme de navigateurs. + +celcatsanitizer est aussi capable d’exporter les emplois du temps en +ICS_. + +Le parseur de celcatsanitizer est optimisé pour les emplois du temps +de l’Université Paul Sabatier, mais il est possible de le modifier. + +Vous pouvez trouver une instance de celcatsanitizer à l’adresse +https://edt.pa1ch.fr/. Cette instance utilise les emplois du temps de +l’Université Paul Sabatier. + +.. _Django: https://www.django-project.com/ +.. _ICS: https://fr.wikipedia.org/wiki/ICalendar + +Qu’est-ce que n’est pas celcatsanitizer ? +----------------------------------------- +celcatsanitizer n’est pas capable de produire un emploi du temps de +lui-même, seulement de reformater ceux produits par Celcat. + +Notes importantes +----------------- +Affiliation +``````````` +celcatsanitizer est un projet mené par des étudiants. Il n’est soutenu +d’aucune manière par Celcat ou l’Université Paul Sabatier. + +Licence +``````` +celcatsanitizer est sous licence AGPL3_, ce qui signifie, entre +autres, que toute modification de son code source **doit** être +redistribuée. + +.. _AGPL3: https://www.gnu.org/licenses/agpl-3.0.fr.html + +Utilisation de celcatsanitizer +============================== + +.. toctree:: + :maxdepth: 2 + + usage/installation + usage/commands + usage/versions + +Développement +============= + +.. toctree:: + :maxdepth: 2 + + dev/contribute + dev/xml + dev/internals + dev/roadmap diff --git a/Documentation/usage/commands.rst b/Documentation/usage/commands.rst new file mode 100644 index 0000000..5dede31 --- /dev/null +++ b/Documentation/usage/commands.rst @@ -0,0 +1,30 @@ +================================================ +Manuel des commandes intégrées à celcatsanitizer +================================================ + +``cleancourses`` +================ +**ATTENTION : cette commande est irréversible.** + +Cette commande permet d’effacr tous les cours présents dans la base. + +``listtimetables`` +================== +Affiche tous les emplois du temps présents dans la base de données, +avec leur nom, leur source et leur identifiant interne dans la base de +données. + +.. _ref-reparse: + +``reparse`` +=========== +Reparse les groupes dans la base de données. + +.. _ref-timetables: + +``timetables`` +============== +Met à jour les emplois du temps présents dans la base de données. + +Il est fortement recommandé d’exécuter régulièrement cette commande +:ref:`à l’aide d’une tâche cron `. diff --git a/Documentation/usage/installation.rst b/Documentation/usage/installation.rst new file mode 100644 index 0000000..7290df1 --- /dev/null +++ b/Documentation/usage/installation.rst @@ -0,0 +1,267 @@ +=============================== +Installation de celcatsanitizer +=============================== + +Dépendances +=========== +celcatsanitizer est écrit en Python 3. Il dépend des bibliothèques +suivantes : + + - `Django 2.0`_ + - requests_, pour récupérer les emplois du temps en HTTP(S) + - BeautifulSoup4_, pour parser les emplois du temps en XML + - icalendar_, pour générer des fichiers ICS_. + +*A priori*, il est possible d’utiliser n’importe quel SGBD supporté +par Django avec celcatsanitizer. Cependant, l’utilisation de +PostgreSQL_ est fortement recommandée. Dans ce cas, vous aurez besoin +d’installer le module psycopg2_. + +Pour l’instant, l’installation doit passer par git_. + +.. _Django 2.0: https://www.djangoproject.com/ +.. _requests: http://docs.python-requests.org/en/master/ +.. _BeautifulSoup4: + https://www.crummy.com/software/BeautifulSoup/bs4/doc/ +.. _icalendar: https://icalendar.readthedocs.io/en/latest/ +.. _ICS: https://fr.wikipedia.org/wiki/ICalendar +.. _PostgreSQL: https://www.postgresql.org/ +.. _psycopg2: http://initd.org/psycopg/docs/install.html +.. _git: https://git-scm.com/ + +Notes sur Django +---------------- +celcatsanitizer utilise des versions assez récentes de Django, +notamment en ce qui concerne son ORM. Le passage de Django 1.10 à +Django 1.11 s’est fait pour utiliser l’annotation ``ExtractWeek``, le +passage de Django 1.11 à Django 2.0 pour utiliser l’attribut +``distinct`` de l’aggrégat ``ArrayAgg``. + +celcatsanitizer passera à Django 2.1 lorsqu’il sortira pour utiliser +l’annotation ``TruncWeek``, pour l’instant implémenté avec une requête +SQL brute. Cette fonctionnalité ne sera nécessaire que pour les +utilisateurs de PostgreSQL. + +Installation +============ +Création de l’environnement virtuel +----------------------------------- +Cette étape est optionnelle, mais est tout de même fortement +recommandée. + +Placez-vous dans le répertoire souhaité, installez l’environnement +virtuel, puis activez-le : + +.. code:: shell + + $ virtualenv -p python3 celcatsanitizer + $ cd celcatsanitizer + $ source bin/activate + +Il est possible que votre version de pip soit ancienne. Si vous le +souhaitez, mettez-le à jour : + +.. code:: shell + + $ pip install -U pip + +Installation des dépendances +---------------------------- + +.. code:: shell + + $ pip install django beautifulsoup4 icalendar requests + +Si vous utilisez PostgreSQL, vous devez installer le module +psycopg2 : + +.. code:: shell + + $ pip install psycopg2 + +Création du projet Django +------------------------- + +.. code:: shell + + $ django-admin startproject celcatsanitizer + $ cd celcatsanitizer + +Récupération des sources de celcatsanitizer +------------------------------------------- + +.. code:: shell + + $ git clone https://git.pa1ch.fr/alban/celcatsanitizer.git edt + +Pour la production, il est recommandé d’utiliser une version +stable. Elles sont accessibles à travers les tags git. + +Configuration de Django +======================= +Avant de pouvoir lancer celcatsanitizer, vous allez devoir modifier +quelques fichiers. + +``settings.py`` +--------------- +Dans le fichier ``celcatsanitizer/settings.py``, vous devrez renseigner +plusieurs informations. + +Configuration des administrateurs +````````````````````````````````` +Vous pouvez retrouver la documentation de la variable ``ADMIN`` `sur le +site de Django`__. + +Cette variable est **obligatoire**. + +__ https://docs.djangoproject.com/fr/2.0/ref/settings/#admins + +Configuration de la base de données +``````````````````````````````````` +Vous pouvez retrouver la documentation relative à la configuration de +la base de données `sur le site de Django`__. + +Cette étape est **obligatoire**. + +__ https://docs.djangoproject.com/fr/2.0/ref/settings/#databases + +Configuration du mode de Django +``````````````````````````````` +Si jamais vous utilisez Django en production, vous **devez +impérativement** mettre la valeur de la variable ``DEBUG`` à +``False``. + +Ajout de celcatsanitizer à la liste des applications Django +``````````````````````````````````````````````````````````` +Ajoutez la chaîne de caractère ``edt`` à la liste ``INSTALLED_APPS``. + +Cette étape est **obligatoire**. + +.. _ref-flatpages: + +Activation des flatpages +```````````````````````` +celcatsanitizer se sert des flatpages pour rendre les pages "contact" +et "à propos". Vous pouvez retrouver le guide d’installation `sur le +site de Django`__. Effectuez uniquement les deux premières étapes, +celcatsanitizer enregistre déjà une route pour les pages statiques, et +la commande de l’étape 4 sera effectuée plus loin. + +Cette étape est **obligatoire**. + +__ + https://docs.djangoproject.com/fr/2.0/ref/contrib/flatpages/#installation + +Gestion des fichiers statiques +`````````````````````````````` +Si vous êtes en production, vous devez renseigner l’emplacement de +vos fichiers statiques dans la variable ``STATIC_ROOT`` de la +configuration de Django (vous pouvez retrouver la documentation +correspondante sur le site de Django). Puis, exécutez la commande +suivante : + +Cette étape est **obligatoire en production**, mais inutile en +déboguage. + +Ajout du processeur de contexte de celcatsanitizer +`````````````````````````````````````````````````` +Rajoutez la chaîne de caractères ``edt.views.ctx_processor`` à la +liste ``context_processors`` dans la variable ``TEMPLATES``. + +Cette étape est **fortement recommandée**. + +Configuration de l’internationalisation +``````````````````````````````````````` +Vous pouvez retrouver la documentation de l’internationalisation `sur +le site de Django`__. + +Ce paramètre est **optionnel**. + +__ https://docs.djangoproject.com/fr/2.0/topics/i18n/ + +``urls.py`` +----------- +Dans le fichier ``celcatsanitizer/urls.py``, importez la fonction +``django.conf.urls.include`` si elle ne l’est pas déjà, et rajouter +``url(r'^', include("edt.urls"))`` à la *fin* de la liste +``urlspatterns``. + +Cette étape est **obligatoire**. + +Derniers préparatifs +==================== +Génération de la base de données +-------------------------------- +Générez les migrations de Django et de celcatsanitizer, puis +appliquez-les : + +.. code:: shell + + $ ./manage.py makemigrations edt + $ ./manage.py migrate + +Collection des fichiers statiques +--------------------------------- +Si vous êtes en production, il faut regrouper les fichiers +statiques. Pour ce faire, exécutez la commande suivante : + +.. code:: shell + + $ ./manage.py collectstatic + +Cette étape est **obligatoire** en production, mais inutile en +déboguage. + +Création d’un super-utilisateur +------------------------------- +Pour pouvoir accéder à l’interface d’administration, il est important +de créer un super-utilisateur. Pour cela, exécutez la commande +suivante : + +.. code:: shell + + $ ./manage.py createsuperuser + +Répondez ensuite aux questions posées. + +Cette étape est **fortement recommandée**. + +.. _ref-cron: + +Cron +---- +Pour mettre à jour les emplois du temps de manière régulière, il faut +rajouter :ref:`la commande de mise à jour ` dans une +tâche cron. + +Lancement +========= +En mode de déboguage +-------------------- +Exécutez tout simplement la commande suivante : + +.. code:: shell + + $ ./manage.py runserver + +En production +------------- +Le serveur intégré à Django n’est pas adapté pour un usage en +production. Il vaut mieux utiliser Apache avec mod_wsgi, ou avec un +serveur gunicorn_ derrière nginx. + +.. _gunicorn: https://gunicorn.org/ + +Ajout des pages statiques +========================= +:ref:`Comme indiqué plus haut `, celcatsanitizer fait +appel aux flatpages de Django. + +À l’aide de l’interface d’administration de Django (si votre instance +se trouve à l’adresse ``example.com``, vous pourrez y accéder à +l’adresse ``example.com/admin``), dans la section "pages statiques", +rajoutez les pages ``/a-propos/`` et ``/contact/``. + +Si vous êtes en production, changez le site de base (``example.com``) +par le site sur lequel se trouvera votre instance de celcatsanitizer, +trouvable dans la section "sites". diff --git a/Documentation/usage/versions.rst b/Documentation/usage/versions.rst new file mode 100644 index 0000000..0f354bc --- /dev/null +++ b/Documentation/usage/versions.rst @@ -0,0 +1,35 @@ +================ +Notes de version +================ + +Version 0.13 +============ +Changements externes +-------------------- + - Ajout de l’emploi du temps des salles + - Ajout d’une fonctionnalité permettant de connaître les salles + disponibles + - Améliorations de la navigabilité du site + + - Ajout de liens pour revenir en arrière sur le site + - Ajout de liens pour parcourir les semaines de l’emploi du temps + + - Les groupes qui n’ont plus de cours du tout ne sont plus affichés + - Ajout d’une page contenant la liste complète des groupes + - Ajout d’une page contenant la liste complète des semaines de cours + pour les groupes et les salles + - Ajout d’un texte de description sur la page des ICS + - Création de la documentation + +Changements internes +-------------------- + - Passage à Django 2.0 + + - Utilisation des routes ``path()`` au lieu de ``url()`` + + - Création d’une table ``Source`` pour stocker la source des emplois + du temps. Cela permet d’éviter de récupérer plusieurs fois le même + fichier et d’éviter les doublons sur les emplois du temps des + salles. + - Ajout de la commande :ref:`reparse ` + - Meilleure abstraction des templates, notamment de ``index.html`` -- cgit v1.2.1