DocScoDoc/docs/DevConventions.md

6.1 KiB

Conventions de codage pour ScoDoc

Le projet étant très ancien, le code est passé par différentes conventions et frameworks. Le style de python et celui du frontend web ont considérablement évolués ces dernières décennies.

Pour les nouveaux codes, respecter les principes suivants:

  • ScoDoc est avant tout une application serveur écrite en Python, qui offre des services via une interface Web, une API, et accessoirement la ligne de commande unix.

  • Les pages Web générées doivent l'être en Python côté serveur. On peut utiliser du JS pour les pages dynamiques complexes (eg éditeur de partition) mais éviter d'utiliser du JS pour générer des éléments statiques: l'abus de JS conduit à dupliquer du code (qui existe en général dans le serveur) et augmente les coûts de maintenance.

Conventions de codage

Formatage du code

  • l'usage de black est obligatoire
  • l'usage de pylint et mypy est fortement recommandé
  • Pour le code JS, indentation avec 2 espaces (sous VS Code, utiliser Prettier).

Conventions standard Python

On se tient à la PEP8, c'est à dire en résumé: UneClasse, une_fonction, _une_fonction_privee, une_variable, UNE_CONSTANTE_GLOBALE.

Les noms de fichiers sont en minuscules sans accents ni espaces, comme_ceci.py.

Annotations de type (typehints)

On annote les paramètres et résultats des fonctions.

def _upload_justificatif_files(
    just: Justificatif, form: AjoutJustificatifEtudForm
) -> bool:
    ...

Pages et templates

Les vues utilisent un template Jinja2, fichier avec extension j2.

On s'astreint, sauf cas particulier, à un nommage identique de la route, la vue et du template.

@bp.route("/un_exemple")
def un_exemple(...):
    ...
    return render_template(".../un_exemple.j2")

Le template aura typiquement avec la structure suivante:

{% extends "sco_page.j2" %}

{% block app_content %}
    <h1>Titre</h1>
{% endblock app_content %}

Pour les pages dans un semestre (avec barre menu etc.), on utilisera <h2> au lieu de <h1>.

Templates habituels

Les templates suivants sont les plus utilisés pour les pages:

  • base.j2 pages hors département (accueil, configuration, ...)

  • sco_page.j2 page standard dans un formsemestre: avec sidebar et barre de menu du semestre. Le contenu de la variable content est placé comme HTML brut (safe) dans la partie contenu. Passer sco=ScoData(formsemestre=formsemestre) en argument au template.

  • sco_page_dept.j2 page dans un département (avec sidebar) mais sans formsemestre (pas de barre de menu)

Constantes définies dans les templates ScoDoc

Le context_processor inject_sco_utils() ajoute des objets pour accès à tous les templates ScoDoc:

  • scu : le module sco_utils.py (diverses fonctions utilitaires et variables de config.)
  • sco : des données sur le contexte, notamment les préférences, le formsemestre et l'étudiant courants (resp. sco.formsemestre et sco.etud)

Appel d'un template page

Pour mémoire, l'appel d'un template dans une vue se fait ainsi:

render_template( "votre_template.j2",
    title="Changer de référentiel de compétences",
    autre_variable=...
)

Passage des anciennes pages ScoDoc 7 aux templates Jinja

Les anciennes pages étaient générées en python selon la structure:

html_sco_header.sco_header(
    cssstyles=["css/....css"],
    javascripts=[
        "js/....js",
    ],
    page_title="titre de la page",
)
... contenu ...
html_sco_header.sco_footer()

La migration la plus simple consiste à utilise sco_page.j2:

render_template(
    "sco_page.j2",
    content=contenu,
    title="titre de la page",
    cssstyles=["..."],
    javascripts=["..."],
)

Mais si on souhaite générer le contenu dans un template, cela prendra la forme:

{% extends "sco_page.j2" %}

{% block title %}
  ...titre...
{% endblock title %}

{% block styles %}
  {{ super() }}
  <link rel="stylesheet" href="{{scu.STATIC_DIR}}/css/un_style_scodoc.css">
  <style>
  ... styles locaux ...
  </style>
{% endblock styles %}

{% block app_content %}
  <div class="pageContent">
    <h2>titre page</h2>
    ... contenu ...
  </div>
{% endblock %}

{% block scripts %}
  {{ super() }}
  <script src="{{scu.STATIC_DIR}}/js/un_script_scodoc.js"></script>
  <script>
  ... script js local ...
  </script>
{% endblock %}

Classes css

scodoc.css (et à partir de 9.7, scodoc97.css) définissent quelques classes à usage général:

  • div.scobox: boite (bords arrondis, fond uni) regroupant des éléments.

    • div.scobox-title le titre de la boite
    • div.scobox-buttons boutons en bas de boite.
  • p.help, div.help: explications, aide.

  • ...

Accès à la base de donnée

Sauf exception (requêtes exotiques, problèmes de performance) à discuter, les accès à la base se font à travers l'ORM SQLAlchemy. Les modèles sont définis dans app/models, sauf les comptes utilisateurs qui sont dans /app/auth/models.py.

Au moment de la définition de nouveaux modèles, éviter si possible les champs nullables, penser à créer là où ce sera utile des index.

Tableaux

ScoDoc génère beaucoup de tableaux, sauf exception destinés à l'affichage Web et à l'export xlsx.

On utilise la super-classe Table de app/tables/table_builder.py.

Le rendu HTML utilise DataTables.

Dates et heures

ScoDoc, contrairement à de nombreuses applications, est centré sur les étudiants et les enseignements, qui sont censés opérer dans le fuseau horaire du serveur. Cela signifie que, quelle que soit l'emplacement de l'utilisateur, les heures affichées et saisies par ScoDoc seront données dans le fuseau horaire du serveur.

L'API publie et reçoit des heures au format ISO avec fuseau horaire (timezone) et n'est pas concernée par cette remarque.

!!! note "Voir aussi"

- [Introduction au développement ScoDoc](DevInternals.md)
- [Guide développeurs](GuideDeveloppeurs.md)
- [API ScoDoc 9](ScoDoc9API.md)
- [Modélisation du BUT](ModelisationParcoursBUT.md)
- [Contacts](Contact.md)