diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d478e690..5338eef7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -37,7 +37,7 @@ jobs: pushd ${{secrets.SITH_PATH}} git pull - poetry install + poetry install --with prod --without dev,docs,tests poetry run ./manage.py install_xapian poetry run ./manage.py migrate echo "yes" | poetry run ./manage.py collectstatic diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml new file mode 100644 index 00000000..16adb95a --- /dev/null +++ b/.github/workflows/deploy_docs.yml @@ -0,0 +1,21 @@ +name: deploy_docs +on: + push: + branches: + - master +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/setup_project + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - uses: actions/cache@v3 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + - run: poetry run mkdocs gh-deploy --force \ No newline at end of file diff --git a/.github/workflows/taiste.yml b/.github/workflows/taiste.yml index d7e1e9d9..7da84c43 100644 --- a/.github/workflows/taiste.yml +++ b/.github/workflows/taiste.yml @@ -36,7 +36,7 @@ jobs: pushd ${{secrets.SITH_PATH}} git pull - poetry install + poetry install --with prod --without dev,docs,tests poetry run ./manage.py install_xapian poetry run ./manage.py migrate echo "yes" | poetry run ./manage.py collectstatic diff --git a/README.md b/README.md index bf818ec6..414681cf 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ - - + + diff --git a/doc/SYNTAX.html b/core/fixtures/SYNTAX.html similarity index 100% rename from doc/SYNTAX.html rename to core/fixtures/SYNTAX.html diff --git a/doc/SYNTAX.md b/core/fixtures/SYNTAX.md similarity index 100% rename from doc/SYNTAX.md rename to core/fixtures/SYNTAX.md diff --git a/core/management/commands/documentation.py b/core/management/commands/documentation.py deleted file mode 100644 index 3e00d84b..00000000 --- a/core/management/commands/documentation.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright 2019 -# - Sli -# -# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM, -# http://ae.utbm.fr. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License a published by the Free Software -# Foundation; either version 3 of the License, or (at your option) any later -# version. -# -# This program 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 General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple -# Place - Suite 330, Boston, MA 02111-1307, USA. -# -# - -import os -import signal -import sys -from http.server import CGIHTTPRequestHandler, test - -from django.core.management.base import BaseCommand -from django.utils import autoreload - - -class Command(BaseCommand): - help = "Generate Sphinx documentation and launch basic server" - - default_addr = "127.0.0.1" - default_port = "8080" - - def add_arguments(self, parser): - parser.add_argument( - "addrport", nargs="?", help="Optional port number, or ipaddr:port" - ) - - def build_documentation(self): - os.chdir(os.path.join(self.project_dir, "doc")) - err = os.system("make html") - - if err != 0: - self.stdout.write("A build error occured") - - def start_server(self, **kwargs): - os.chdir(os.path.join(self.project_dir, "doc", "_build/html")) - addr = self.default_addr - port = self.default_port - if kwargs["addrport"]: - addrport = kwargs["addrport"].split(":") - - addr = addrport[0] - - if len(addrport) > 1: - port = addrport[1] - - if not port.isnumeric(): - self.stdout.write("%s is not a valid port" % (port,)) - sys.exit(0) - - test(HandlerClass=CGIHTTPRequestHandler, port=int(port), bind=addr) - - def build_and_start_server(self, **kwargs): - self.build_documentation() - self.start_server(**kwargs) - - def handle(self, *args, **kwargs): - self.project_dir = os.getcwd() - - signal.signal(signal.SIGTERM, lambda *args: sys.exit(0)) - try: - if os.environ.get(autoreload.DJANGO_AUTORELOAD_ENV) == "true": - reloader = autoreload.get_reloader() - reloader.watch_dir(os.path.join(self.project_dir, "doc"), "**/*.rst") - autoreload.logger.info( - "Watching for file changes with %s", reloader.__class__.__name__ - ) - autoreload.start_django(reloader, self.build_and_start_server, **kwargs) - else: - exit_code = autoreload.restart_with_reloader() - sys.exit(exit_code) - except KeyboardInterrupt: - pass diff --git a/core/management/commands/markdown.py b/core/management/commands/markdown.py index c8e21714..09a03d0d 100644 --- a/core/management/commands/markdown.py +++ b/core/management/commands/markdown.py @@ -21,20 +21,19 @@ # # -import os +from pathlib import Path +from django.conf import settings from django.core.management.base import BaseCommand from core.markdown import markdown class Command(BaseCommand): - help = "Output the fully rendered doc/SYNTAX.md file" + help = "Output the fully rendered SYNTAX.md file" def handle(self, *args, **options): - root_path = os.path.dirname( - os.path.dirname(os.path.dirname(os.path.dirname(__file__))) - ) - with open(os.path.join(root_path) + "/doc/SYNTAX.md", "r") as md: + root_path = Path(settings.BASE_DIR) + with open(root_path / "core/fixtures/SYNTAX.md", "r") as md: result = markdown(md.read()) print(result, end="") diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py index d2f6c9dd..8bd53c6f 100644 --- a/core/management/commands/populate.py +++ b/core/management/commands/populate.py @@ -383,7 +383,7 @@ Welcome to the wiki page! # Adding syntax help page p = Page(name="Aide_sur_la_syntaxe") p.save(force_lock=True) - with open(root_path / "doc" / "SYNTAX.md", "r") as rm: + with open(root_path / "core" / "fixtures" / "SYNTAX.md", "r") as rm: PageRev( page=p, title="Aide sur la syntaxe", author=skia, content=rm.read() ).save() diff --git a/core/markdown.py b/core/markdown.py index 8146ca54..5904dfbf 100644 --- a/core/markdown.py +++ b/core/markdown.py @@ -14,7 +14,6 @@ # from __future__ import annotations -import os import re from typing import TYPE_CHECKING @@ -131,9 +130,3 @@ markdown = mistune.create_markdown( "url", ], ) - -if __name__ == "__main__": - root_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - with open(os.path.join(root_path) + "/doc/SYNTAX.md", "r") as md: - result = markdown(md.read()) - print(result, end="") diff --git a/core/tests.py b/core/tests.py index 5be0b2e6..5c259b3b 100644 --- a/core/tests.py +++ b/core/tests.py @@ -215,9 +215,9 @@ def test_custom_markdown_syntax(md, html): def test_full_markdown_syntax(): - doc_path = Path(settings.BASE_DIR) / "doc" - md = (doc_path / "SYNTAX.md").read_text() - html = (doc_path / "SYNTAX.html").read_text() + syntax_path = Path(settings.BASE_DIR) / "core" / "fixtures" + md = (syntax_path / "SYNTAX.md").read_text() + html = (syntax_path / "SYNTAX.html").read_text() result = markdown(md) assert result == html diff --git a/doc/Color Theory - Palette Creator/README.txt b/doc/Color Theory - Palette Creator/README.txt deleted file mode 100644 index 81ec8d00..00000000 --- a/doc/Color Theory - Palette Creator/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -A Pen created at CodePen.io. You can find this one at https://codepen.io/anon/pen/PKVVXY. - -This page was used to generate the color palette of the sith. \ No newline at end of file diff --git a/doc/Color Theory - Palette Creator/css/style.css b/doc/Color Theory - Palette Creator/css/style.css deleted file mode 100644 index c2172d22..00000000 --- a/doc/Color Theory - Palette Creator/css/style.css +++ /dev/null @@ -1,74 +0,0 @@ -html, body { - margin: 0; - padding: 0; - width: 100%; - height: 100%; - background: #424242; - font-size: 16px; -} - -body { - display: flex; - flex-direction: column; - align-items: center; - font-size: .875rem; -} - -.form { - margin: 5rem 0; - width: 30rem; - background: #FAFAFA; - padding: 2rem; - border-radius: .25rem; - box-shadow: 0 4px 5px hsla(0, 0%, 0%, .5); -} - -.form-group { - display: flex; - flex-flow: column nowrap; -} - -.form-group:not(:first-child) { - margin-top: 1rem; -} - -.color-display { - display: flex; - align-items: center; -} - -.color-group { - display: flex; - align-items: center; - justify-content: space-between; -} - -.color-group > .color-code { - flex: 1 0 auto; - margin-left: 1rem; -} - -.color-hue { - height: 2rem; - align-self: stretch; - background-image: linear-gradient(to right, red, yellow, lime, cyan, blue, magenta, red) -} - -.form-input { - width: 100%; - margin: 0; -} - -.color-preview { - height: 5rem; - width: 5rem; - background-color: lightgrey; - border: 1px solid black; - display: flex; - justify-content: center; - align-items: center; -} - -.color-text { - font-size: 3rem; -} \ No newline at end of file diff --git a/doc/Color Theory - Palette Creator/index.html b/doc/Color Theory - Palette Creator/index.html deleted file mode 100644 index b67eb520..00000000 --- a/doc/Color Theory - Palette Creator/index.html +++ /dev/null @@ -1,422 +0,0 @@ - - - - - Color Theory Palette creator - - - - - - - - - - -
-
-
- -
-
-
- First color -
-
- -
-
-
- Second color -
-
- -
-
-
-
-
- Primary color -
-
- -
-
-
- Secondary color -
-
- -
-
-
-
-
- Text on primary color -
-
- Ab -
- -
-
-
- Text on complementary color -
-
- Ab -
- -
-
-
-
-
- Complementary neutral light color -
-
- Ab -
- -
-
-
- Complementary neutral color -
-
- Ab -
- -
-
-
- Complementary neutral dark color -
-
- Ab -
- -
-
-
- Primary neutral light color -
-
- Ab -
- -
-
-
- Primary neutral color -
-
- Ab -
- -
-
-
- Primary neutral dark color -
-
- Ab -
- -
-
-
-
-
- "White" color -
-
- Ab -
- -
-
-
- "Black" color -
-
- Ab -
- -
-
-
-
-
- Primary light color -
-
- Ab -
- -
-
-
- Primary color -
-
- Ab -
- -
-
-
- Primary dark color -
-
- Ab -
- -
-
-
-
- - - - - - - diff --git a/doc/Color Theory - Palette Creator/js/index.js b/doc/Color Theory - Palette Creator/js/index.js deleted file mode 100644 index f085c83f..00000000 --- a/doc/Color Theory - Palette Creator/js/index.js +++ /dev/null @@ -1,103 +0,0 @@ -/* jshint esversion: 6 */ - -// This is using Sass.js to use Sass built-in color mixing functions - -const firstColorChooser = document.forms['color-theory']['first-color']; -const firstColor = document.querySelector('.first-color'); -const secondColor = document.querySelector('.second-color'); - -let hue = undefined; -let comp = undefined; - -updateColors(); -Sass.options({ - precision: 1 -}); -computeScss(); - -document.forms['color-theory']['first-color'].addEventListener('input', updateColors); - -document.forms['color-theory']['first-color'].addEventListener('change', computeScss); - -function updateColors(ev) { - hue = parseInt(firstColorChooser.value); - comp = (hue + 180) % 360; - setColorPreview([firstColor], `hsl(${hue}, 100%, 50%)`); - setColorPreview([secondColor], `hsl(${comp}, 100%, 50%)`); -} - -function setColorPreview(fieldsets, color) { - Array.from(fieldsets).forEach(fieldset => { - const preview = fieldset.querySelector('.color-preview'); - preview.style.backgroundColor = fieldset.querySelector('.color-code').value = color; - const text = fieldset.querySelector('.color-text') - if(text) - text.style.color = computeTextColor(window.getComputedStyle(preview).backgroundColor); - }); -} - -function setColorText(fieldsets, bg, text) { - Array.from(fieldsets).forEach(fieldset => { - fieldset.querySelector('.color-preview').style.backgroundColor = bg; - fieldset.querySelector('.color-text').style.color = fieldset.querySelector('.color-code').value = text; - }); -} - -function computeScss() { - Sass.compile( - `$first-color: hsl(${hue}, 100%, 50%);` + - document.querySelector('#scss-template').content.firstElementChild.textContent, computedScssHandler); - -} - -function computedScssHandler(result) { - let colors = {}; - result.text.split('\n\n').forEach(rule => { - const color = /\.([\w\-]+) {\s*color: (hsl\() (\d{1,3}(?:\.\d+)?)deg(.*) (\));\s*}/.exec(rule).splice(1, 5).join('').split('hsl'); - colors[color[0]] = `hsl${color[1]}`; - }); - - for (let colorName in colors) - if (document.querySelector(`.${colorName}`)) setColorPreview(document.querySelectorAll(`.${colorName}`), colors[colorName]); - - const primaryTextColor = computeTextColor(window.getComputedStyle(document.querySelector('.primary-color .color-preview')).backgroundColor); - const complementaryTextColor = computeTextColor(window.getComputedStyle(document.querySelector('.complementary-color .color-preview')).backgroundColor); - setColorText([document.querySelector('.text-on-primary')], document.querySelector('.primary-color .color-preview').style.backgroundColor, primaryTextColor); - setColorText([document.querySelector('.text-on-complementary')], document.querySelector('.complementary-color .color-preview').style.backgroundColor, complementaryTextColor) -} - -function computeTextColor(colorStr) { - const black = [0, 0, 0, .87]; - const white = [255, 255, 255, 1]; - - [, , r, g, b, a] = /(rgba?)\((\d{1,3}), (\d{1,3}), (\d{1,3})(?:, (\d(?:\.\d+)))?\)/.exec(colorStr); - const color = [parseInt(r), parseInt(g), parseInt(b), parseFloat(a == undefined ? 1 : a)] - const blackContrast = computeConstrastRatio(black, color); - const whiteContrast = computeConstrastRatio(white, color); - return blackContrast < whiteContrast ? `hsl(0, 0%, 100%)` : `hsla(0, 0%, 0%, 0.87)` -} - -function computeConstrastRatio([fr, fg, fb, fa], [br, bg, bb, ba]) { - if (fa < 1) { - fr = fr * fa + br * (1 - fa); - fg = fg * fa + bg * (1 - fa); - fb = fb * fa + bb * (1 - fa); - fa = 1; - } - const fl = luminance([fr, fg, fb]); - const bl = luminance([br, bg, bb]); - - if (fl < bl) - return (bl + .05) / (fl + .05); - else - return (fl + .05) / (bl + .05); -} - -function luminance([r, g, b]) { - return .2126 * colorComponent(r) + .7152 * colorComponent(g) + .0722 * colorComponent(b); -} - -function colorComponent(color) { - const c = color / 255; - return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); -} \ No newline at end of file diff --git a/doc/Color Theory - Palette Creator/license.txt b/doc/Color Theory - Palette Creator/license.txt deleted file mode 100644 index 5514f9a9..00000000 --- a/doc/Color Theory - Palette Creator/license.txt +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/doc/Etransaction/Manuel_Integration_E-transactions_Internet_V6.6_FR.pdf b/doc/Etransaction/Manuel_Integration_E-transactions_Internet_V6.6_FR.pdf deleted file mode 100644 index c9612fee..00000000 Binary files a/doc/Etransaction/Manuel_Integration_E-transactions_Internet_V6.6_FR.pdf and /dev/null differ diff --git a/doc/Guide de Tresorerie.pdf b/doc/Guide de Tresorerie.pdf deleted file mode 100644 index 295ccedc..00000000 Binary files a/doc/Guide de Tresorerie.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/Paiement_Hmac.php b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/Paiement_Hmac.php deleted file mode 100644 index c25645dd..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/Paiement_Hmac.php +++ /dev/null @@ -1,124 +0,0 @@ -loadHTMLFile('https://'.$serveur.'/load.html'); -$server_status = ""; -$element = $doc->getElementById('server_status'); -if($element){ -$server_status = $element->textContent;} -if($server_status == "OK"){ -// Le serveur est prêt et les services opérationnels -$serveurOK = $serveur; -break;} -// else : La machine est disponible mais les services ne le sont pas. -} -//curl_close($ch); <== voir paybox -if(!$serveurOK){ -die("Erreur : Aucun serveur n'a été trouvé");} -// Activation de l'univers de préproduction -//$serveurOK = 'preprod-tpeweb.paybox.com'; - -//Création de l'url cgi paybox -$serveurOK = 'https://'.$serveurOK.'/cgi/MYchoix_pagepaiement.cgi'; -// echo $serveurOK; -*/ - - - -// --------------- TRAITEMENT DES VARIABLES --------------- - -// On récupère la date au format ISO-8601 -$dateTime = date("c"); -$dateTime = "2016-07-26T15:38:11+02:00"; - -// On crée la chaîne à hacher sans URLencodage -$msg = "PBX_SITE=".$pbx_site. -"&PBX_RANG=".$pbx_rang. -"&PBX_IDENTIFIANT=".$pbx_identifiant. -"&PBX_TOTAL=".$pbx_total. -"&PBX_DEVISE=978". -"&PBX_CMD=".$pbx_cmd. -"&PBX_PORTEUR=".$pbx_porteur. -// "&PBX_REPONDRE_A=".$pbx_repondre_a. -"&PBX_RETOUR=".$pbx_retour. -// "&PBX_EFFECTUE=".$pbx_effectue. -// "&PBX_ANNULE=".$pbx_annule. -// "&PBX_REFUSE=".$pbx_refuse. -"&PBX_HASH=SHA512". -"&PBX_TIME=".$dateTime; -// echo $msg; - -// Si la clé est en ASCII, On la transforme en binaire -$binKey = pack("H*", $keyTest); - -// On calcule l’empreinte (à renseigner dans le paramètre PBX_HMAC) grâce à la fonction hash_hmac et // -// la clé binaire -// On envoi via la variable PBX_HASH l'algorithme de hachage qui a été utilisé (SHA512 dans ce cas) -// Pour afficher la liste des algorithmes disponibles sur votre environnement, décommentez la ligne // -// suivante -// print_r(hash_algos()); -echo $msg, "\n\n"; -var_dump($binKey); -$hmac = strtoupper(hash_hmac('sha512', $msg, $binKey)); - -// La chaîne sera envoyée en majuscule, d'où l'utilisation de strtoupper() -// On crée le formulaire à envoyer -// ATTENTION : l'ordre des champs est extrêmement important, il doit -// correspondre exactement à l'ordre des champs dans la chaîne hachée -?> - - - - -
- - - - - - - - - - - - -
diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/SignVer.java b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/SignVer.java deleted file mode 100644 index 6578419e..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/SignVer.java +++ /dev/null @@ -1,63 +0,0 @@ -package signver; - -import java.security.interfaces.RSAPublicKey; -import java.security.Signature; -import java.security.KeyFactory; -import java.security.spec.X509EncodedKeySpec; -import java.io.FileInputStream; -import java.io.DataInputStream; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.net.URLCodec; - -public class SignVer { - - // verification signature RSA des donnees avec cle publique - - private static boolean verify( byte[] dataBytes, byte[] sigBytes, String sigAlg, RSAPublicKey pubKey) throws Exception - { - Signature sig = Signature.getInstance(sigAlg); - sig.initVerify(pubKey); - sig.update(dataBytes); - return sig.verify(sigBytes); - } - - // chargement de la cle AU FORMAT der : - // openssl rsa -inform PEM -in pbx_pubkey.pem -outform DER -pubin -out /tmp/pubkey.der - - private static RSAPublicKey getPubKey(String pubKeyFile) throws Exception - { - FileInputStream fis = new FileInputStream(pubKeyFile); - DataInputStream dis = new DataInputStream(fis); - byte[] pubKeyBytes = new byte[fis.available()]; - dis.readFully(pubKeyBytes); - fis.close(); - dis.close(); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - // extraction cle - X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(pubKeyBytes); - RSAPublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(pubSpec); - return pubKey; - } - - // exemple de verification de la signature - - public static void main(String[] unused) throws Exception { - - String sData = ""; // donnees signees URL encodees - String sSig = ""; // signature Base64 et URL encodee - - // decodage ... - byte[] dataBytes = URLCodec.decodeUrl(sData.getBytes()); - byte[] sigBytes = Base64.decodeBase64( URLCodec.decodeUrl(sSig.getBytes())); - - // lecture de la cle publique - RSAPublicKey pubK = getPubKey("/tmp/pubkey.der"); - - // verification signature - boolean result = verify(dataBytes, sigBytes, "SHA1withRSA", pubK); - - // affichage resultat - System.out.println("Resultat de la verification de signature : " + result); - } -} diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/TestK004.prv.pem b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/TestK004.prv.pem deleted file mode 100644 index 27859f9f..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/TestK004.prv.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQCvDYKaLH2xz4goZYXZWoHo6wyMb24A1iF7s70tB/g3XthEVS+/ -Wov+ZGqNTMLc0L+HZAJjcEc9h8Br5jPLR4VhaoKi+rezDxTQweaC24ydJWFKRhyX -Bhm2Wfnhppgzv9EqZKOrFaTlLQHu0F+KWEd7LngP4xcW9qjt19MfEmk0swIDAQAB -AoGABqXztNlFuNAR8r7QU43tayQqKNc+jUeUo/cSkzg/RBMVEZtOoezVbkbwCQfG -Ss6ex4yTzqT//6U9OJvYkbrYpOdq2BinuRv9n/NlKhCJ/Ym9s/DS8D6xdEX/R5lg -mIURQYl9uHS6VVnLq79j38BsjIhDAvjuSzZGZUa4v0iBTHkCQQDWp4iPqv2jUzBW -UgDP6C+QFqLgYKuYxF+yyBCXO0XzaHaEJUBuxuvTU/kuIifk3lhXnV5r0sXJd2Ax -aQkoJXc1AkEA0MU+4SSYPYADQm1gcXXuR4Kjb0/QhIGRiotxVu2nLGS7aULe1D8p -XoLpSQCv3j5amtXVx1yTWuaEYZqHVeQxRwJAdOprh1UrMXpuKZYgux1MSr8JmA0P -afYL6eTupHC0eQ+8/d0Ma0oNyN1EK8yOzioNFCuy8ierc0CCNGdxhVxiwQJAP/cv -fOwpeS5v0TqSAjGQAHkWelSKHw9T+I8g+vF19zQl9+p1O7LeigayU5vSRtX0DNzX -022Z+JAIn58pODfioQJBALQGN2kFCSk935VnMUJ4X5qFCKiXBgebuARUSw6tDEpY -gFdqyJE4WQ4uWVz0D9M27lCa8wj7pYrOhB/UiMKbuqY= ------END RSA PRIVATE KEY----- diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/TestK004.pub.pem b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/TestK004.pub.pem deleted file mode 100644 index e8c4bcd1..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/TestK004.pub.pem +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvDYKaLH2xz4goZYXZWoHo6wyM -b24A1iF7s70tB/g3XthEVS+/Wov+ZGqNTMLc0L+HZAJjcEc9h8Br5jPLR4VhaoKi -+rezDxTQweaC24ydJWFKRhyXBhm2Wfnhppgzv9EqZKOrFaTlLQHu0F+KWEd7LngP -4xcW9qjt19MfEmk0swIDAQAB ------END PUBLIC KEY----- diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/accepte.php b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/accepte.php deleted file mode 100644 index c194bab2..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/accepte.php +++ /dev/null @@ -1,11 +0,0 @@ -

Votre transaction a été acceptée


"); -print ("
MONTANT : $montant\n"); -print ("
REFERENCE : $ref_com\n"); -print ("
AUTO : $auto\n"); -print ("
TRANS : $trans\n"); -?> \ No newline at end of file diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/annule.php b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/annule.php deleted file mode 100644 index f09cfa57..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/annule.php +++ /dev/null @@ -1,11 +0,0 @@ -

Votre transaction a été annulée


"); -print ("
MONTANT : $montant\n"); -print ("
REFERENCE : $ref_com\n"); -#print ("
AUTO : $auto\n"); -print ("
TRANS : $trans\n"); -?> \ No newline at end of file diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/mail_ticket_client.htm b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/mail_ticket_client.htm deleted file mode 100644 index 5fd19d9d..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/mail_ticket_client.htm +++ /dev/null @@ -1,79 +0,0 @@ - - - - - -Exemple_mail_ticket_client - - - - - - - -
- -

Merci de votre -commande

- -

Celle-ci sera traitée -dans les meilleurs délais

- -

Cordialement,

- -

Votre Enseigne

- -

Gardez les références de votre commande et n'hésitez pas à -nous contacter si vous avez des questions :

- -

tel : 00 00 00 00 00

- -

courriel : contact@maboutique.fr

- -
- - - - diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/pubkey.pem b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/pubkey.pem deleted file mode 100644 index 55dc28b5..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/pubkey.pem +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDe+hkicNP7ROHUssGNtHwiT2Ew -HFrSk/qwrcq8v5metRtTTFPE/nmzSkRnTs3GMpi57rBdxBBJW5W9cpNyGUh0jNXc -VrOSClpD5Ri2hER/GcNrxVRP7RlWOqB1C03q4QYmwjHZ+zlM4OUhCCAtSWflB4wC -Ka1g88CjFwRw/PB9kwIDAQAB ------END PUBLIC KEY----- diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/refuse.php b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/refuse.php deleted file mode 100644 index 0f94a0ad..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/refuse.php +++ /dev/null @@ -1,11 +0,0 @@ -

Votre transaction a été refusée


"); -print ("
MONTANT : $montant\n"); -print ("
REFERENCE : $ref_com\n"); -#print ("
AUTO : $auto\n"); -print ("
TRANS : $trans\n"); -?> \ No newline at end of file diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/testsign.php b/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/testsign.php deleted file mode 100644 index b3b6d5ec..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Exemple.php/testsign.php +++ /dev/null @@ -1,102 +0,0 @@ - -///// script PHP de vérification de la signature Paybox. -///// Ce code peut s'executer dans un contexte Apache/PHP. -///// Il affiche alors une page web qui permet de vérifier et signer des données. - - - - - -formulaire d'exemple pour test signature - - - - -
- - - - - - - - - - - - -
status =
-
- - diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Appel_par_cle_HMAC_V2_1.2.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Appel_par_cle_HMAC_V2_1.2.pdf deleted file mode 100644 index 2db9bcc7..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Appel_par_cle_HMAC_V2_1.2.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/CGU_V9_-_29_sept_2014_-SSM.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/CGU_V9_-_29_sept_2014_-SSM.pdf deleted file mode 100644 index aed41954..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/CGU_V9_-_29_sept_2014_-SSM.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Dictionnaire_pour_E-commercant_V6.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Dictionnaire_pour_E-commercant_V6.pdf deleted file mode 100644 index 73ca4170..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Dictionnaire_pour_E-commercant_V6.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_ parametre_de_tests_V6_31.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_ parametre_de_tests_V6_31.pdf deleted file mode 100644 index 2b926877..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_ parametre_de_tests_V6_31.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_Infos_Securite_SSL.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_Infos_Securite_SSL.pdf deleted file mode 100644 index 634a5f4f..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_Infos_Securite_SSL.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PageChoix_V1_3.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PageChoix_V1_3.pdf deleted file mode 100644 index d5f14c54..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PageChoix_V1_3.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PagePaiement_V1_00.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PagePaiement_V1_00.pdf deleted file mode 100644 index 5f809068..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PagePaiement_V1_00.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PayPal_V9_2.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PayPal_V9_2.pdf deleted file mode 100644 index 06f50e54..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_PayPal_V9_2.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_Paylib.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_Paylib.pdf deleted file mode 100644 index 82d7c064..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/E-transactions_NoteTechniqueIntegration_Paylib.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Guide_Bonnes_Pratiques_Securisation_cle_HMAC_V1_1.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Guide_Bonnes_Pratiques_Securisation_cle_HMAC_V1_1.pdf deleted file mode 100644 index 55b5d99e..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Guide_Bonnes_Pratiques_Securisation_cle_HMAC_V1_1.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Les_etapes_de_votre_raccordement_V3.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Les_etapes_de_votre_raccordement_V3.pdf deleted file mode 100644 index 8cb2b68e..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Les_etapes_de_votre_raccordement_V3.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_E-transactions_aide_a_la_migration-installation.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_E-transactions_aide_a_la_migration-installation.pdf deleted file mode 100644 index ea7560e0..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_E-transactions_aide_a_la_migration-installation.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_Internet_V6.5_FR.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_Internet_V6.5_FR.pdf deleted file mode 100644 index 32247e9a..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_Internet_V6.5_FR.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_RemoteMPI_V6 1.2_FR.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_RemoteMPI_V6 1.2_FR.pdf deleted file mode 100644 index a9e1ee85..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_RemoteMPI_V6 1.2_FR.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_Traitement_par_Lots_V6.5_FR.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_Traitement_par_Lots_V6.5_FR.pdf deleted file mode 100644 index 8aeb4386..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_E-transactions_Traitement_par_Lots_V6.5_FR.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_Gestion_Automatisee_des_Encaissements.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_Gestion_Automatisee_des_Encaissements.pdf deleted file mode 100644 index 59acc9b6..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Integration_Gestion_Automatisee_des_Encaissements.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Utilisateur_Back-office_E-transactions-v6_0_2-Commercant.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Utilisateur_Back-office_E-transactions-v6_0_2-Commercant.pdf deleted file mode 100644 index 999880a7..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_Utilisateur_Back-office_E-transactions-v6_0_2-Commercant.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_des_bonnes_pratiques_3D_Secure_v3.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_des_bonnes_pratiques_3D_Secure_v3.pdf deleted file mode 100644 index 04387f1a..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Manuel_des_bonnes_pratiques_3D_Secure_v3.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/NoteTechniqueIntegration_Oney_V1 5_E-transactions_v3.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/NoteTechniqueIntegration_Oney_V1 5_E-transactions_v3.pdf deleted file mode 100644 index 0d71457c..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/NoteTechniqueIntegration_Oney_V1 5_E-transactions_v3.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_d_ouverture_de_compte_PayPal_pour_E-transactions.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_d_ouverture_de_compte_PayPal_pour_E-transactions.pdf deleted file mode 100644 index 22408a04..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_d_ouverture_de_compte_PayPal_pour_E-transactions.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_de_Depot_E-transactions_Traitement_par_Lots_V6_30.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_de_Depot_E-transactions_Traitement_par_Lots_V6_30.pdf deleted file mode 100644 index cfde7948..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_de_Depot_E-transactions_Traitement_par_Lots_V6_30.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_de_test_E-transactions_V1_1_FR.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_de_test_E-transactions_V1_1_FR.pdf deleted file mode 100644 index 2c8a3d12..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Procedure_de_test_E-transactions_V1_1_FR.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Tableau_correspondance_SIPS_ATOS-PAYBOX_V4.pdf b/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Tableau_correspondance_SIPS_ATOS-PAYBOX_V4.pdf deleted file mode 100644 index 62c77837..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Manuel installation Offre Internet/Tableau_correspondance_SIPS_ATOS-PAYBOX_V4.pdf and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/3dsecure.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/3dsecure.png deleted file mode 100644 index 08b0475e..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/3dsecure.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/Thumbs.db b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/Thumbs.db deleted file mode 100644 index 0d009396..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/Thumbs.db and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/amex.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/amex.png deleted file mode 100644 index b03e23e6..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/amex.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-e-transactions-cb-visa-mastercard.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-e-transactions-cb-visa-mastercard.png deleted file mode 100644 index b983fd84..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-e-transactions-cb-visa-mastercard.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-e-transactions.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-e-transactions.png deleted file mode 100644 index 78ea3b7a..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-e-transactions.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-turquoise.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-turquoise.png deleted file mode 100644 index e99bdebc..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca-turquoise.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca.png deleted file mode 100644 index fd1209e0..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/ca.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-blanc.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-blanc.png deleted file mode 100644 index 1c660f82..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-blanc.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-gris.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-gris.png deleted file mode 100644 index 825634c4..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-gris.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-phrase-source.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-phrase-source.png deleted file mode 100644 index 9db4530a..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-phrase-source.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-transparent.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-transparent.png deleted file mode 100644 index 3cfd99cc..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/e-transactions-transparent.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/header.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/header.png deleted file mode 100644 index 045aad7a..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/header.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/mastercard.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/mastercard.png deleted file mode 100644 index 4b1ec88a..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/mastercard.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/visa.png b/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/visa.png deleted file mode 100644 index c5fd61c1..00000000 Binary files a/doc/Kit_E-transactions_internet_premium_PHP/Pack Logos CA/visa.png and /dev/null differ diff --git a/doc/Kit_E-transactions_internet_premium_PHP/Personnalisation/nouvelle version_page_paiement.css b/doc/Kit_E-transactions_internet_premium_PHP/Personnalisation/nouvelle version_page_paiement.css deleted file mode 100644 index 65322f1e..00000000 --- a/doc/Kit_E-transactions_internet_premium_PHP/Personnalisation/nouvelle version_page_paiement.css +++ /dev/null @@ -1,206 +0,0 @@ -/* CSS Document */ - -/* feuille de style par d?faut pour les pages -de choix de paiement et de paiement -paybox system*/ - -th { /* headers de tables (dans choix paiement les ent?tes de table en bleu )*/ - color: black; - background-color: #2890D6; - font-size: 16px; - font-weight: bold; -} - -td {/* cellules */ - font-size: 13px; -} - -h2 {/*le texte 'paiement de' et '?'*/ - margin:0; - padding: 0; -} - -.pbx_table_logo td {/*les cellules de la table logo (la table a la classe "pbx_table_logo")*/ - background-color: #FFFFFF; - text-align: center; -} - -.pbx_h1{/* le premier bloc de texte dans choixpaiement */ - font-size: 14px; - font-family: verdana; - font-weight:normal; -} - - -.pbx_h2{/* le second bloc de texte dans choixpaiement (choisisseze un moyen...)*/ - font-family: verdana; - font-size:12px; - font-weight:bold; -} - -.pbx_h3{/* l'ent?te reprenant le libell? du type de moyen de paiement*/ - font-family: verdana; - font-size:12; - font-weight:normal; -} - -.pbx_h4{/* nom d'enseigne, en page de paiement*/ - color:#444; - display: block; - margin: 8px 0 0 0; - padding: 0; - border-top: 1px solid #ccc; - padding: 5px; - display: block; - background-color: #f5f5f5; - height: 35px; - line-height: 35px; - font-size: 12px; - font-weight: normal; - text-shadow: none; -} - -.pbx_copyright h5{/*mention paybox en bas de page (choix et paiement)*/ - font-size:10px; - font-weight: normal; -} - -a { - text-decoration: none; - color : gray; - font-weight: bold; - font-style: italic; - padding: 0 5px; -} - -#tabledevises { - color: #AAA; -} - -a:hover { - color : #222; -} - -body { color: #555555; - font-family: arial,verdana,sans-serif; - padding : 0px; - margin: 0; -} - - -#idframe_pay { - border-color: #CCCCCC; - border-radius: 6px 6px 6px 6px; - border-style: solid; - border-width: 1px; - margin: 20px; - position: relative; -} - -#idframe_pay table { - border-spacing:0; - border-collapse:collapse; - width: 100%; -} - -#idframe_pay h2 { - width: 100%; - background: url("main_header_background.png") repeat scroll 0 0 transparent; - border-color: #CCCCCC; - border-radius: 5px 5px 0 0; - border-style: solid; - border-width: 0 0 1px 0; - box-shadow: 1px 1px 0 0 #888888 inset; - color: #EEEEEE; - font-weight: bold; - text-shadow: 1px 1px 1px #444444; - font-size: 16px; - font-weight: bold; - text-align: center; - padding: 8px 0 0 0; -} -/* -#idframe_pay td { - vertical-align: top; -} -*/ -.pbx-align-center { - text-align: center; - padding: 20px 10px; - width: 50%; -} - -.pbx-align-right { - text-align: right; - padding: 2px 10px; - width: 50%; - white-space: nowrap; -} - -.pbx-align-button-right img { - -vertical-align:middle; -} - -.pbx-align-left { - text-align: left; - padding: 2px 10px; - width: 50%; -} - -.pbx-align-left img { - -vertical-align:middle; -} - -.pbx-align-very-left { - text-align: left; - padding: 2px 10px; - width: 100%; -} - -.pbx-no-padding { - padding: 0; -} - -.pbx-align-button-right { - text-align: right; - padding: 2px 10px; - width: 50%; -} - -.pbx-align-button-left { - text-align: left; - padding: 2px 10px; - width: 50%; -} - - -#Devises{ - left:0px; - top:0px; -} - -#pbx-numero-carte, #pbx-numero-carte-input { - padding-top: 30px -} - -#pbx-maxicheque-vide { - display: none; -} - -#pbx-maxicheque-frame { - padding: 0 220px; -} - -#blocCarte1 { - display: inline-block; -} - -#zoneResultConsult { - border: 1px solid #CCCCCC; - border-radius: 10px 10px 10px 10px; - display: block; - margin: 20px; - padding: 20px; -} \ No newline at end of file diff --git a/doc/MLD.pdf b/doc/MLD.pdf deleted file mode 100644 index 51372e58..00000000 Binary files a/doc/MLD.pdf and /dev/null differ diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index d4bb2cbb..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -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) diff --git a/doc/about/introduction.rst b/doc/about/introduction.rst deleted file mode 100644 index 3d682ead..00000000 --- a/doc/about/introduction.rst +++ /dev/null @@ -1,29 +0,0 @@ -Introduction -============ - -Le but de ce projet est de fournir à l'Association des Étudiants de l'UTBM une plate-forme pratique et centralisée de ses services. Le Sith de l'AE tient à jour le registre des cotisations à l'association, prend en charge la trésorerie, les ventes de produits et services, la diffusion d’événements, la gestion de la laverie et bien plus encore. Il est conçu de manière suffisamment générique pour être facilement adaptable à une autre association. - -C'est un projet bénévole qui tire ses origines des années 2000. Il s'agit de la troisième version du site de l'association initiée en 2015. C'est une réécriture complète en rupture totale des deux versions qui l'ont précédée. - -Pourquoi réécrire le site -------------------------- - -L'ancienne version du site, sobrement baptisée `ae2 `_ présentait un nombre impressionnant de fonctionnalités. Il avait été écrit en PHP et se basait sur son propre framework maison. - -Malheureusement, son entretien était plus ou moins hasardeux et son framework reposait sur des principes assez différents de ce qui se fait aujourd'hui, rendant la maintenance difficile. De plus, la version de PHP qu'il utilisait était plus que dépréciée et à l'heure de l'arrivée de PHP 7 et de sa non rétrocompatibilité il était vital de faire quelque chose. Il a donc été décidé de le réécrire. - -La philosophie du projet ------------------------- - -Pour éviter les erreurs du passé, ce projet met l'accent sur la maintenabilité. Le choix des technologies ne s'est donc pas fait uniquement sur le fait qu'elle soit récentes, mais également sur leur robustesse, leur fiabilité et leur potentiel à être maintenu loin dans le futur. - -La maintenabilité passe également par le choix minutieux des dépendances qui doivent eux aussi passer l'épreuve du temps pour éviter qu'elles ne mettent le projet en danger. - -Cela passe également par la minimisation des frameworks employés de manière à réduire un maximum les connaissances nécessaires pour contribuer au projet et donc simplifier la prise en main. La simplicité est à privilégier si elle est possible. - -Le projet doit être simple à installer et à déployer. - -Le projet étant à destination d'étudiants, il est préférable de minimiser les ressources utilisées par l'utilisateur final. Il faut qu'il soit au maximum économe en bande passante et calcul côté client. - - -Le projet est un logiciel libre et est sous licence GPL. Aucune dépendance propriétaire ne sera acceptée. diff --git a/doc/about/tech.rst b/doc/about/tech.rst deleted file mode 100644 index 933e232d..00000000 --- a/doc/about/tech.rst +++ /dev/null @@ -1,233 +0,0 @@ -Technologies utilisées -====================== - -Bien choisir ses technologies est crucial puisqu'une fois que le projet est suffisamment avancé, il est très difficile voir impossible de revenir en arrière. - -En novembre 2015, plusieurs choix s'offraient à nous : - -* Continuer avec du PHP -* S'orienter vers un langage web plus moderne et à la mode comme le Python ou le Ruby -* Baser le site sur un framework Javascript - -Le PHP 5, bientôt 7, de l'époque étant assez discutable comme `cet article `__ et l'ancien site ayant laissé un goût amer à certains développeurs, celui-ci a été mis de côté. - -L'écosystème Javascript étant à peine naissant et les frameworks allant et venant en seulement quelques mois, il était impossible de prédire avec certitude si ceux-ci passeraient l'épreuve du temps, il était inconcevable de tout parier là dessus. - -Ne restait plus que le Python et le Ruby avec les frameworks Django et Ruby On Rails. Ruby ayant une réputation d'être très "cutting edge", c'est Python, un langage bien implanté et ayant fait ses preuves, qui a été retenu. - -Il est à noter que réécrire le site avec un framework PHP comme Laravel ou Symphony -eut aussi été possible, ces deux technologies étant assez matures et robustes -au moment où le développement a commencé. -Cependant, il aurait été potentiellemet fastidieux de maintenir en parallèle deux -versions de PHP sur le serveur durant toute la durée du développement. -Il faut aussi prendre en compte que nous étions à ce moment dégoûtés du PHP. - -Backend -------- - -Python 3 -~~~~~~~~ - -`Site officiel `__ - -Le python est un langage de programmation interprété multi paradigme sorti en 1991. Il est très populaire pour sa simplicité d'utilisation, sa puissance, sa stabilité, sécurité ainsi que sa grande communauté de développeur. Sa version 3, non rétro compatible avec sa version 2, a été publiée en 2008. - -.. note:: - - Puisque toutes les dépendances du backend sont des packages Python, elles sont toutes ajoutées directement dans le fichier **pyproject.toml** à la racine du projet. - -Django -~~~~~~ - -| `Site officiel `__ -| `Documentation `__ - -Django est un framework web pour Python apparu en 2005. Il fourni un grand nombre de fonctionnalités pour développer un site rapidement et simplement. Cela inclu entre autre un serveur Web de développement, un parseur d'URLs pour le routage des différentes URI du site, un ORM (Object-Relational Mapper) pour la gestion de la base de donnée ainsi qu'un moteur de templates pour le rendu HTML. Django propose une version LTS (Long Term Support) qui reste stable et est maintenu sur des cycles plus longs, ce sont ces versions qui sont utilisées. - -Il est possible que la version de Django utilisée ne soit pas la plus récente. -En effet, la version de Django utilisée est systématiquement celle munie d'un support au long-terme. - -PostgreSQL / SQLite3 -~~~~~~~~~~~~~~~~~~~ - -| `Site officiel PostgreSQL `__ -| `Site officiel SQLite `__ - -Comme la majorité des sites internet, le Sith de l'AE enregistre ses données dans une base de donnée. Nous utilisons une base de donnée relationnelle puisque c'est la manière typique d'utiliser Django et c'est ce qu'utilise son ORM. Dans la pratique il arrive rarement dans le projet de se soucier de ce qui fonctionne derrière puisque le framework abstrait les requêtes au travers de son ORM. Cependant, il arrive parfois que certaines requêtes, lorsqu'on cherche à les optimiser, ne fonctionnent que sur un seul backend. - -Le principal à retenir ici est : - -* Sur la version de production nous utilisons PostgreSQL, c'est cette version qui doit fonctionner en priorité -* Sur les versions de développement, pour faciliter l'installation du projet, nous utilisons la technologie SQLite3 qui ne requiert aucune installation spécifique (La librairie `sqlite` est incluse dans les librairies par défaut de Python). Certaines instructions ne sont pas supportées par cette technologie et il est parfois nécessaire d'installer PostgreSQL pour le développement de certaines parties du site. - -Frontend --------- - -Jinja2 -~~~~~~ - -`Site officiel `__ - -Jinja2 est un moteur de template écrit en Python qui s'inspire fortement de la syntaxe des templates de Django. Ce moteur apporte toutefois son lot d'améliorations non négligeables. Il permet par exemple l'ajout de macros, sortes de fonctions écrivant du HTML. - -Un moteur de templates permet de générer du contenu textuel de manière procédural en fonction des données à afficher, cela permet de pouvoir inclure du code proche du Python dans la syntaxe au milieu d'un document contenant principalement du HTML. On peut facilement faire des boucles ou des conditions ainsi même que de l'héritage de templates. - -Attention : le rendu est fait côté serveur, si on souhaite faire des modifications côté client, il faut utiliser du Javascript, rien ne change à ce niveau là. - -Exemple d'utilisation d'un template Jinja2 - -.. sourcecode:: html+jinja - - {% block title %}{% endblock %} - - -jQuery -~~~~~~ - -`Site officiel `__ - -jQuery est une bibliothèque JavaScript libre et multiplateforme créée pour faciliter l'écriture de scripts côté client dans le code HTML des pages web. La première version est lancée en janvier 2006 par John Resig. - -C'est une vieille technologie et certains feront remarquer à juste titre que le Javascript moderne permet d'utiliser assez simplement la majorité de ce que fournit jQuery sans rien avoir à installer. Cependant, de nombreuses dépendances du projet utilisent encore jQuery qui est toujours très implanté aujourd'hui. Le sucre syntaxique qu'offre cette librairie reste très agréable à utiliser et économise parfois beaucoup de temps. Ça fonctionne et ça fonctionne très bien. C'est maintenu et pratique. - -VueJS -~~~~~ - -`Site officiel `__ - -jQuery permet de facilement manipuler le DOM et faire des requêtes en AJAX, -mais est moins pratique à utiliser pour créer des applications réactives. -C'est pour cette raison que Vue a été intégré au projet. - -Vue est une librairie Javascript qui se concentre sur le rendu déclaratif et la composition des composants. -C'est une technologie très utilisée pour la création d'applications web monopages (ce que le site n'est pas) -mais son architecture progressivement adoptable permet aisément d'adapter son -comportement à une application multipage comme le site AE. - -A ce jour, il est utilisé pour l'interface des barmen, dans l'application des comptoirs. - -AlpineJS -~~~~~~~~ - -`Site officiel `__ - -Dans une démarche similaire à celle de l'introduction de Vue, Alpine a aussi fait son -apparition au sein des dépendances Javascript du site. -La librairie est décrite par ses créateurs comme : -"un outil robuste et minimal pour composer un comportement directement dans vos balises". - -Alpine permet d'accomplir la plupart du temps le même résultat qu'un usage des fonctionnalités -de base de Vue, mais est beaucoup plus léger, un peu plus facile à prendre en main -et ne s'embarasse pas d'un DOM virtuel. -De par son architecture, il extrêmement bien adapté pour un usage dans un site multipage. -C'est une technologie simple et puissante qui se veut comme le jQuery du web moderne. - -Sass -~~~~ - -`Site officiel `__ - -Sass (Syntactically Awesome Stylesheets) est un langage dynamique de génération de feuilles CSS apparu en 2006. C'est un langage de CSS "amélioré" qui permet l'ajout de variables (à une époque où le CSS ne les supportait pas), de fonctions, mixins ainsi qu'une syntaxe pour imbriquer plus facilement et proprement les règles sur certains éléments. Le Sass est traduit en CSS directement côté serveur et le client ne reçoit que du CSS. - -C'est une technologie stable, mature et pratique qui ne nécessite pas énormément d'apprentissage. - -Fontawesome -~~~~~~~~~~~ - -`Site officiel `__ - -Fontawesome regroupe tout un ensemble d'icônes libres de droits utilisables facilement sur n'importe quelle page web. Ils sont simple à modifier puisque modifiables via le CSS et présentent l'avantage de fonctionner sur tous les navigateurs contrairement à un simple icône unicode qui s'affiche lui différemment selon la plate-forme. - -.. note:: - - C'est une dépendance capricieuse qui évolue très vite et qu'il faut très souvent mettre à jour. - -.. warning:: - - Il a été décidé de **ne pas utiliser** de CDN puisque le site ralentissait régulièrement. Il est préférable de fournir cette dépendance avec le site. - -Documentation -------------- - -Sphinx -~~~~~~ - -`Site officiel `__ - -Sphinx est un outil qui permet la création de documentations intelligentes et très jolies. C'est cet outil qui permet d'écrire le documentation que vous êtes en train de lire actuellement. Développé en 2008 pour la communauté Python, c'est l'outil le plus répandu. Il est utilisé pour la documentation officielle de Python, pour celle de Django, Jinja2 et bien d'autres. - -ReadTheDocs -~~~~~~~~~~~ - -`Site officiel `__ - -C'est un site d'hébergement de documentations utilisant Sphinx. Il propose la génération de documentation à partir de sources et leur hébergement gracieusement pour tout projet open source. C'est le site le plus utilisé et sur lequel sont hébergées bon nombre de documentations comme par exemple celle de Django. La documentation sur ce site est automatiquement générée à chaque nouvelle modification du projet. - -reStructuredText -~~~~~~~~~~~~~~~~ - -`Site officiel `__ - -C'est un langage de balisage léger utilisé notamment dans la documentation du langage Python. C'est le langage dans lequel est écrit l'entièreté de la documentation ci-présente pour que Sphinx puisse la lire et la mettre en forme. - -Workflow --------- - -Git -~~~ - -`Site officiel `__ - -Git est un logiciel de gestion de versions écrit par Linus Torvalds pour les besoins du noyau linux en 2005. C'est ce logiciel qui remplace svn anciennement utilisé pour gérer les sources du projet (rappelez vous, l'ancien site date d'avant 2005). Git est plus complexe à utiliser mais est bien plus puissant, permet de gérer plusieurs version en parallèle et génère des codebases vraiment plus légères puisque seules les modifications sont enregistrées (contrairement à svn qui garde une copie de la codebase par version). - -Git s'étant imposé comme le principal outil de gestion de versions, -sa communauté est très grande et sa documentation très fournie. -Il est également aisé de trouver des outils avec une interface graphique, -qui simplifient grandement son usage. - -GitHub -~~~~~~ - -| `Site officiel `__ -| `Page github du Pôle Informatique de l'AE `__ - -Github est un service web d'hébergement et de gestion de développement de logiciel. -C'est une plate-forme avec interface web permettant de déposer du code géré avec Git -offrant également de l'intégration continue et du déploiement automatique. -C'est au travers de cette plate-forme que le Sith de l'AE est géré. - -Depuis le 1er Octobre 2022, GitHub remplace GitLab dans un soucis de facilité d'entretien, -les machines sur lesquelles tournent le site étant de plus en plus vielles, il devenait très -difficile d'effectuer les mise à jours de sécurité du GitLab sans avoir de soucis matériel -pour l'hébergement et la gestion des projets informatiques de l'AE. - -Sentry -~~~~~~ - -| `Site officiel `__ -| `Instance de l'AE `__ - -Sentry est une plate-forme libre qui permet de se tenir informer des bugs qui ont lieu sur le site. À chaque crash du logiciel (erreur 500), une erreur est envoyée sur la plate-forme et est indiqué précisément à quelle ligne de code celle-ci a eu lieu, à quelle heure, combien de fois, avec quel navigateur la page a été visitée et même éventuellement un commentaire de l'utilisateur qui a rencontré le bug. - -Poetry -~~~~~~~~~~ - -`Utiliser Poetry `__ - -Poetry est un utilitaire qui permet de créer et gérer des environements Python de manière simple et intuitive. Il permet également de gérer et mettre à jour le fichier de dépendances. -L'avantage d'utiliser poetry (et les environnements virtuels en général) est de pouvoir gérer plusieurs projets différents en parallèle puisqu'il permet d'avoir sur sa machine plusieurs environnements différents et donc plusieurs versions d'une même dépendance dans plusieurs projets différent sans impacter le système sur lequel le tout est installé. - -Les dépendances utilisées par poetry sont déclarées dans le fichier `pyproject.toml`, situé à la racine du projet. - -Black -~~~~~ - -`Site officiel `__ - -Pour faciliter la lecture du code, il est toujours appréciable d'avoir une norme d'écriture cohérente. C'est généralement à l'étape de relecture des modifications par les autres contributeurs que sont repérées ces fautes de normes qui se doivent d'être corrigées pour le bien commun. - -Imposer une norme est très fastidieux, que ce soit pour ceux qui relisent ou pour ceux qui écrivent. C'est pour cela que nous utilisons black qui est un formateur automatique de code. Une fois l'outil lancé, il parcours la codebase pour y repérer les fautes de norme et les corrige automatiquement sans que l'utilisateur n'ait à s'en soucier. Bien installé, il peut effectuer ce travail à chaque sauvegarde d'un fichier dans son éditeur, ce qui est très agréable pour travailler. \ No newline at end of file diff --git a/doc/about/versioning.rst b/doc/about/versioning.rst deleted file mode 100644 index 8d32e39a..00000000 --- a/doc/about/versioning.rst +++ /dev/null @@ -1,36 +0,0 @@ -Le versioning -============= - -Dans le monde du développement, nous faisons face à un problème relativement étrange pour un domaine aussi avancé : on est brouillon. - -On teste, on envoie, ça marche pas, on reteste, c'est ok. Par contre, on a oublié plein d'exceptions. Et on refactor. Ça marche mieux mais c'est moins rapide, etc. - -Et derrière tout ça, on fait des trucs qui marchent puis on se retrouve dans la mouise parce qu'on a effacé un morceau de code qui nous aurait servi plus tard. - -Pour pallier ce problème, le programmeur a créé un principe révolutionnaire (ouais... à mon avis, on s'est inspiré d'autres trucs, mais on va dire que c'est nous les créateurs) : le Versioning (*Apparition inexpliquée*). - -D'après projet-isika (c'est pas wikipedia ouais, ils étaient pas clairs eux), le versioning (ou versionnage en français mais c'est quand même vachement dégueu comme mot) consiste à travailler directement sur le code source d'un projet, en gardant toutes les versions précédentes. Les outils du versioning aident les développeurs à travailler parallèlement sur différentes parties du projet et à revenir facilement aux étapes précédentes de leur travail en cas de besoin. L’utilisation d’un logiciel de versioning est devenue quasi-indispensable pour tout développeur, même s’il travaille seul. - -Un versioning pour les gouverner tous -------------------------------------- - -On va vite fait passer sur les différents logiciels de contrôle de version avant de revenir à l'essentiel, le vrai, le beau, l'unique et l'ultime : Git. - -**Source Code Control System (SCCS)**) : Développé en 1972 dans les labos d'IBM, il a été porté sur Unix pour ensuite donner naissance à RCS. -**GNU RCS (Revision Control System)** : RCS est à l'origine un projet universitaire, initié au début des années 1980, et maintenu pendant plus d'une décennie par Walter F. Tichy au sein de l'université Purdue. - -Ce logiciel représente à l'époque une alternative libre au système SCCS, et une évolution technique, notamment par son interface utilisateur, plus conviviale, et une récupération des données, plus rapide, par l'amélioration du stockage des différentes versions. Ce gain de performance provient d'un algorithme appelé en anglais « reverse differences » (ou plus simplement « deltas ») et consiste à stocker la copie complète des versions les plus récentes et conserver uniquement les changements réalisés. - -**CVS (Concurrent Versions System)** : En gros, c'est la première fois qu'on essaie de fusionner des versions *concurrentes* (dis-donc, quel hasard que ce soit des concurrents vu le nom du système !) de fichiers sources. C'était pas forcément compliqué : en gros, il y avait un serveur qui prenait à chaque fois la dernière version de chaque fichier, les développeurs devaient toujours avoir la dernière version du fichier s'ils voulaient éditer celui-ci. Si c'était pas le cas, le serveur les envoyait paitre. - -**SVN (Subversion)** : En gros, c'est comme CVS mais avec quelques améliorations du fait du refactoring complet fait par Apache. Subversion permet notamment le renommage et le déplacement de fichiers ou de répertoires sans en perdre l'historique. On a aussi un versioning sur les metadatas (genre les changements de permissions des fichiers. - -**Git** : Enfin le voilà. Le versioning ultime. Créé par Linus Torvalds en 2005, il permet notamment au bordel qu'est Linux d'être maintenu par des développeurs du monde entier grâce à un système original de version : en gros, chaque ordinateur a une version du code source et il n'y a pas forcément un serveur central qui garde tout (et demande un compte à chaque fois. Bon, maintenant on est de retour au format minitel avec Github mais on va vous montrer comment s'en sortir). Il y a également un système de branche pour pouvoir gérer différentes versions du code en parallèle. Tout est fait sous forme de petits fichiers de versioning qui vont faire des copies des fichiers correspondant à la modification proposée. Bref, c'est trop bien et on a pas fait mieux. - -C'est pas forcément utile de comprendre le fonctionnement interne de Git pour développer (la preuve, je n'ai pas franchement chercher au tréfond du bousin) mais c'est en revanche indispensable de comprendre comment l'utiliser avant de faire n'importe quoi. Du coup, on va voir ci-dessous comment utiliser Git et comment on l'utilise sur le site AE. - -TLDR ----- - -Un système de versioning permet de faire de la merde dans votre code et de pouvoir revenir en arrière malgré tout. Ça permet aussi de coder à plusieurs. -Git est le meilleur système de gestion de version (ou système de versioning) que vous pourrez trouver à l'heure actuelle. Utilisez-le. \ No newline at end of file diff --git a/doc/apps/core.rst b/doc/apps/core.rst deleted file mode 100644 index 8d237032..00000000 --- a/doc/apps/core.rst +++ /dev/null @@ -1,7 +0,0 @@ -Documentation de core -===================== - -.. toctree:: - :maxdepth: 2 - - core/models.rst \ No newline at end of file diff --git a/doc/apps/core/models.rst b/doc/apps/core/models.rst deleted file mode 100644 index 0efaf3d1..00000000 --- a/doc/apps/core/models.rst +++ /dev/null @@ -1,4 +0,0 @@ -Classes liées aux utilisateurs -============================== - -.. autoclass:: core.models.User \ No newline at end of file diff --git a/doc/conf.py b/doc/conf.py deleted file mode 100644 index f43c1cc9..00000000 --- a/doc/conf.py +++ /dev/null @@ -1,65 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# http://www.sphinx-doc.org/en/master/config - -# -- Path setup -------------------------------------------------------------- - -# 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 - -import django - -sys.path.insert(0, os.path.abspath("..")) -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sith.settings") -django.setup() - - -# -- Project information ----------------------------------------------------- - -project = "Sith AE UTBM" -copyright = ( # noqa A001 - "2019, Bartuccio Antoine (Sli), Brunet Pierre (Krophil), Jacquet Florent (Skia)" -) -author = "Bartuccio Antoine (Sli), Brunet Pierre (Krophil), Jacquet Florent (Skia)" - - -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ["sphinx.ext.autodoc", "sphinx_copybutton", "sphinx.ext.autosectionlabel"] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# 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 pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] - - -# -- 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 = "sphinx_rtd_theme" - -# 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"] diff --git a/doc/contacts b/doc/contacts deleted file mode 100644 index fd7ca2af..00000000 --- a/doc/contacts +++ /dev/null @@ -1,4 +0,0 @@ -Contacts de la banque pour pouvoir coder et mettre en place la boutique en ligne: - * Marc Delfils : Marc.DELFILS@ca-franchecomte.fr - * Estelle Mesny : Estelle.MESNY@ca-franchecomte.fr - diff --git a/doc/devenv/populate.rst b/doc/devenv/populate.rst deleted file mode 100644 index 1fcd3dbf..00000000 --- a/doc/devenv/populate.rst +++ /dev/null @@ -1,87 +0,0 @@ -Générer l'environnement avec populate -===================================== - -Lors de l'installation du site en local (via la commande `setup`), la commande **populate** est appelée. - -Cette commande génère entièrement la base de données de développement. Elle se situe dans `core/management/commands/populate.py`. - -Utilisations : - -.. code-block:: shell - - ./manage.py setup # Génère la base de test - ./manage.py setup --prod # Ne génère que le schéma de base et les données strictement nécessaires au fonctionnement - -Les données générées du site dev -================================ - -Par défaut, la base de données du site de prod contient des données nécessaires au fonctionnement du site comme les groupes (voir :ref:`groups-list`), un utilisateur root, les clubs de base et quelques autres instances indispensables. En plus de ces données par défaut, la base de données du site de dev contient des données de test (*fixtures*) pour remplir le site et le rendre exploitable. - -**Voici les clubs générés pour le site de dev :** - - * AE - - - Bibo'UT - - Carte AE - - Guy'UT - - + Woenzel'UT - - - Troll Penché - - * BdF - * Laverie - -**Voici utilisateurs générés pour le site de dev :** - - Le mot de passe de tous les utilisateurs est **plop**. - - * **root** -> Dans le groupe Root et cotisant - * **skia** -> responsable info AE et cotisant, barmen MDE - * **public** -> utilisateur non cotisant et sans groupe - * **subscriber** -> utilisateur cotisant et sans groupe - * **old_subscriber** -> utilisateur anciennement cotisant et sans groupe - * **counter** -> administrateur comptoir - * **comptable** -> administrateur comptabilité - * **guy** -> utilisateur non cotisant et sans groupe - * **rbatsbak** -> utilisateur non cotisant et sans groupe - * **sli** -> cotisant avec carte étudiante attachée au compte, barmen MDE - * **krophil** -> cotisant avec des plein d'écocups, barmen foyer - * **comunity** -> administrateur communication - * **tutu** -> administrateur pédagogie - -Ajouter des fixtures -==================== -.. role:: python(code) - :language: python - -Les fixtures sont contenus dans *core/management/commands/populate.py* après la ligne 205 : :python:`if not options["prod"]:`. - -Pour ajouter une fixtures, il faut : - -* importer la classe à instancier en début de fichier -* créer un objet avec les attributs nécessaires en fin de fichier -* enregistrer l'objet dans la base de données - -.. code-block:: python - - # Exemple pour ajouter un utilisateur - - # Importation de la classe - import core.models import User - - # [...] - - # Création de l'objet - jesus = User( - username="jc", - last_name="Jesus", - first_name="Christ", - email="son@god.cloud", - date_of_birth="2020-24-12", - is_superuser=False, - is_staff=True, - ) - jesus.set_password("plop") - # Enregistrement dans la base de donnée - jesus.save() \ No newline at end of file diff --git a/doc/frequent/subscriptions.rst b/doc/frequent/subscriptions.rst deleted file mode 100644 index fc446201..00000000 --- a/doc/frequent/subscriptions.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. _add_subscription: - -Ajouter une nouvelle cotisation -=============================== - -Il arrive régulièrement que le type de cotisation proposé varie en prix et en durée au cours des années. Le projet étant pensé pour être utilisé par d'autres associations dans la mesure du possible, ces cotisations sont configurables directement dans les paramètres du projet. - -Comprendre la configuration ---------------------------- - -Pour modifier les cotisations disponibles, tout se gère dans la configuration avec la variable *SITH_SUBSCRIPTIONS*. Dans cet exemple, nous allons ajouter une nouvelle cotisation d'un mois. - -.. code-block:: python - - from django.utils.translation import gettext_lazy as _ - - SITH_SUBSCRIPTIONS = { - # Voici un échantillon de la véritable configuration à l'heure de l'écriture. - # Celle-ci est donnée à titre d'exemple pour mieux comprendre comment cela fonctionne. - "un-semestre": {"name": _("One semester"), "price": 15, "duration": 1}, - "deux-semestres": {"name": _("Two semesters"), "price": 28, "duration": 2}, - "cursus-tronc-commun": { - "name": _("Common core cursus"), - "price": 45, - "duration": 4, - }, - "cursus-branche": {"name": _("Branch cursus"), "price": 45, "duration": 6}, - "cursus-alternant": {"name": _("Alternating cursus"), "price": 30, "duration": 6}, - "membre-honoraire": {"name": _("Honorary member"), "price": 0, "duration": 666}, - "un-jour": {"name": _("One day"), "price": 0, "duration": 0.00555333}, - - # On rajoute ici notre cotisation - # Elle se nomme "Un mois" - # Coûte 6€ - # Dure 1 mois (on résonne en semestre, ici c'est 1/6 de semestre) - "un-mois": {"name": _("One month"), "price": 6, "duration": 0.166} - } - -Créer une migration -------------------- - -La modification de ce paramètre est étroitement lié à la génération de la base de données. Cette variable est utilisé dans l'objet *Subscription* pour générer les *subscription_type*. Le modifier requiers de générer une migration de basse de données. - -.. code-block:: bash - - ./manage.py makemigrations subscription - -.. note:: - - N'oubliez pas d'appliquer black sur le fichier de migration généré. - -Rajouter la traduction pour la cotisation ------------------------------------------ - -Comme on peut l'observer, la cotisation a besoin d'un nom qui est internationalisé. Il est donc nécessaire de le traduire en français. Pour rajouter notre traduction de *"One month"* il faut se référer à cette partie de la documentation : :ref:`translations`. diff --git a/doc/frequent/weekmail.rst b/doc/frequent/weekmail.rst deleted file mode 100644 index e8d920f4..00000000 --- a/doc/frequent/weekmail.rst +++ /dev/null @@ -1,53 +0,0 @@ -Modifier le weekmail -==================== - -Le site est capable de générer des mails automatiques composé de l’agrégation d'articles composé par les administrateurs de clubs. Le contenu est inséré dans un template standardisé et contrôlé directement dans le code. Il arrive régulièrement que l'équipe communication souhaite modifier ce template. Que ce soit les couleurs, l'agencement ou encore la bannière ou le footer, voici tout ce qu'il y a à savoir sur le fonctionnement du weekmail en commençant par la classe qui le contrôle. - -.. autoclass:: com.models.Weekmail - :members: - -Modifier la bannière et le footer ---------------------------------- - -Comme on peut l'observer plus haut, ces éléments sont contrôlés par les méthodes *get_banner* et *get_footer* de la classe *Weekmail*. Les modifier est donc très simple, il suffit de modifier le contenu de la fonction et de rajouter les nouvelles images dans les statics. - -Les images sont à ajouter dans dans **core/static/com/img** et sont à nommer selon le type (banner ou footer), le semestre (Automne ou Printemps) et l'année. - -Exemple : *weekmail_bannerA18.jpg* pour la bannière de l'automne 2018. - -.. code-block:: python - - # Sélectionner le fichier de bannière pour le weekmail de l'automne 2018 - - def get_banner(self): - return "http://" + settings.SITH_URL + static("com/img/weekmail_bannerA18.jpg") - -.. note:: - - Penser à prendre les images au format **jpg** et que les images soient le plus léger possible, c'est bien mieux pour l'utilisateur final. - -.. note:: - - Pensez à laisser les anciennes images dans le dossier pour que les anciens weekmails ne soient pas affectés par les changements. - -Modifier le template --------------------- - -Comme on peut le voir dans la documentation de la classe, il existe deux templates différents. Un des templates est en texte pur et sert pour le rendu dégradé des lecteurs de mails ne supportant pas le HTML et un autre fait un rendu en HTML. - -Ces deux templates sont respectivement accessibles aux emplacements suivants : - -* com/templates/com/weekmail_renderer_html.jinja -* com/templates/com/weekmail_renderer_text.jinja - -.. note:: - - Pour le rendu HTML, pensez à utiliser le CSS et le javascript le plus simple possible pour que le rendu se fasse correctement dans les clients mails qui sont souvent capricieux. - -.. note:: - - Le CSS est inclus statiquement pour que toute modification ultérieure de celui-ci n'affecte pas les versions précédemment envoyées. - -.. warning:: - - Si vous souhaitez ajouter du contenu, n'oubliez pas de bien inclure ce contenu dans les deux templates. diff --git a/doc/header b/doc/header deleted file mode 100644 index 9ab735b7..00000000 --- a/doc/header +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding:utf-8 -* -# -# Copyright 2023 © AE UTBM -# ae@utbm.fr / ae.info@utbm.fr -# -# This file is part of the website of the UTBM Student Association (AE UTBM), -# https://ae.utbm.fr. -# -# You can find the source code of the website at https://github.com/ae-utbm/sith3 -# -# LICENSED UNDER THE GNU GENERAL PUBLIC LICENSE VERSION 3 (GPLv3) -# SEE : https://raw.githubusercontent.com/ae-utbm/sith3/master/LICENSE -# OR WITHIN THE LOCAL FILE "LICENSE" -# -# \ No newline at end of file diff --git a/doc/index.rst b/doc/index.rst deleted file mode 100644 index b97e8437..00000000 --- a/doc/index.rst +++ /dev/null @@ -1,101 +0,0 @@ -.. Sith AE UTBM documentation master file, created by - sphinx-quickstart on Thu Aug 8 19:24:14 2019. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Bienvenue sur la documentation du Sith de l'AE -============================================== - -.. include:: ../README.rst - -.. toctree:: - :maxdepth: 2 - :caption: À propos du projet: - - about/introduction - about/tech - about/versioning - -.. toctree:: - :maxdepth: 2 - :caption: Bien démarrer - - start/install - start/structure - start/hello_world - - start/translations - - start/devtools - -.. toctree:: - :maxdepth: 2 - :caption: La surcouche "Site AE" - - overlay/rights - overlay/groups - -.. toctree:: - :maxdepth: 2 - :caption: Contenu de l'environnement de développement - - devenv/populate - -.. toctree:: - :maxdepth: 1 - :caption: Modifications fréquentes - - frequent/subscriptions - frequent/weekmail - -.. toctree:: - :maxdepth: 3 - :caption: Documentation des apps - - apps/core - -.. toctree:: - :maxdepth: 2 - :caption: Divers - - misc/md_syntax - misc/helpers - misc/direnv - misc/prod - -Documentations complémentaires ------------------------------- - -Python et Django -~~~~~~~~~~~~~~~~ - -* `Apprendre Python `__ -* `Apprendre Django `__ -* `Documentation de Django `__ -* `Classy Class-Based Views `__ - -HTML/Jinja/JS/(S)CSS -~~~~~~~~~~~~~~~~~~~~ - -* `Cours sur le javascript `__ -* `Cours sur jQuery `__ -* `Cours sur le HTML et CSS `__ -* `Documentation sur les grilles CSS `__ -* `Guide pour le SASS `__ -* `Documentation de fontawesome `__ -* `Documentation pour Jinja2 `__ - -Git -~~~ - -* `Cours sur Git `__ -* `Livre sur Git `__ - - -Documents téléchargeables -------------------------- - -* :download:`Rapport de la TW de Skia sur la création du site ` -* :download:`Rapport sur la TO de Skia et LoJ ` -* :download:`Manuel du service E-transactions ` -* :download:`Guide de trésorerie ` \ No newline at end of file diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100644 index 922152e9..00000000 --- a/doc/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/doc/misc/direnv.rst b/doc/misc/direnv.rst deleted file mode 100644 index 7801799b..00000000 --- a/doc/misc/direnv.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _direnv: - -Utiliser direnv -=============== - -Pour éviter d'avoir à sourcer l'environnement à chaque fois qu'on rentre dans le projet, il est possible d'utiliser l'utilitaire `direnv `__. - -.. sourcecode:: bash - - # Installation de l'utilitaire - - # Debian et Ubuntu - sudo apt install direnv - # Mac - brew install direnv - - - # Installation dans la config - # Si sur bash - echo 'eval "$(direnv hook bash)"' >> ~/.bashrc - # Si sur ZSH - echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc - - exit # On redémarre le terminal - - # Une fois dans le dossier du projet site AE - direnv allow . - -Une fois que cette configuration a été appliquée, aller dans le dossier du site applique automatiquement l'environnement virtuel, cela fait beaucoup moins de temps perdu pour tout le monde. - -Direnv est un utilitaire très puissant et qui peut s'avérer pratique dans bien des situations, n'hésitez pas à aller vous renseigner plus en détail sur celui-ci. \ No newline at end of file diff --git a/doc/misc/helpers.rst b/doc/misc/helpers.rst deleted file mode 100644 index d961b37c..00000000 --- a/doc/misc/helpers.rst +++ /dev/null @@ -1,17 +0,0 @@ -Commandes utiles -================ - -Appliquer le header de licence sur tout le projet -------------------------------------------------- - -.. code-block:: bash - - for f in $(find . -name "*.py" ! -path "*migration*" ! -path "./env/*" ! -path "./doc/*"); do cat ./doc/header "$f" > /tmp/temp && mv /tmp/temp "$f"; done - -Compter le nombre de lignes de code ------------------------------------ - -.. code-block:: bash - - sudo apt install cloc - cloc --exclude-dir=doc,env . diff --git a/doc/misc/md_syntax.rst b/doc/misc/md_syntax.rst deleted file mode 100644 index a4882ef4..00000000 --- a/doc/misc/md_syntax.rst +++ /dev/null @@ -1,20 +0,0 @@ -Syntaxe markdown utilisée dans le site -====================================== - -.. note:: - - Si vous faites une mise à jour sur le parseur markdown, il est bon de documenter cette mise à jour dans la page de référence *doc/SYNTAX.md*. Mettre à jour ce fichier vas casser les tests si vous ne mettez pas à jour le fichier *doc/SYNTAX.html* qui lui correspond juste après. Pour mettre à jour ce fichier il suffit d'utiliser la commande - - :: - - ./manage.py markdown > doc/SYNTAX.html - -.. warning:: - - Le rendu de cette aide est fait via Sphinx, il peut représenter quelques différences avec la réalité. Il est possible de télécharger juste en dessous les versions brutes. - -* :download:`Fichier d'aide en markdown <../SYNTAX.md>` -* :download:`Fichier d'aide rendu en HTML <../SYNTAX.html>` - -.. raw:: html - :file: ../SYNTAX.html diff --git a/doc/misc/prod.rst b/doc/misc/prod.rst deleted file mode 100644 index 959a16af..00000000 --- a/doc/misc/prod.rst +++ /dev/null @@ -1,21 +0,0 @@ -Configurer pour la production -============================= - -Configurer Sentry ------------------ - -Pour connecter l'application à une instance de sentry (ex: https://sentry.io) il est nécessaire de configurer la variable **SENTRY_DSN** dans le fichier *settings_custom.py*. Cette variable est composée d'un lien complet vers votre projet sentry. - -Récupérer les statiques ------------------------ - -Nous utilisons du SCSS dans le projet. En environnement de développement (DEBUG=True), le SCSS est compilé à chaque fois que le fichier est demandé. Pour la production, le projet considère que chacun des fichier est déjà compilé, et, pour ce faire, il est nécessaire d'utiliser les commandes suivantes dans l'ordre : - -.. code-block:: bash - - ./manage.py collectstatic # Pour récupérer tous les fichiers statiques - ./manage.py compilestatic # Pour compiler les fichiers SCSS qu'ils contiennent - -.. note:: - - Le dossier où seront enregistrés ces fichiers statiques peut être changé en modifiant la variable *STATIC_ROOT* dans les paramètres. \ No newline at end of file diff --git a/doc/modules.dia b/doc/modules.dia deleted file mode 100644 index 17f71d53..00000000 Binary files a/doc/modules.dia and /dev/null differ diff --git a/doc/modules_full.png b/doc/modules_full.png deleted file mode 100644 index 57098b89..00000000 Binary files a/doc/modules_full.png and /dev/null differ diff --git a/doc/modules_maj.dia b/doc/modules_maj.dia deleted file mode 100644 index 59df236b..00000000 Binary files a/doc/modules_maj.dia and /dev/null differ diff --git a/doc/modules_maj.png b/doc/modules_maj.png deleted file mode 100644 index 2dcd5913..00000000 Binary files a/doc/modules_maj.png and /dev/null differ diff --git a/doc/modules_simple.png b/doc/modules_simple.png deleted file mode 100644 index 06ca3be1..00000000 Binary files a/doc/modules_simple.png and /dev/null differ diff --git a/doc/overlay/groups.rst b/doc/overlay/groups.rst deleted file mode 100644 index 3ad30a65..00000000 --- a/doc/overlay/groups.rst +++ /dev/null @@ -1,64 +0,0 @@ -Le système de groupes -===================== - -Il existe deux types de groupes sur le site AE. L'un se base sur des groupes enregistrés en base de données pendant le développement, c'est le système de groupes réels. L'autre est plus dynamique et comprend tous les groupes générés pendant l'exécution et l'utilisation du programme. Cela correspond généralement aux groupes liés aux clubs. Ce sont les méta groupes. - -La définition d'un groupe --------------------------- - -Comme on peut l'observer, il existe une entrée de groupes dans la base de données. Cette classe implémente à la fois les groupes réels et les méta groupes. - -Ce qui différencie ces deux types de groupes ce sont leur utilisation et leur manière d'être générés. La distinction est faite au travers de la propriété `is_meta`. - -.. autoclass:: core.models.Group - :members: - -Les groupes réels ------------------ - -Pour simplifier l'utilisation de ces deux types de groupe, il a été crée une classe proxy (c'est à dire qu'elle ne correspond pas à une vraie table en base de donnée) qui encapsule leur utilisation. RealGroup peut être utilisé pour créer des groupes réels dans le code et pour faire une recherche sur ceux-ci (dans le cadre d'une vérification de permissions par exemple). - -.. autoclass:: core.models.RealGroup - :members: - -.. note:: - - N'oubliez pas de créer une variable dans les settings contenant le numéro du groupe pour facilement l'utiliser dans le code plus tard. Ces variables sont du type `SITH_GROUP_GROUPE_NAME_ID`. - -Les méta groupes ----------------- - -Les méta groupes, comme expliqué précédemment, sont utilisés dans les contextes où il est nécessaire de créer un groupe *on runtime*. Les objets `MetaGroup`, bien que dynamiques, doivent tout de même s'enregistrer en base de donnée comme des vrais groupes afin de pouvoir être affectés dans les permissions d'autres objets, comme un forum ou une page de wiki par exemple. C'est principalement utilisé au travers des clubs qui génèrent automatiquement deux groupes à leur création : - -* club-bureau : contient tous les membres d'un club **au dessus** du grade défini dans settings.SITH_MAXIMUM_FREE_ROLE. -* club-membres : contient tous les membres d'un club **en dessous** du grade défini dans settings.SITH_MAXIMUM_FREE_ROLE. - -.. autoclass:: core.models.MetaGroup - :members: - - -.. _groups-list: - -La liste des groupes réels --------------------------- - -Les groupes réels existant par défaut dans le site sont les suivants : - -Groupes gérés automatiquement par le site : - -* **Public** -> tous les utilisateurs du site -* **Subscribers** -> tous les cotisants du site -* **Old subscribers** -> tous les anciens cotisants - -Groupes gérés par les administrateurs (à appliquer à la main sur un utilisateur) : - -* **Root** -> administrateur global du site -* **Accounting admin** -> les administrateurs de la comptabilité -* **Communication admin** -> les administrateurs de la communication -* **Counter admin** -> les administrateurs des comptoirs (foyer et autre) -* **SAS admin** -> les administrateurs du SAS -* **Forum admin** -> les administrateurs du forum -* **Pedagogy admin** -> les administrateurs de la pédagogie (guide des UVs) -* **Banned from buying alcohol** -> les utilisateurs interdits de vente d'alcool (non mineurs) -* **Banned from counters** -> les utilisateurs interdits d'utilisation des comptoirs -* **Banned to subscribe** -> les utilisateurs interdits de cotisation diff --git a/doc/overlay/rights.rst b/doc/overlay/rights.rst deleted file mode 100644 index 1e03f536..00000000 --- a/doc/overlay/rights.rst +++ /dev/null @@ -1,159 +0,0 @@ -La gestion des droits -===================== - -La gestion des droits dans l'association étant très complexe, le système de permissions intégré dans Django ne suffisait pas, il a donc fallu créer et intégrer le notre. - -La gestion des permissions se fait directement sur un modèle, il existe trois niveaux de permission : - -* Édition des propriétés de l'objet -* Édition de certaines valeurs l'objet -* Voir l'objet - -Protéger un modèle ------------------- - -Lors de l'écriture d'un modèle, il est très simple de définir des permissions. Celle-ci peuvent être basées sur des groupes et/ou sur des fonctions personnalisées. - -Nous allons présenter ici les deux techniques. Dans un premier temps nous allons protéger une classe Article par groupes. - -.. code-block:: python - - from django.db import models - from django.conf import settings - from django.utils.translation import gettext_lazy as _ - - from core.views import * - from core.models import User, Group - - # Utilisation de la protection par groupe - class Article(models.Model): - - title = models.CharField(_("title"), max_length=100) - content = models.TextField(_("content")) - - # Ne peut pas être une liste - # Groupe possédant l'objet - # Donne les droits d'édition des propriétés de l'objet - owner_group = models.ForeignKey( - Group, related_name="owned_articles", default=settings.SITH_GROUP_ROOT_ID - ) - - # Doit être une liste - # Tous les groupes qui seront ajouté dans ce champ auront les droits d'édition de l'objet - edit_group = models.ManyToManyField( - edit_groups = models.ManyToManyField( - Group, - related_name="editable_articles", - verbose_name=_("edit groups"), - blank=True, - ) - ) - - # Doit être une liste - # Tous les groupes qui seront ajouté dans ce champ auront les droits de vue de l'objet - view_groups = models.ManyToManyField( - Group, - related_name="viewable_articles", - verbose_name=_("view groups"), - blank=True, - ) - -Voici maintenant comment faire en définissant des fonctions personnalisées. Cette deuxième solution permet, dans le cas où la première n'est pas assez puissante, de créer des permissions complexes et fines. Attention à bien les rendre lisibles et de bien documenter. - -.. code-block:: python - - from django.db import models - from django.utils.translation import gettext_lazy as _ - - from core.views import * - from core.models import User, Group - - # Utilisation de la protection par fonctions - class Article(models.Model): - - title = models.CharField(_("title"), max_length=100) - content = models.TextField(_("content")) - - # Donne ou non les droits d'édition des propriétés de l'objet - # Un utilisateur dans le bureau AE aura tous les droits sur cet objet - def is_owned_by(self, user): - return user.is_board_member - - # Donne ou non les droits d'édition de l'objet - # L'objet ne sera modifiable que par un utilisateur cotisant - def can_be_edited_by(self, user): - return user.is_subscribed - - # Donne ou non les droits de vue de l'objet - # Ici, l'objet n'est visible que par un utilisateur connecté - def can_be_viewed_by(self, user): - return not user.is_anonymous - -.. note:: - - Si un utilisateur est autorisé à un niveau plus élevé que celui auquel il est testé, le système le détectera automatiquement et les droits lui seront accordé. Par défaut, les seuls utilisateurs ayant des droits quelconques sont les *superuser* de Django et les membres du bureau AE qui sont définis comme *owner*. - -Appliquer les permissions -------------------------- - -Dans un template -~~~~~~~~~~~~~~~~ - -Il existe trois fonctions de base sur lesquelles reposent les vérifications de permission. Elles sont disponibles dans le contexte par défaut du moteur de template et peuvent être utilisées à tout moment. - -Tout d'abord, voici leur documentation et leur prototype. - -.. autofunction:: core.views.can_edit_prop -.. autofunction:: core.views.can_edit -.. autofunction:: core.views.can_view - -Voici un exemple d'utilisation dans un template : - -.. code-block:: html+jinja - - {# ... #} - {% if can_edit(club, user) %} - {{ club }} - {% endif %} - -Dans une vue -~~~~~~~~~~~~ - -Généralement, les vérifications de droits dans les templates se limitent au liens à afficher puisqu'il ne faut pas mettre de logique autre que d'affichage à l'intérieur. C'est donc généralement au niveau des vues que cela a lieu. - -Notre système s'appuie sur un système de mixin à hériter lors de la création d'une vue basée sur une classe. Ces mixins ne sont compatibles qu'avec les classes récupérant un objet ou une liste d'objet. Dans le cas d'un seul objet, une permission refusée est levée lorsque l'utilisateur n'as pas le droit de visionner la page. Dans le d'une liste d'objet, le mixin filtre les objets non autorisés et si aucun ne l'est l'utilisateur recevra une liste vide d'objet. - -Voici un exemple d'utilisation en reprenant l'objet Article crée précédemment : - -.. code-block:: python - - from django.views.generic import CreateView, ListView - - from core.views import CanViewMixin, CanCreateMixin - - from .models import Article - - ... - - # Il est important de mettre le mixin avant la classe héritée de Django - # L'héritage multiple se fait de droite à gauche et les mixins ont besoin - # d'une classe de base pour fonctionner correctement. - class ArticlesListView(CanViewMixin, ListView): - - model = Article # On base la vue sur le modèle Article - ... - - # Même chose pour une vue de création de l'objet Article - class ArticlesCreateView(CanCreateMixin, CreateView): - - model = Article - -Le système de permissions de propose plusieurs mixins différents, les voici dans leur intégralité. - -.. autoclass:: core.views.CanCreateMixin -.. autoclass:: core.views.CanEditPropMixin -.. autoclass:: core.views.CanEditMixin -.. autoclass:: core.views.CanViewMixin -.. autoclass:: core.views.UserIsRootMixin -.. autoclass:: core.views.FormerSubscriberMixin -.. autoclass:: core.views.UserIsLoggedMixin \ No newline at end of file diff --git a/doc/start/devtools.rst b/doc/start/devtools.rst deleted file mode 100644 index 1cc9dc3a..00000000 --- a/doc/start/devtools.rst +++ /dev/null @@ -1,120 +0,0 @@ -Configurer son environnement de développement -============================================= - -Le projet n'est en aucun cas lié à un quelconque environnement de développement. -Il est possible pour chacun de travailler avec les outils dont il a envie et d'utiliser l'éditeur de code avec lequel il est le plus à l'aise. - -Pour donner une idée, Skia a écrit une énorme partie de projet avec l'éditeur *Vim* sur du GNU/Linux -alors que Sli a utilisé *Sublime Text* sur MacOS et que Maréchal travaille avec PyCharm -sur ~~Windows muni de WSL~~ Arch Linux btw. - -Configurer les pre-commit hooks --------------------------------- - -La procédure habituelle pour contribuer au projet consiste à commit des modifications, puis à les push sur le dépôt distant et à ouvrir une pull request. Cette PR va faire tourner les outils de vérification de la qualité de code. Si la vérification échoue, la PR est bloquée, et il faut réparer le problème (ce qui implique de push un micro-commit ou de push force sur la branche). - -Dans l'idéal, on aimerait donc qu'il soit impossible d'oublier de faire tourner ces vérification. Pour ça, il existe un mécanisme : les pre-commits hooks. Ce sont des actions qui tournent automatiquement lorsque vous effectuez un `git commit`. Ces dernières vont analyser et éventuellement modifier le code, avant que Git n'ajoute effectivement le commit sur l'arbre git. Voyez ça comme une micro-CI qui tourne en local. - -Les git hooks sont une fonctionnalité par défaut de Git. Cependant, leur configuration peut-être un peu embêtante si vous le faites manuellement. Pour gérer ça plus simplement, nous utilisons le logiciel python [pre-commit](https://pre-commit.com/) qui permet de contrôler leur installation via un seul fichier de configuration, placé à la racine du projet (plus précisément, il s'agit du fichier `.pre-commit-config.yaml`). - -.. note:: - - Les pre-commits sont également utilisés dans la CI. Si ces derniers fonctionnent localement, vous avez la garantie que la pipeline ne sera pas fachée. ;) - -C'est une fonctionnalité de git lui même mais c'est assez embêtant à gérer manuellement. Pour gérer ça plus simplement, nous utilisons le logiciel python [pre-commit](https://pre-commit.com/) qui permet de contrôller leur installation via un fichier yaml. - -Les pre-commits sont également utilisés dans la CI, si les pre-commits fonctionnent localement, vous avez la garantie que la pipeline ne sera pas fachée ;). - -Le logiciel est installé par défaut par poetry. Il suffit ensuite de lancer : - -.. code-block:: - - pre-commit install - -Tout se fait ensuite automatiquement lorsqu'on utilise git normalement pour commit. Pour appliquer les pre-commits manuellement, il est possible d'appeler soi même les pre-commits - -.. code-block:: - - pre-commit run --all-files - - -Configurer Ruff pour son éditeur ---------------------------------- - -.. note:: - - Ruff est inclus dans les dépendances du projet. - Si vous avez réussi à terminer l'installation, vous n'avez donc pas de configuration - supplémentaire à effectuer. - -Pour utiliser Ruff, placez-vous à la racine du projet et lancez la commande suivante : - -.. code-block:: - - ruff format # pour formatter le code - ruff check # pour linter le code - -Ruff va alors faire son travail sur l'ensemble du projet puis vous dire -si des documents ont été reformatés (si vous avez fait `ruff format`) -ou bien s'il y a des erreurs à réparer (si vous avez faire `ruff check`). - -Appeler Ruff en ligne de commandes avant de pousser votre code sur Github -est une technique qui marche très bien. -Cependant, vous risquez de souvent l'oublier. -Or, lorsque le code ne respecte pas les standards de qualité, -la pipeline bloque les PR sur les branches protégées. - -Pour éviter de vous faire régulièrement avoir, vous pouvez configurer -votre éditeur pour que Ruff fasse son travail automatiquement à chaque édition d'un fichier. -Nous tenterons de vous faire ici un résumé pour deux éditeurs de textes populaires -que sont VsCode et Sublime Text. - -VsCode -~~~~~~ - -Installez l'extension Ruff pour VsCode. -Ensuite, ajoutez ceci dans votre configuration : - -.. sourcecode:: json - - { - "[python]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "charliermarsh.ruff" - } - } - -Sublime Text -~~~~~~~~~~~~ - -Vous devez installer ce plugin : https://packagecontrol.io/packages/LSP-ruff. -Suivez ensuite les instructions données dans la description du plugin. - -Dans la configuration de votre projet, ajoutez ceci: - -.. sourcecode:: json - - { - "settings": { - "lsp_format_on_save": true, - "LSP": { - "LSP-ruff": { - "enabled": true, - } - } - } - } - - -Si vous utilisez le plugin `anaconda `__, pensez à modifier les paramètres du linter pep8 pour éviter de recevoir des warnings dans le formatage de ruff comme ceci : - -.. sourcecode:: json - - { - "pep8_ignore": [ - "E203", - "E266", - "E501", - "W503" - ] - } diff --git a/doc/start/hello_world.rst b/doc/start/hello_world.rst deleted file mode 100644 index 88e585bf..00000000 --- a/doc/start/hello_world.rst +++ /dev/null @@ -1,275 +0,0 @@ -Créer une nouvelle application Hello World -========================================== - -L'objectif de ce petit tutoriel est de prendre rapidement en main les vues, les urls et les modèles de Django. On créera une application nommée *hello* qui fournira une page affichant "Hello World", une autre page qui affichera en plus un numéro qui sera récupéré depuis l'URL ainsi qu'une page affichant un élément récupéré de la base de données, le tout au milieu d'une page typique du Sith AE. - -Créer l'application -------------------- - -La première étape est de crée l'application. Cela se fait très simplement avec les outils fournis par le framework. - -.. code-block:: bash - - ./manage.py startapp hello - -Il faut ensuite activer l'application dans les paramètres du projet en l'ajoutant dans la liste des applications installées. - -.. code-block:: python - - # sith/settings.py - - # ... - - INSTALLED_APPS = ( - ... - "hello", - ) - -Enfin, on vas inclure les URLs de cette application dans le projet sous le préfixe */hello/*. - -.. code-block:: python - - # sith/urls.py - urlpatterns = [ - ... - path("hello/", include("hello.urls", namespace="hello", app_name="hello")), - ] - -Un Hello World simple ---------------------- - -Dans un premier temps, nous allons créer une vue qui va charger un template en utilisant le système de vues basé sur les classes de Django. - -.. code-block:: python - - # hello/views.py - - from django.views.generic import TemplateView - - # Toute la logique pour servir la vue et parser le template - # est directement héritée de TemplateView - class HelloView(TemplateView): - template_name = "hello/hello.jinja" # On indique quel template utiliser - -On vas ensuite créer le template. - -.. code-block:: html+jinja - - {# hello/templates/hello/hello.jinja #} - - {# On étend le template de base du Sith #} - {% extends "core/base.jinja" %} - - {# On remplis la partie titre du template étendu #} - {# Il s'agit du titre qui sera affiché dans l'onglet du navigateur #} - {% block title %} - Hello World - {% endblock %} - - {# On remplis le contenu de la page #} - {% block content %} -

Hello World !

- {% endblock %} - -Enfin, on crée l'URL. On veut pouvoir appeler la page depuis https://localhost:8000/hello, le préfixe indiqué précédemment suffit donc. - -.. code-block:: python - - # hello/urls.py - from django.urls import path - from hello.views import HelloView - - urlpatterns = [ - # Le préfixe étant retiré lors du passage du routeur d'URL - # dans le fichier d'URL racine du projet, l'URL à matcher ici est donc vide - path("", HelloView.as_view(), name="hello"), - ] - -Et voilà, c'est fini, il ne reste plus qu'à lancer le serveur et à se rendre sur la page. - -Manipuler les arguments d'URL ------------------------------ - -Dans cette partie, on cherche à détecter les numéros passés dans l'URL pour les passer dans le template. On commence par ajouter cet URL modifiée. - -.. code-block:: python - - # hello/urls.py - from django.urls import path - from hello.views import HelloView - - urlpatterns = [ - path("", HelloView.as_view(), name="hello"), - path("", HelloView.as_view(), name="hello"), - ] - -Cette deuxième URL vas donc appeler la classe crée tout à l'heure en lui passant une variable *hello_id* dans ses *kwargs*, nous allons la récupérer et la passer dans le contexte du template en allant modifier la vue. - -.. code-block:: python - - # hello/views.py - from django.views.generic import TemplateView - - class HelloView(TemplateView): - template_name = "hello/hello.jinja" - - # C'est la méthode appelée juste avant de définir le type de requête effectué - def dispatch(self, request, *args, **kwargs): - - # On récupère l'ID et on le met en attribut - self.hello_id = kwargs.pop("hello_id", None) - - # On reprend le déroulement normal en appelant la méthode héritée - return super(HelloView, self).dispatch(request, *args, **kwargs) - - # Cette méthode renvoie les variables qui seront dans le contexte du template - def get_context_data(self, **kwargs): - - # On récupère ce qui était sensé être par défaut dans le contexte - kwargs = super(HelloView, self).get_context_data(**kwargs) - - # On ajoute notre ID - kwargs["hello_id"] = self.hello_id - - # On renvoie le contexte - return kwargs - -Enfin, on modifie le template en rajoutant une petite condition sur la présence ou non de cet ID pour qu'il s'affiche. - -.. code-block:: html+jinja - - {# hello/templates/hello/hello.jinja #} - {% extends "core/base.jinja" %} - - {% block title %} - Hello World - {% endblock title %} - - {% block content %} -

- Hello World ! - {% if hello_id -%} - {{ hello_id }} - {%- endif -%} -

- {% endblock content %} - -.. note:: - - Il est tout à fait possible d'utiliser les arguments GET passés dans l'URL. Dans ce cas, il n'est pas obligatoire de modifier l'URL et il est possible de récupérer l'argument dans le dictionnaire `request.GET`. - -À l'assaut des modèles ----------------------- - -Pour cette dernière partie, nous allons ajouter une entrée dans la base de données et l'afficher dans un template. Nous allons ainsi créer un modèle nommé *Article* qui contiendra une entrée de texte pour le titre et une autre pour le contenu. - -Commençons par le modèle en lui même. - -.. code-block:: python - - # hello/models.py - from django.db import models - - - class Article(models.Model): - - title = models.CharField("titre", max_length=100) - content = models.TextField("contenu") - -Continuons avec une vue qui sera en charge d'afficher l'ensemble des articles présent dans la base. - -.. code-block:: python - - # hello/views.py - - from django.views.generic import ListView - - from hello.models import Article - - ... - - # On hérite de ListView pour avoir plusieurs objets - class ArticlesListView(ListView): - - model = Article # On base la vue sur le modèle Article - template_name = "hello/articles.jinja" - -On n'oublie pas l'URL. - -.. code-block:: python - - from hello.views import HelloView, ArticlesListView - - urlpatterns = [ - ... - path("articles/", ArticlesListView.as_view(), name="articles_list") - ] - -Et enfin le template. - -.. code-block:: html+jinja - - {# hello/templates/hello/articles.jinja #} - {% extends "core/base.jinja" %} - - {% block title %} - Hello World Articles - {% endblock title %} - - {% block content %} - {# Par défaut une liste d'objets venant de ListView s'appelle object_list #} - {% for article in object_list %} -

{{ article.title }}

-

{{ article.content }}

- {% endfor %} - {% endblock content %} - -Maintenant que toute la logique de récupération et d'affichage est terminée, la page est accessible à l'adresse https://localhost:8000/hello/articles. - -Mais, j'ai une erreur ! Il se passe quoi ?! Et bien c'est simple, nous avons créé le modèle mais il n'existe pas dans la base de données. Il est dans un premier temps important de créer un fichier de migrations qui contient des instructions pour la génération de celles-ci. Ce sont les fichiers qui sont enregistrés dans le dossier migration. Pour les générer à partir des classes de modèles qu'on vient de manipuler il suffit d'une seule commande. - -.. code-block:: bash - - ./manage.py makemigrations - -Un fichier *hello/migrations/0001_initial.py* se crée automatiquement, vous pouvez même aller le voir. - -.. note:: - - Il est tout à fait possible de modifier à la main les fichiers de migrations. C'est très intéressant si par exemple il faut appliquer des modifications sur les données d'un modèle existant après cette migration mais c'est bien au delà du sujet de ce tutoriel. Référez vous à la documentation pour ce genre de choses. - -J'ai toujours une erreur ! Mais oui, c'est pas fini, faut pas aller trop vite. Maintenant il faut appliquer les modifications à la base de données. - -.. code-block:: bash - - ./manage.py migrate - -Et voilà, là il n'y a plus d'erreur. Tout fonctionne et on a une superbe page vide puisque aucun contenu pour cette table n'est dans la base. Nous allons en rajouter. Pour cela nous allons utiliser le fichier *core/management/commands/populate.py* qui contient la commande qui initialise les données de la base de données de test. C'est un fichier très important qu'on viendra à modifier assez souvent. Nous allons y ajouter quelques articles. - -.. code-block:: python - - # core/management/commands/populate.py - from hello.models import Article - - ... - - class Command(BaseCommand): - - ... - - def handle(self, *args, **options): - - ... - - # les deux syntaxes ci-dessous sont correctes et donnent le même résultat - Article(title="First hello", content="Bonjour tout le monde").save() - Article.objects.create(title="Tutorial", content="C'était un super tutoriel") - - -On regénère enfin les données de test en lançant la commande que l'on vient de modifier. - -.. code-block:: bash - - ./manage.py setup - -On revient sur https://localhost:8000/hello/articles et cette fois-ci nos deux articles apparaissent correctement. \ No newline at end of file diff --git a/doc/start/install.rst b/doc/start/install.rst deleted file mode 100644 index 257fcf46..00000000 --- a/doc/start/install.rst +++ /dev/null @@ -1,242 +0,0 @@ -Installer le projet -=================== - -Dépendances du système ----------------------- - -Certaines dépendances sont nécessaires niveau système : - -* poetry -* libssl -* libjpeg -* zlib1g-dev -* python -* gettext -* graphviz - -Sur Windows -~~~~~~~~~~~ - -Chers utilisateurs de Windows, quel que soit votre amour de Windows, -de Bill Gates et des bloatwares, je suis désolé -de vous annoncer que, certaines dépendances étant uniquement disponibles sur des sytèmes UNIX, -il n'est pas possible développer le site sur Windows. - -Heureusement, il existe une alternative qui ne requiert pas de désinstaller votre -OS ni de mettre un dual boot sur votre ordinateur : :code:`WSL`. - -- **Prérequis:** vous devez être sur Windows 10 version 2004 ou ultérieure (build 19041 & versions ultérieures) ou Windows 11. -- **Plus d'info:** `docs.microsoft.com `_ - -.. sourcecode:: bash - - # dans un shell Windows - wsl --install - - # afficher la liste des distribution disponible avec WSL - wsl -l -o - - # installer WSL avec une distro (ubuntu conseillé) - wsl --install -d - -.. note:: - - Si vous rencontrez le code d'erreur ``0x80370102``, regardez les réponses de ce `post `_. - -Une fois :code:`WSL` installé, mettez à jour votre distro & installez les dépendances **(voir la partie installation sous Ubuntu)**. - -.. note:: - - Comme `git` ne fonctionne pas de la même manière entre Windows & Unix, il est nécessaire de cloner le repository depuis Windows. - (cf: `stackoverflow.com `_) - -Pour accéder au contenu d'un répertoire externe à :code:`WSL`, il suffit simplement d'utiliser la commande suivante: - -.. sourcecode:: bash - - # oui c'est beau, simple et efficace - cd /mnt//vos/fichiers/comme/dhab - -Une fois l'installation des dépendances terminée (juste en dessous), il vous suffira, pour commencer à dev, d'ouvrir votre plus bel IDE et d'avoir 2 consoles: -1 console :code:`WSL` pour lancer le projet & 1 console pour utiliser :code:`git` - -.. note:: - - A ce stade, si vous avez réussi votre installation de :code:`WSL` ou bien qu'il - était déjà installé, vous pouvez effectuer la mise en place du projet en suivant - les instructions pour Ubuntu. - - -Sur Ubuntu -~~~~~~~~~~ - -.. sourcecode:: bash - - # Sait-on jamais - sudo apt update - - sudo apt install python-is-python3 # Permet d'utiliser python au lieu de python3, c'est optionnel - - sudo apt install build-essentials libssl-dev libjpeg-dev zlib1g-dev python-dev \ - libffi-dev python-dev-is-python3 libgraphviz-dev pkg-config \ - gettext git pipx - - pipx install poetry - -.. note:: - - Si vous avez réussi à exécuter les instructions ci-dessus sans trop de problèmes, - vous pouvez passer à la partie :ref:`Finalise installation` - -Sur MacOS -~~~~~~~~~ - -Pour installer les dépendances, il est fortement recommandé d'installer le gestionnaire de paquets `homebrew `_. -Il est également nécessaire d'avoir installé xcode - -.. sourcecode:: bash - - echo 'export PATH="$(brew --prefix graphviz)/bin:$PATH"' >> ~/.zshrc - echo 'export CFLAGS="-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -I $(brew --prefix graphviz)/include"' >> ~/.zshrc - echo 'export LDFLAGS="-L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -L $(brew --prefix graphviz)/lib"' >> ~/.zshrc - - brew install git python graphviz pipx - pipx install poetry - - # Pour bien configurer gettext - brew link gettext # (suivez bien les instructions supplémentaires affichées) - -.. note:: - - Si vous rencontrez des erreurs lors de votre configuration, n'hésitez pas à vérifier l'état de votre installation homebrew avec :code:`brew doctor` - -.. note:: - - Si vous avez réussi à exécuter les instructions ci-dessus sans trop de problèmes, - vous pouvez passer à la partie :ref:`Finalise installation` - -.. _Finalise installation: - -Finaliser l'installation ------------------------- - -.. sourcecode:: bash - - # Les commandes git doivent se faire depuis le terminal de Windows si on utilise WSL ! - git clone https://github.com/ae-utbm/sith3.git - cd sith3 - - # Création de l'environnement et installation des dépendances - poetry install - - # Activation de l'environnement virtuel - poetry shell - - # Installe xapian - python manage.py install_xapian - - # Prépare la base de données - python manage.py setup - - # Installe les traductions - python manage.py compilemessages - -.. note:: - - Pour éviter d'avoir à utiliser la commande poetry shell systématiquement, il est possible de consulter :ref:`direnv`. - -Configuration pour le développement ------------------------------------ - -Lorsqu'on souhaite développer pour le site, il est nécessaire de passer le logiciel en mode debug dans les settings_custom. Il est aussi conseillé de définir l'URL du site sur localhost. Voici un script rapide pour le faire. - -.. sourcecode:: bash - - echo "DEBUG=True" > sith/settings_custom.py - echo 'SITH_URL = "localhost:8000"' >> sith/settings_custom.py - -Démarrer le serveur de développement ------------------------------------- - -Il faut toujours avoir préalablement activé l'environnement virtuel comme fait plus haut et se placer à la racine du projet. Il suffit ensuite d'utiliser cette commande : - -.. sourcecode:: bash - - python manage.py runserver - -.. note:: - - Le serveur est alors accessible à l'adresse http://localhost:8000 ou bien http://127.0.0.1:8000/. - -Générer la documentation ------------------------- - -La documentation est automatiquement mise en ligne sur readthedocs à chaque envoi de code sur GitHub. -Pour l'utiliser en local ou globalement pour la modifier, il existe une commande du site qui génère la documentation et lance un serveur la rendant accessible à l'adresse http://localhost:8080. -Cette commande génère la documentation à chacune de ses modifications, inutile de relancer le serveur à chaque fois. - -.. note:: - - Les dépendances pour la documentation sont optionnelles. - Avant de commencer à travailler sur la doc, il faut donc les installer - avec la commande :code:`poetry install --with docs` - -.. sourcecode:: bash - - python manage.py documentation - - # Il est possible de spécifier un port et une adresse d'écoute différente - python manage.py documentation adresse:port - -Lancer les tests ----------------- - -Pour lancer les tests il suffit d'utiliser la commande intégrée à django. - -.. code-block:: bash - - # Lancer tous les tests - pytest - - # Lancer les tests de l'application core - pytest core - - # Lancer les tests de la classe UserRegistrationTest de core - pytest core.tests.UserRegistrationTest - - # Lancer une méthode en particulier de cette même classe - pytest core.tests.UserRegistrationTest.test_register_user_form_ok - -.. note:: - - Certains tests sont un peu longs à tourner. - Pour ne faire tourner que les tests les plus rapides, - vous pouvez exécutez pytest ainsi : - - .. code-block:: bash - - pytest -m "not slow" - - # vous pouvez toujours faire comme au-dessus - pytest core -m "not slow" - - A l'inverse, vous pouvez ne faire tourner que les tests - lents en remplaçant `-m "not slow"` par `-m slow`. - - De cette manière, votre processus de développement - devrait être un peu plus fluide. - Cependant, n'oubliez pas de bien faire tourner - tous les tests avant de push un commit. - - - -Vérifier les dépendances Javascript ------------------------------------ - -Une commande a été écrite pour vérifier les éventuelles mises à jour à faire sur les librairies Javascript utilisées. -N'oubliez pas de mettre à jour à la fois le fichier de la librairie, mais également sa version dans `sith/settings.py`. - -.. code-block:: bash - - # Vérifier les mises à jour - python manage.py check_front diff --git a/doc/start/mvt_circle.svg b/doc/start/mvt_circle.svg deleted file mode 100644 index ff58fc67..00000000 --- a/doc/start/mvt_circle.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
Modèle

ORM
(Object Relational Mapping)
[Not supported by viewer]
Vue

Logique de l'application
[Not supported by viewer]
Template

Logique d'affichage
[Not supported by viewer]
Créer, Modifier, Supprimer
Créer, Modifier, Supprimer
Données pour l'affichage
Données pour l'affichage
Jeux de données
Jeux de données
Entrée utilisateur
Entrée utilisateur
\ No newline at end of file diff --git a/doc/start/mvt_flat.svg b/doc/start/mvt_flat.svg deleted file mode 100644 index a4e1b660..00000000 --- a/doc/start/mvt_flat.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
Template
Template
Vue
Vue
Modèle
Modèle
Côté client
Côté client
Côté serveur
Côté serveur
Base de données
Base de données
\ No newline at end of file diff --git a/doc/start/structure.rst b/doc/start/structure.rst deleted file mode 100644 index 1c5e3cb5..00000000 --- a/doc/start/structure.rst +++ /dev/null @@ -1,157 +0,0 @@ -La structure du projet -====================== - -Le principe MVT ---------------- - -Django est un framework suivant le modèle MVT (Model-View-Template) aussi appelé MTV (Model-Template-View). - -.. figure:: mvt_circle.svg - :alt: Diagramme MVT - :align: center - - Diagramme MVT - -On peut ainsi voir que la Vue gère la logique d'application, le modèle gère la structure de la base de données et communique avec elle et la vue effectue la logique de l'application. Décris comme ça, cela fait penser au modèle MVC (Model-View-Controller) mais évitons de nous complexifier les choses. Disons que c'est assez proche mais qu'il y a quelques différences (déjà au niveau du nommage). - -On peut également représenter le tout sous une autre forme, plus simple à comprendre et visualiser en aplatissant le diagramme. Cela représente mieux ce qui se passe. - -.. figure:: mvt_flat.svg - :alt: Diagramme MVT aplati - :align: center - - Diagramme MVT aplati - -Cette représentation permet de se représenter les interactions sous formes de couches. Avec ça en tête, ce sera plus simple d’appréhender la manière dont est découpé le projet. - -Le découpage en applications ----------------------------- - -| /projet -| **sith/** -| Application principale du projet. -| **accounting/** -| Ajoute un système de comptabilité. -| **api/** -| Application où mettre les endpoints publiques d'API. -| **club/** -| Contient les modèles liés aux clubs et assos et ajoute leur gestion. -| **com/** -| Fournis des outils de communications aux clubs (weekmail, affiches…). -| **core/** -| Application la plus importante. Contient les principales surcouches -| liées au projet comme la gestion des droits et les templates de base. -| **counter/** -| Ajoute des comptoirs de vente pour les clubs et gère les ventes sur les lieux de vie. -| **data/** -| Contient les fichiers statiques ajoutés par les utilisateurs. -| N'est pas suivi par Git. -| **doc/** -| Contient la documentation du projet. -| **eboutic/** -| Ajoute le comptoir de vente en ligne. Permet d'acheter en carte bancaire. -| **election/** -| Ajoute un système d'élection permettant d'élire les représentants étudiants. -| **forum/** -| Ajoute un forum de discussion. -| **launderette/** -| Permet la gestion des laveries. -| **locale/** -| Contient les fichiers de traduction. -| **matmat/** -| Système de recherche de membres. -| **pedagogy/** -| Contient le guide des UVs. -| **rootplace/** -| Ajoute des outils destinés aux administrateurs. -| **static/** -| Contient l'ensemble des fichiers statiques ajoutés par les développeurs. -| Ce dossier est généré par le framework, il est surtout utile en production ; -| évitez d'y toucher pendant le développement. -| Ce dossier n'est pas suivi par Git. -| **stock/** -| Système de gestion des stocks. -| **subscription/** -| Ajoute la gestion des cotisations des membres. -| **trombi/** -| Permet la génération du trombinoscope des élèves en fin de cursus. -| **.coveragec** -| Configure l'outil permettant de calculer la couverture des tests sur le projet. -| **.gitignore** -| Permet de définir quels fichiers sont suivis ou non par Git. -| **.github/** -| Contient les fichiers de configuration des actions github. -| **.readthedocs.yml** -| Permet de configurer la génération de documentation sur Readthedocs. -| **.db.sqlite3** -| Base de données de développement par défaut. Est automatiquement généré -| lors de la configuration du projet en local. N'est pas suivie par Git. -| **LICENSE** -| Licence du projet. -| **LICENSE.old** -| Ancienne licence du projet. -| **manage.py** -| Permet de lancer les commandes liées au framework Django. -| **migrate.py** -| Contiens des scripts de migration à exécuter pour importer les données de l'ancien site. -| **README.md** -| Fichier de README. À lire pour avoir des informations sur le projet. -| **pyproject.toml** -| Contient les dépendances Python du projet. - - -L'application principale ------------------------- - -| /sith -| **__init__.py** -| Permet de définir le dossier comme un package Python. -| Ce fichier est vide. -| **settings.py** -| Contient les paramètres par défaut du projet. -| Ce fichier est versionné et fait partie intégrant de celui-ci. -| Notez que les informations sensibles qui se trouvent dans ce fichier -| ne sont pas celles utilisées en production. -| Ce sont des paramètres factices préremplies pour faciliter la mise en place -| du projet qui sont surchargés en production par les vrais paramètres. -| **settings_custom.py** -| Contient les paramètres spécifiques à l'installation courante. -| Ce fichier n'est pas versionné et surcharge les paramètres par défaut. -| **urls.py** -| Contient les routes d'URLs racines du projet. -| On y inclut les autres fichiers d'URLs et leur namespace. -| **toolbar_debug.py** -| Contient la configuration de la barre de debug à gauche à destination -| du site de développement. -| **et_keys/** -| Contiens la clef publique du système de paiement E-Transactions. - -.. warning:: - - Ne pas mettre de configuration personnelle ni aucun mot de passe dans **settings.py**. Si il y a besoin de ce genre de chose, il faut le mettre dans **settings_custom.py** qui lui n'est pas versionné. - -Le contenu d'une application ----------------------------- - -| /app1 -| **__init__.py** -| Permet de définir le dossier comme un package Python. -| **models.py** -| C'est là que les modèles sont définis. Ces classes définissent -| les tables dans la base de données. -| **views.py** -| C'est là où les vues sont définies. -| **admin.py** -| C'est là que l'on déclare quels modèles doivent apparaître -| dans l'interface du module d'administration de Django. -| **tests.py** -| Ce fichier contient les tests fonctionnels, unitaires -| et d'intégrations qui sont lancés par la pipeline. -| **urls.py** -| On y définit les URLs de l'application et on les lie aux vues. -| **migrations/** -| Ce dossier sert à stocker les fichiers de migration de la base -| de données générés par la commande *makemigrations*. -| **templates/** -| Ce dossier-ci contient généralement des sous-dossiers et sert -| à accueillir les templates. Les sous dossiers servent de namespace. diff --git a/doc/start/translations.rst b/doc/start/translations.rst deleted file mode 100644 index a59c3e5c..00000000 --- a/doc/start/translations.rst +++ /dev/null @@ -1,81 +0,0 @@ -.. _translations: - -Ajouter une traduction -====================== - -Le code du site est entièrement écrit en anglais, le texte affiché aux utilisateurs l'est également. La traduction en français se fait ultérieurement avec un fichier de traduction. Voici un petit guide rapide pour apprendre à s'en servir. - -Dans le code du logiciel ------------------------- - -Imaginons que nous souhaitons afficher "Hello" et le traduire en français. Voici comment signaler que ce mot doit être traduit. - -Si le mot est dans le code Python : - -.. sourcecode:: python - - from django.utils.translation import gettext_lazy as _ - - # ... - - help_text=_("Hello") - - # ... - -Si le mot apparaît dans le template Jinja : - -.. sourcecode:: html+jinja - - {# ... #} - - {% trans %}Hello{% endtrans %} - - {# ... #} - -Générer le fichier django.po ----------------------------- - -La traduction se fait en trois étapes. Il faut d'abord générer un fichier de traductions, l'éditer et enfin le compiler au format binaire pour qu'il soit lu par le serveur. - -.. sourcecode:: bash - - ./manage.py makemessages --locale=fr --ignore "env/*" -e py,jinja - -Éditer le fichier django.po ---------------------------- - -.. role:: python(code) - :language: python - -.. sourcecode:: python - - # locale/fr/LC_MESSAGES/django.po - - # ... - msgid "Hello" - msgstr "" # Ligne à modifier - - # ... - -.. note:: - - Si les commentaires suivants apparaissent, pensez à les supprimer. Ils peuvent gêner votre traduction. - - :: - - #, fuzzy - #| msgid "Bonjour" - - -Générer le fichier django.mo ----------------------------- - -Il s'agit de la dernière étape. Un fichier binaire est généré à partir du fichier django.mo. - -.. sourcecode:: bash - - ./manage.py compilemessages - -.. note:: - - Pensez à redémarrer le serveur si les traductions ne s'affichent pas \ No newline at end of file diff --git a/doc/Comptes-rendus/CR 16.01.05.pdf b/docs/Comptes-rendus/CR 16.01.05.pdf similarity index 100% rename from doc/Comptes-rendus/CR 16.01.05.pdf rename to docs/Comptes-rendus/CR 16.01.05.pdf diff --git a/doc/Comptes-rendus/CR 16.11.10.pdf b/docs/Comptes-rendus/CR 16.11.10.pdf similarity index 100% rename from doc/Comptes-rendus/CR 16.11.10.pdf rename to docs/Comptes-rendus/CR 16.11.10.pdf diff --git a/doc/Comptes-rendus/CR 16.11.16.pdf b/docs/Comptes-rendus/CR 16.11.16.pdf similarity index 100% rename from doc/Comptes-rendus/CR 16.11.16.pdf rename to docs/Comptes-rendus/CR 16.11.16.pdf diff --git a/doc/Comptes-rendus/CR 16.12.1.pdf b/docs/Comptes-rendus/CR 16.12.1.pdf similarity index 100% rename from doc/Comptes-rendus/CR 16.12.1.pdf rename to docs/Comptes-rendus/CR 16.12.1.pdf diff --git a/doc/Comptes-rendus/CR 16.12.15.pdf b/docs/Comptes-rendus/CR 16.12.15.pdf similarity index 100% rename from doc/Comptes-rendus/CR 16.12.15.pdf rename to docs/Comptes-rendus/CR 16.12.15.pdf diff --git a/doc/Comptes-rendus/CR 16.12.8.pdf b/docs/Comptes-rendus/CR 16.12.8.pdf similarity index 100% rename from doc/Comptes-rendus/CR 16.12.8.pdf rename to docs/Comptes-rendus/CR 16.12.8.pdf diff --git a/doc/Architecture_et_presentation_-_Skia_2016.pdf b/docs/archives/Architecture_et_presentation_-_Skia_2016.pdf similarity index 100% rename from doc/Architecture_et_presentation_-_Skia_2016.pdf rename to docs/archives/Architecture_et_presentation_-_Skia_2016.pdf diff --git a/doc/TO_Skia_LoJ/.gitignore b/docs/archives/TO_Skia_LoJ/.gitignore similarity index 100% rename from doc/TO_Skia_LoJ/.gitignore rename to docs/archives/TO_Skia_LoJ/.gitignore diff --git a/doc/TO_Skia_LoJ/Couvertures.odg b/docs/archives/TO_Skia_LoJ/Couvertures.odg similarity index 100% rename from doc/TO_Skia_LoJ/Couvertures.odg rename to docs/archives/TO_Skia_LoJ/Couvertures.odg diff --git a/doc/TO_Skia_LoJ/Couvertures.pdf b/docs/archives/TO_Skia_LoJ/Couvertures.pdf similarity index 100% rename from doc/TO_Skia_LoJ/Couvertures.pdf rename to docs/archives/TO_Skia_LoJ/Couvertures.pdf diff --git a/doc/TO_Skia_LoJ/Makefile b/docs/archives/TO_Skia_LoJ/Makefile similarity index 100% rename from doc/TO_Skia_LoJ/Makefile rename to docs/archives/TO_Skia_LoJ/Makefile diff --git a/doc/TO_Skia_LoJ/Rapport.pdf b/docs/archives/TO_Skia_LoJ/Rapport.pdf similarity index 100% rename from doc/TO_Skia_LoJ/Rapport.pdf rename to docs/archives/TO_Skia_LoJ/Rapport.pdf diff --git a/doc/TO_Skia_LoJ/Rapport.tex b/docs/archives/TO_Skia_LoJ/Rapport.tex similarity index 100% rename from doc/TO_Skia_LoJ/Rapport.tex rename to docs/archives/TO_Skia_LoJ/Rapport.tex diff --git a/doc/TO_Skia_LoJ/slides/Makefile b/docs/archives/TO_Skia_LoJ/slides/Makefile similarity index 100% rename from doc/TO_Skia_LoJ/slides/Makefile rename to docs/archives/TO_Skia_LoJ/slides/Makefile diff --git a/doc/TO_Skia_LoJ/slides/beamercolorthememetropolis.sty b/docs/archives/TO_Skia_LoJ/slides/beamercolorthememetropolis.sty similarity index 100% rename from doc/TO_Skia_LoJ/slides/beamercolorthememetropolis.sty rename to docs/archives/TO_Skia_LoJ/slides/beamercolorthememetropolis.sty diff --git a/doc/TO_Skia_LoJ/slides/beamerfontthememetropolis.sty b/docs/archives/TO_Skia_LoJ/slides/beamerfontthememetropolis.sty similarity index 100% rename from doc/TO_Skia_LoJ/slides/beamerfontthememetropolis.sty rename to docs/archives/TO_Skia_LoJ/slides/beamerfontthememetropolis.sty diff --git a/doc/TO_Skia_LoJ/slides/beamerinnerthememetropolis.sty b/docs/archives/TO_Skia_LoJ/slides/beamerinnerthememetropolis.sty similarity index 100% rename from doc/TO_Skia_LoJ/slides/beamerinnerthememetropolis.sty rename to docs/archives/TO_Skia_LoJ/slides/beamerinnerthememetropolis.sty diff --git a/doc/TO_Skia_LoJ/slides/beamerouterthememetropolis.sty b/docs/archives/TO_Skia_LoJ/slides/beamerouterthememetropolis.sty similarity index 100% rename from doc/TO_Skia_LoJ/slides/beamerouterthememetropolis.sty rename to docs/archives/TO_Skia_LoJ/slides/beamerouterthememetropolis.sty diff --git a/doc/TO_Skia_LoJ/slides/beamerthememetropolis.sty b/docs/archives/TO_Skia_LoJ/slides/beamerthememetropolis.sty similarity index 100% rename from doc/TO_Skia_LoJ/slides/beamerthememetropolis.sty rename to docs/archives/TO_Skia_LoJ/slides/beamerthememetropolis.sty diff --git a/doc/TO_Skia_LoJ/slides/pgfplotsthemetol.sty b/docs/archives/TO_Skia_LoJ/slides/pgfplotsthemetol.sty similarity index 100% rename from doc/TO_Skia_LoJ/slides/pgfplotsthemetol.sty rename to docs/archives/TO_Skia_LoJ/slides/pgfplotsthemetol.sty diff --git a/doc/TO_Skia_LoJ/slides/slide.pdf b/docs/archives/TO_Skia_LoJ/slides/slide.pdf similarity index 100% rename from doc/TO_Skia_LoJ/slides/slide.pdf rename to docs/archives/TO_Skia_LoJ/slides/slide.pdf diff --git a/doc/TO_Skia_LoJ/slides/slide.tex b/docs/archives/TO_Skia_LoJ/slides/slide.tex similarity index 100% rename from doc/TO_Skia_LoJ/slides/slide.tex rename to docs/archives/TO_Skia_LoJ/slides/slide.tex diff --git a/doc/TW_Skia/.gitignore b/docs/archives/TW_Skia/.gitignore similarity index 100% rename from doc/TW_Skia/.gitignore rename to docs/archives/TW_Skia/.gitignore diff --git a/doc/TW_Skia/Makefile b/docs/archives/TW_Skia/Makefile similarity index 100% rename from doc/TW_Skia/Makefile rename to docs/archives/TW_Skia/Makefile diff --git a/doc/TW_Skia/Rapport.pdf b/docs/archives/TW_Skia/Rapport.pdf similarity index 100% rename from doc/TW_Skia/Rapport.pdf rename to docs/archives/TW_Skia/Rapport.pdf diff --git a/doc/TW_Skia/Rapport.tex b/docs/archives/TW_Skia/Rapport.tex similarity index 100% rename from doc/TW_Skia/Rapport.tex rename to docs/archives/TW_Skia/Rapport.tex diff --git a/docs/explanation/conventions.md b/docs/explanation/conventions.md new file mode 100644 index 00000000..4c7c4930 --- /dev/null +++ b/docs/explanation/conventions.md @@ -0,0 +1,303 @@ +Cette page traite des conventions utilisées dans le développement du site. + +## Langue + +Les noms, de fonctions, de classe, de fichiers et de dossiers sont en anglais. +De même, les commentaires et les docstrings sont rédigés en anglais. + +En revanche la documentation est rédigée en français. +En effet, les développeurs et les développeuses +qui ont été, sont et seront amenés à travailler +sur le site sont presque tous des francophones. +Or, la bonne compréhension prime. +Une documentation, qui se doit d'utiliser au mieux +les mots justes, compris de manière juste, +gagne à être écrite en langue vernaculaire, +lorsqu'on est assuré qu'une coopération +internationale est peu probable. + +De la sorte, on s'assure au mieux que les +rédacteurs et rédactrices s'expriment bien +et que, réciproquement, les lecteurs et lectrices +comprennent au mieux. + +A ce titre, on ne vous en voudra pas +si vous rédigez des commentaires ou des docstrings +en français. + +En revanche, le code en lui-même doit +rester impérativement en anglais ; +les instructions étant en langue anglaise, +introduire des mots français au milieu crée un +contraste qui nuit à la compréhension. + +De manière générale, demandez-vous juste à qui vous êtes en train d'écrire : + +- si vous écrivez pour la machine, c'est en anglais +- si vous écrivez pour des êtres humains, c'est en français + +## Gestion de version + +Le projet utilise Git pour gérer les versions et +GitHub pour héberger le dépôt distant. + +L'arbre possède deux branches protégées : `master` et `taiste`. + +`master` est la branche contenant le code tel qu'il +tourne effectivement sur le vrai site de l'AE. +Celle-ci doit, autant que faire se peut, rester impeccable. + +`taiste` est la branche de référence pour le développement. +Cette dernière est régulièrement déployée sur le +site de test. +Elle permet de s'assurer que les diverses modifications +fonctionnent bien entre elles et fonctionnent bien +sur le serveur, avant d'être envoyées sur master. + +### Gestion des branches + +Toutes les modifications appliquées sur `taiste` +doivent se faire via des Pull Requests +depuis les différentes branches de développement. +Toutes les modifications appliquées sur `master` +doivent se faire via des Pull Requests +depuis `taiste`, ou bien depuis une branche +de *hotfix*, dans le cas où il faut réparer +un bug urgent apparu de manière impromptue. + +Aucun `push` direct n'est admis, ni sur l'une, +ni sur l'autre branche. + +En obligeant à passer par des PR, +on s'assure qu'au moins une autre personne +aura lu votre code et que les outils de test +et de vérification de code auront validé vos modifications. + +Par extension du mode de travail par PR, +les branches `master` et `taiste` ne peuvent +recevoir du code que sous la forme de merge commits. + +De plus, ces branches doivent recevoir, mais jamais donner +(à part entre elles). +Lorsqu'une modification a été effectuée sur `taiste` +et que vous souhaitez la récupérer dans une de vos +branches, vous devez procéder par `rebase`, +et non par `merge`. + +En d'autres termes, vous devez respecter les deux règles suivantes : + +1. Les branches `master` et `taiste` ne doivent contenir que des merge commits +2. Seules les branches `master` et `taiste` peuvent contenir des merge commits + +=== "Bien ✔ï¸" + + ```mermaid + gitGraph: + commit id: "initial commit" + branch bar + checkout main + checkout bar + commit id: "baz" + checkout main + merge bar id: "Merge branch bar" + branch foo + commit id: "foo a" + commit id: "foo b" + commit id: "foo c" + checkout main + merge foo id: "Merge branch foo" + ``` + +=== "Pas bien âŒ" + + ```mermaid + gitGraph: + commit + branch bar + branch foo + commit id: "foo a" + commit id: "foo b" + checkout main + checkout bar + commit id: "baz" + checkout main + merge bar id: "Merge branch bar" + checkout foo + merge main id: "Merge branch main" + commit id: "foo c" + checkout main + merge foo id: "Merge branch foo" + ``` + +## Style de code + +### Conventions de nommage + +Les conventions de nommage sont celles de la +[PEP8](https://peps.python.org/pep-0008/) : + +- les classes sont en PascalCase (ex: `class SacredGraal`) +- les constantes sont en MACRO_CASE (ex: `FAVOURITE_COLOUR = "blue"`) +- les fonctions et les variables sont en snake_case (ex: `swallow_origin = "african"`) +- les fichiers et dossiers contenant du code sont en snake_case +- les fichiers et les dossiers contenant de la documentation sont en kebab-case + +En parallèle de la casse, les règles +de formatage du code sont celles du formateur Ruff. +Ces règles sont automatiquement appliquées quand +vous faites tourner Ruff, donc vous n'avez pas à trop +vous poser de questions de ce côté-là. + +En ce qui concerne les autres langages utilisés +(Jinja, SCSS, Javascript), nous n'avons pas fixé +de convention à suivre. +Pour SCSS et Javascript, vous pouvez utiliser +Prettier, avec sa configuration par défaut, +qui est plutôt bonne. + +### Qualité du code + +Pour s'assurer de la qualité du code, Ruff est également utilisé. + +Tout comme pour le format, Ruff doit tourner avant chaque commit. + +!!!note "to edit or not to edit" + + Vous constaterez sans doute que `ruff format` modifie votre code, + mais que `ruff check` vous signale juste une liste + d'erreurs sans rien modifier. + + En effet, `ruff format` ne s'occupe que de la forme du code, + alors que `ruff check` regarde la logique du code. + Si Ruff modifiait automatiquement la logique du code, + ça serait un coup à introduire plus de bugs que ça n'en résoud. + + Il existe cependant certaines catégories d'erreurs que Ruff + peut réparer de manière sûre. + Pour appliquer ces réparations, faites : + + ```bash + ruff check --fix + ``` + +## Documentation + +La documentation est écrite en markdown, avec les fonctionnalités +offertes par MkDocs, MkDocs-material et leurs extensions. + +La documentation est intégralement en français, à l'exception +des exemples, qui suivent les conventions données plus haut. + +### Découpage + +La séparation entre les différentes parties de la documentation se fait +en suivant la méthodologie [Diataxis](https://diataxis.fr/). +On compte quatre sections : + +1. Explications : parlez dans cette section de ce qui est bon à savoir + sans que ça touche aux détails précis de l'implémentation. + Si vous parlez de *pourquoi* un choix a été fait ou que vous montrez + grossièrement les contours d'une partie du projet, c'est une explication. +2. Tutoriels : parlez dans cette section d'étapes précises + ou de détails d'implémentation qu'un nouveau développeur + doit suivre pour commencer à travailler sur le projet. +3. Utilisation : parlez dans cette section de méthodes utiles + pour un développeur qui a déjà pris en main le projet. + Voyez cette partie comme un livre de recettes de cuisine. +4. Référence : parlez dans cette section des détails d'implémentation du projet. + En réalité, vous n'aurez pas besoin de beaucoup vous pencher dessus, + puisque cette partie est composée presque uniquement + des docstrings présents dans le code. + +Pour plus de détails, lisez directement la documentation de Diataxis, +qui expose ces concepts de manière beaucoup plus complète. + +### Style + +Votre markdown doit être composé de lignes courtes ; +à partir de 88 caractères, c'est trop long. +Si une phrase est trop longue pour tenir sur une ligne, +vous pouvez l'écrire sur plusieurs. + +Une ligne ne peut pas contenir plus d'une seule phrase. +Dit autrement, quand vous finissez une phrase, +faites systématiquement un saut de ligne. + +=== "Bien ✔ï¸" + + ```markdown linenums="1" + First shalt thou take out the Holy Pin, + then shalt thou count to three, no more, no less. + Three shalt be the number thou shalt count, + and the number of the counting shalt be three. + Four shalt thou not count, neither count thou two, + excepting that thou then proceed to three. + Five is right out. + Once the number three, being the third number, be reached, + then lobbest thou thy Holy Hand Grenade of Antioch towards thou foe, + who being naughty in My sight, shall snuff it. + ``` + +=== "Pas bien âŒ" + + ```markdown linenums="1" + First shalt thou take out the Holy Pin, then shalt thou count to three, no more, no less. Three shalt be the number thou shalt count, and the number of the counting shalt be three. Four shalt thou not count, neither count thou two, excepting that thou then proceed to three. Five is right out. Once the number three, being the third number, be reached, then lobbest thou thy Holy Hand Grenade of Antioch towards thou foe, who being naughty in My sight, shall snuff it. + ``` + +À noter que ces deux exemples donnent le même résultat +dans la documentation générée. +Mais la version avec de courtes lignes est beaucoup +plus facile à modifier et à versioner. + +!!!warning "Grammaire et orthographe" + + Ca peut paraitre évident dit comme ça, mais c'est toujours bon à rappeler : + évitez de faire des fautes de français. + Relisez vous quand vous avez fini d'écrire. + + +### Docstrings + +Les docstrings sont écrits en suivant la norme +[Google](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) +et les fonctionnalités de [Griffe](https://mkdocstrings.github.io/griffe/docstrings/). + +Ils doivent être explicites sur ce que la fonction accomplit, +mais ne pas parler de comment elle le fait. +Un bon docstring est celui qui dit exactement +ce qu'il faut pour qu'on puisse savoir comment +utiliser la fonction ou la classe documentée sans avoir à lire son code. + +Tout comme les pédales d'une voiture : +pour pouvoir conduire, vous avez juste besoin +de savoir ce qui se passe quand vous appuyez dessus. +La connaissance de la mécanique interne est inutile dans ce cadre. + +N'hésitez pas à mettre des examples dans vos docstrings. + +## Pourquoi une partie du projet ne respecte pas ces conventions ? + +Parce que le projet est vieux. +Le commit initial date du 18 novembre 2015. +C'était il y a presque dix ans au moment +où ces lignes sont écrites. +Au début, on ne se posait pas forcément +ce genre de questions. +Puis le projet a grandi, de manière sédimentaire, +fonctionnalité après fonctionnalité, +développé par des personnes n'ayant pas toutes la +même esthétique. + +On retrouve dans le code ces inspirations diverses +de personnes variées à travers une décennie. +Au bout d'un moment, il est bon de se poser +et de normaliser les choses. + +De ce côté-là, une première pierre a été posée +en novembre 2018, avec l'utilisation d'un formateur. +Il convient de poursuivre ce travail d'unification. + +Cependant, là où on peut reformater automatiquement +du code, il faut y aller à la main pour retravailler +un style de code. +C'est un travail de fourmi qui prendra du temps. diff --git a/docs/explanation/index.md b/docs/explanation/index.md new file mode 100644 index 00000000..e3fe89ab --- /dev/null +++ b/docs/explanation/index.md @@ -0,0 +1,101 @@ +## Objectifs + +Le but de ce projet est de fournir à +l'Association des Étudiants de l'UTBM +une plate-forme pratique et centralisée de ses services. +Le Sith de l'AE tient à jour le registre des cotisations +à l'association, prend en charge la trésorerie, +les ventes de produits et services, +la diffusion d’événements, +la gestion de la laverie et bien plus encore. + +C'est un projet bénévole qui tire ses origines des années 2000. +Il s'agit de la troisième version du site de l'AE. +Son développement a commencé en 2015. +C'est une réécriture complète en rupture totale +des deux versions qui l'ont précédée. + +## Pourquoi réécrire le site + +L'ancienne version du site, sobrement baptisée +[ae2](https://github.com/ae-utbm/sith2), +présentait un nombre impressionnant de fonctionnalités. +Il avait été écrit en PHP et se basait +sur son propre framework maison. + +Malheureusement, son entretien était plus ou +moins hasardeux et son framework reposait +sur des principes assez différents de ce qui se fait +aujourd'hui, rendant la maintenance difficile. +De plus, la version de PHP qu'il utilisait +était plus que dépréciée et à l'heure de l'arrivée de PHP 7 +et de sa non-rétrocompatibilité il était vital de faire +quelque chose. +Il a donc été décidé de le réécrire. + +## La philosophie initiale + +Pour éviter les erreurs du passé, +ce projet met l'accent sur la maintenabilité. +Le choix des technologies ne s'est donc pas +fait uniquement sur le fait qu'elle soit récentes, +mais également sur leur robustesse, +leur fiabilité et leur potentiel à être maintenu +loin dans le futur. + +La maintenabilité passe également par le +choix minutieux des dépendances qui doivent, +elles aussi, passer l'épreuve du temps +pour éviter qu'elles ne mettent le projet en danger. + +Cela passe également par la minimisation +des frameworks employés de manière à réduire un maximum +les connaissances nécessaires pour contribuer +au projet et donc simplifier la prise en main. +La simplicité est à privilégier si elle est possible. + +Le projet doit être simple à installer et à déployer. + +Le projet étant à destination d'étudiants, +il est préférable de minimiser les ressources +utilisées par l'utilisateur final. +Il faut qu'il soit au maximum économe en bande +passante et calcul côté client. + +Le projet est un logiciel libre et est sous licence GPL. +Aucune dépendance propriétaire n'est acceptée. + +## La philosophie, 10 ans plus tard + +Malgré la bonne volonté et le travail colossal +fourni par les developpeurs de la version actuelle +du projet, force est de constater que nombre d'erreurs +ont malheureusement été commises : +usage complexe et excessif de certains mécanismes OO, +réécriture maison de fonctionnalités de Django, +système de gestion des permissions rigide et coûteux +en requête à la base de données... + +Mais malgré tout ça, le site tourne. +En effet, force est de constater que le pari initial +de choisir un framework stable et durable a payé. +Aujourd'hui encore, Django est activement maintenu, +ses mises à jour sont régulières sans pour autant +nécessiter beaucoup de changements lors des changements +de version majeure. + +Quant aux erreurs qui ont été commises, +que celui qui n'a jamais reconsidéré a posteriori +que ce qui lui semblait une bonne architecture +était en fait un ensemble brinquebalant, +leur jette la première pierre. + +La solidité des fondations ayant été prouvée +par l'épreuve du temps, +le travail restant à accomplir n'est +pas de réécrire encore une fois le site +en utilisant encore d'autres technologies, +mais plutôt de raboter les surcouches du site, +pour refixer le plus solidement possiblement +le projet sur ces fondations. + diff --git a/docs/explanation/technos.md b/docs/explanation/technos.md new file mode 100644 index 00000000..29b6e0c5 --- /dev/null +++ b/docs/explanation/technos.md @@ -0,0 +1,355 @@ +Bien choisir ses technologies est crucial +puisqu'une fois que le projet est suffisamment avancé, +il est très difficile voir impossible de revenir en arrière. + +En novembre 2015, plusieurs choix se présentaient : + +- Continuer avec du PHP +- S'orienter vers un langage web +plus moderne et à la mode comme le Python ou le Ruby +- Baser le site sur un framework Javascript + +Le PHP 5, bientôt 7, de l'époque +étant assez discutable comme +[cet article le montre](https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/), +et l'ancien site ayant laissé un goût amer +à certains développeurs, celui-ci a été mis de côté. + +L'écosystème Javascript étant à peine naissant +et les frameworks allant et venant en seulement quelques mois, +il était impossible de prédire avec certitude +si ceux-ci passeraient l'épreuve du temps, +il était inconcevable de tout parier là-dessus. + +Ne restait plus que le Python et le Ruby +avec les frameworks Django et Ruby On Rails. +Ruby ayant une réputation d'être très "cutting edge", +c'est Python, un langage bien implanté +et ayant fait ses preuves, qui a été retenu. + +Il est à noter que réécrire le site avec un framework PHP +comme Laravel ou Symphony eut aussi été possible, +ces deux technologies étant assez matures et robustes +au moment où le développement a commencé. +Cependant, il aurait été potentiellement +fastidieux de maintenir en parallèle deux +versions de PHP sur le serveur durant toute +la durée du développement. +Il faut aussi prendre en compte que nous étions +à ce moment dégoûtés du PHP. + +## Backend + +### Python 3 + +[Site officiel](https://www.python.org/) + +Le python est un langage de programmation +interprété multi paradigme sorti en 1991. +Il est très populaire dans de nombreux domaines +pour sa simplicité d'utilisation, +sa polyvalence, sa sécurité ainsi +que sa grande communauté de développeur. +Sa version 3, non rétro compatible avec sa version 2, +a été publiée en 2008. + +!!!note + + Puisque toutes les dépendances du backend sont + des packages Python, + elles sont toutes ajoutées directement + dans le fichier **pyproject.toml**, + à la racine du projet. + +### Django + +[Site officiel](https://www.djangoproject.com/) + +[Documentation](https://docs.djangoproject.com/en/latest/) + +Django est un framework web pour Python apparu en 2005. +Il fournit un grand nombre de fonctionnalités +pour développer un site rapidement et simplement. +Cela inclut entre autre un serveur Web de développement, +un parseur d'URLs pour le routage, +un ORM (Object-Relational Mapper) +pour la gestion de la base de donnée, +un cadre pour l'écriture et l'exécution des tests, +de nombreux utilitaires pour l'internationalisation, +les zones horaires et autres, +une interface web d'administration aisément configurable, +un moteur de templates pour le rendu HTML... + +Django propose une version LTS (Long Term Support) +qui reste stable et est maintenu sur des cycles plus longs. +Ce sont ces versions qui sont utilisées. + + +### PostgreSQL / SQLite3 + +[Site officiel PostgreSQL](https://www.postgresql.org/) + +[Site officiel SQLite](https://www.sqlite.org/index.html>) + +Comme la majorité des sites internet, +le Sith de l'AE enregistre ses données +dans une base de données. +Nous utilisons une base de donnée relationnelle +puisque c'est la manière typique d'utiliser +Django et c'est ce qu'utilise son ORM. + +Le principal à retenir ici est : + +- Sur la version de production, nous utilisons PostgreSQL, +c'est cette version qui doit fonctionner en priorité. +C'est un système de gestion de base de données fiable, +puissant, activement maintenu, et particulièrement +bien supporté par Django. +- Sur les versions de développement, +pour faciliter l'installation du projet, +nous utilisons la technologie SQLite3 +qui ne requiert aucune installation spécifique +(la librairie `sqlite` est incluse dans les +librairies par défaut de Python). +Certaines instructions ne sont pas supportées +par cette technologie et il est parfois nécessaire +d'installer PostgreSQL pour le développement +de certaines parties du site +(cependant, ces parties sont rares, et vous pourriez +même ne jamais en rencontrer une). + +PostgreSQL est-ce avec quoi le site doit fonctionner. +Cependant, pour permettre aux développeurs +de travailler en installant le moins de dépendances +possible sur leur ordinateur, +il est également désirable de chercher la compatibilité +avec SQLite. +Aussi, dans la mesure du possible, nous +cherchons à ce que les interactions avec la base +de données fonctionnent avec l'un comme avec l'autre. + +Heureusement, et grâce à l'ORM de Django, cette +double compatibilité est presque toujours possible. + +## Frontend + +### Jinja2 + +[Site officiel](https://jinja.palletsprojects.com/en/latest/) + +Jinja2 est un moteur de template écrit en Python +qui s'inspire fortement de la syntaxe des templates de Django. +Ce moteur apporte toutefois son lot d'améliorations non négligeables. +Il permet par exemple l'ajout de macros, +sortes de fonctions écrivant du HTML. + +Un moteur de templates permet de générer +du contenu textuel de manière procédural +en fonction des données à afficher, +cela permet de pouvoir inclure du code proche du Python +dans la syntaxe au milieu d'un document +contenant principalement du HTML. +On peut facilement faire des boucles ou des conditions +ainsi même que de l'héritage de templates. + +!!!note + le rendu est fait côté serveur, + si on souhaite faire des modifications côté client, + il faut utiliser du Javascript, rien ne change à ce niveau-là. + +### jQuery + +[Site officiel](https://jquery.com/) + +jQuery est une bibliothèque JavaScript +libre et multiplateforme créée pour faciliter +l'écriture de scripts côté client +dans le code HTML des pages web. +La première version est lancée en janvier 2006 par John Resig. + +C'est une vieille technologie et certains +feront remarquer à juste titre que le Javascript +moderne permet d'utiliser assez simplement +la majorité de ce que fournit jQuery +sans rien avoir à installer. +Cependant, de nombreuses dépendances du projet +utilisent encore jQuery qui est toujours +très implanté aujourd'hui. +Le sucre syntaxique qu'offre cette librairie +reste très agréable à utiliser et économise +parfois beaucoup de temps. +Ça fonctionne et ça fonctionne très bien. +C'est maintenu et pratique. + + +### AlpineJS + +[Site officiel](https://alpinejs.dev/) + +AlpineJS est une librairie légère et minimaliste +permettant le rendu dynamique d'éléments sur une page +web, code de manière déclarative. +La librairie est décrite par ses créateurs comme : +"un outil robuste et minimal pour composer un comportement directement dans vos balises". + +Alpine permet d'accomplir la plupart du temps le même résultat qu'un usage des fonctionnalités +de base des plus gros frameworks Javascript, +mais est beaucoup plus léger, un peu plus facile à prendre en main +et ne s'embarrasse pas d'un DOM virtuel. +Grâce à son architecture, il est extrêmement +bien adapté pour un usage dans un site multipage. +C'est une technologie simple et puissante qui se veut comme le jQuery du web moderne. + +### Sass + +[Site officiel](https://sass-lang.com/) + +Sass (Syntactically Awesome Stylesheets) est un langage dynamique +de génération de feuilles CSS apparu en 2006. +C'est un langage de CSS "amélioré" qui permet +l'ajout de variables +(à une époque où le CSS ne les supportait pas), +de fonctions, mixins ainsi qu'une syntaxe pour +imbriquer plus facilement et proprement les règles +sur certains éléments. +Le Sass est traduit en CSS directement côté serveur +et le client ne reçoit que du CSS. + +C'est une technologie stable, +mature et pratique qui ne nécessite pas énormément +d'apprentissage. + +### Fontawesome + +[Site officiel](https://fontawesome.com>) + +Fontawesome regroupe tout un ensemble +d'icônes libres de droits utilisables facilement +sur n'importe quelle page web. +Ils sont simples à modifier puisque modifiables +via le CSS et présentent l'avantage de fonctionner +sur tous les navigateurs contrairement +à un simple icône unicode qui s'affiche +lui différemment selon la plate-forme. + +!!!note + + C'est une dépendance capricieuse qui évolue très vite + et qu'il faut très souvent mettre à jour. + +!!!warning + + Il a été décidé de **ne pas utiliser** + de CDN puisque le site ralentissait régulièrement. + Il est préférable de fournir cette dépendance avec le site. + +## Workflow + +### Git + +[Site officiel](https://git-scm.com/) + +Git est un logiciel de gestion de versions écrit par +Linus Torvalds pour les besoins du noyau linux en 2005. +C'est ce logiciel qui remplace svn anciennement +utilisé pour gérer les sources du projet +(rappelez vous, l'ancien site date d'avant 2005). +Git est plus complexe à utiliser, +mais est bien plus puissant, +permet de gérer plusieurs versions en parallèle +et génère des codebases vraiment plus légères puisque +seules les modifications sont enregistrées +(contrairement à svn qui garde une copie +de la codebase par version). + +Git s'étant imposé comme le principal outil de gestion de versions, +sa communauté est très grande et sa documentation très fournie. +Il est également aisé de trouver des outils avec une interface graphique, +qui simplifient grandement son usage. + +### GitHub + +[Site officiel](https://github.com) + +[Page github du Pôle Informatique de l'AE](https://github.com/ae-utbm/) + +Github est un service web d'hébergement et de gestion de développement de logiciel. +C'est une plate-forme avec interface web permettant de déposer du code géré avec Git +offrant également de l'intégration continue et du déploiement automatique. +C'est au travers de cette plate-forme que le Sith de l'AE est géré. + +### Sentry + +[Site officiel](https://sentry.io) + +[Instance de l'AE](https://ae2.utbm.fr) + +Sentry est une plate-forme libre qui permet +de se tenir informé des bugs qui ont lieu sur le site. +À chaque crash du logiciel (erreur 500), +une erreur est envoyée sur la plate-forme +et il est indiqué précisément à quelle ligne de code +celle-ci a eu lieu, à quelle heure, combien de fois, +avec quel navigateur la page a été visitée et même éventuellement +un commentaire de l'utilisateur qui a rencontré le bug. + +C'est un outil incroyablement pratique +pour savoir tout ce qui ne fonctionne pas, +et surtout pour récolter toutes les informations +nécessaires à la réparation des bugs. + +### Poetry + +[Utiliser Poetry](https://python-poetry.org/docs/basic-usage/) + +Poetry est un utilitaire qui permet de créer et gérer +des environnements Python de manière simple et intuitive. +Il permet également de gérer et mettre à jour +le fichier de dépendances. + +L'avantage d'utiliser poetry +(et les environnements virtuels en général) +est de pouvoir gérer plusieurs projets différents +en parallèle puisqu'il permet d'avoir sur sa +machine plusieurs environnements différents et +donc plusieurs versions d'une même dépendance +dans plusieurs projets différents sans impacter +le système sur lequel le tout est installé. + +Poetry possède également l'avantage par rapport à un simple venv +que les versions exactes de toutes les dépendances, +y compris celles utilisées par d'autres dépendances, +sont consignées dans un fichier `.lock`. +On est donc sûr et certain que deux environnements virtuels +configurés avec le même fichier lock utiliseront +exactement les mêmes versions des mêmes dépendances, +y compris si celles-ci ne sont pas indiquées explicitement. + +Les dépendances utilisées par poetry sont déclarées +dans le fichier `pyproject.toml`, +situé à la racine du projet. + +### Ruff + +[Site officiel](https://astral.sh/ruff) + +Pour faciliter la lecture du code, +il est toujours appréciable d'avoir +une norme d'écriture cohérente. +C'est généralement à l'étape de relecture +des modifications par les autres contributeurs +que sont repérées ces fautes de normes +qui se doivent d'être corrigées pour le bien commun. + +Imposer une norme est très fastidieux, +que ce soit pour ceux qui relisent +ou pour ceux qui écrivent. +C'est pour cela que nous utilisons Ruff, +qui est un formateur et linter automatique de code. +Une fois l'outil lancé, il parcourt la codebase +pour y repérer les fautes de norme et les erreurs de logique courantes +et les corrige automatiquement (quand c'est possible) +sans que l'utilisateur ait à s'en soucier. +Bien installé, il peut effectuer ce travail +à chaque sauvegarde d'un fichier dans son éditeur, +ce qui est très agréable pour travailler. \ No newline at end of file diff --git a/docs/howto/direnv.md b/docs/howto/direnv.md new file mode 100644 index 00000000..6d39ba3a --- /dev/null +++ b/docs/howto/direnv.md @@ -0,0 +1,59 @@ +Pour éviter d'avoir à sourcer l'environnement +à chaque fois qu'on rentre dans le projet, +il est possible d'utiliser l'utilitaire [direnv](https://direnv.net/). + +Comme pour beaucoup de choses, il faut commencer par l'installer : + +=== "Linux" + + === "Debian/Ubuntu" + + ```bash + sudo apt install direnv + ``` + + === "Arch Linux" + + ```bash + sudo pacman -S direnv + ``` + +=== "macOS" + + ```bash + brew install direnv + ``` + +Puis on configure : + +=== "bash" + + ```bash + echo 'eval "$(direnv hook bash)"' >> ~/.bashrc + exit # On redémarre le terminal + ``` + +=== "zsh" + + ```zsh + echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc + exit # On redémarre le terminal + ``` + +=== "nu" + + Désolé, par `direnv hook` pour `nu` + +Une fois le terminal redémarré, dans le répertoire du projet : +```bash +direnv allow . +``` + +Une fois que cette configuration a été appliquée, +aller dans le dossier du site applique automatiquement +l'environnement virtuel. +Ça peut faire gagner pas mal de temps. + +Direnv est un utilitaire très puissant +et qui peut s'avérer pratique dans bien des situations, +n'hésitez pas à aller vous renseigner plus en détail sur celui-ci. \ No newline at end of file diff --git a/docs/howto/migrations.md b/docs/howto/migrations.md new file mode 100644 index 00000000..a262519d --- /dev/null +++ b/docs/howto/migrations.md @@ -0,0 +1,354 @@ +## Qu'est-ce qu'une migration ? + +Une migration est un fichier Python qui contient +des instructions pour modifier la base de données. +Une base de données évolue au cours du temps, +et les migrations permettent de garder une trace +de ces modifications. + +Grâce à elles, on peut également apporter des modifications +à la base de données sans être obligées de la recréer. +On applique seulement les modifications nécessaires. + +## Appliquer les migrations + +Pour appliquer les migrations, exécutez la commande suivante : + +```bash +python ./manage.py migrate +``` + +Vous remarquerez peut-être que cette commande +a été utilisée dans la section +[Installation](../tutorial/install.md). +En effet, en partant d'une base de données vierge +et en appliquant toutes les migrations, on arrive +à l'état actuel de la base de données. +Logique. + +Si vous utilisez cette commande sur une base de données +sur laquelle toutes les migrations ont été appliquées, +elle ne fera rien. + +Si vous utilisez cette commande sur une base de données +sur laquelle seule une partie des migrations ont été appliquées, +seules les migrations manquantes seront appliquées. + +## Créer une migration + +Pour créer une migration, exécutez la commande suivante : + +```bash +python ./manage.py makemigrations +``` + +Cette commande comparera automatiquement le contenu +des classes de modèles et le comparera avec les +migrations déjà appliquées. +A partir de cette comparaison, elle générera +automatiquement une nouvelle migration. + +!!! note + + La commande `makemigrations` ne fait que + générer les fichiers de migration. + Elle ne modifie pas la base de données. + Pour appliquer la migration, n'oubliez pas la + commande `migrate`. + +Un fichier de migration ressemble à ça : + +```python +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + # liste des autres migrations à appliquer avant celle-ci + ] + + operations = [ + # liste des opérations à appliquer sur la db + ] +``` + +Grâce à la liste des dépendances, Django sait dans +quel ordre les migrations doivent être appliquées. +Grâce à la liste des opérations, Django sait quelles +sont les opérations à appliquer durant cette migration. + +## Revenir à une migration antérieure + +Lorsque vous développez, il peut arriver que vous vouliez +revenir à une migration antérieure. +Pour cela, il suffit d'appliquer la commande `migrate` +en spécifiant le nom de la migration à laquelle vous +voulez revenir : + +```bash +python ./manage.py migrate +``` + +Par exemple, si vous voulez revenir à la migration `0001_initial` +de l'application `customer`, vous pouvez exécuter la commande suivante : + +```bash +python ./manage.py migrate customer 0001 +``` + +## Customiser une migration + +Il peut arriver que vous ayez besoin de modifier +le fichier de migration généré par Django. +Par exemple, si vous voulez exécuter un script Python +lors de l'application de la migration. + +Dans ce cas, vous pouvez trouver les fichiers de migration +dans le dossier `migrations` de chaque application. +Vous pouvez modifier le fichier Python correspondant +à la migration que vous voulez modifier. + +Ajoutez l'opération que vous voulez effectuer +dans l'attribut `operations` de la classe `Migration`. + +Par exemple : + +```python +from django.db import migrations + +def forwards_func(apps, schema_editor): + print("Appplication de la migration") + +def reverse_func(apps, schema_editor): + print("Annulation de la migration") + +class Migration(migrations.Migration): + + dependencies = [] + + operations = [ + migrations.RunPython(forwards_func, reverse_func), + ] +``` + +!!! warning "Script d'annulation de la migration" + + Lorsque vous incluez un script Python dans une migration, + incluez toujours aussi un script d'annulation, + sinon Django ne pourra pas annuler la migration + après son application. + + Vous ne pourrez donc pas revenir à un état antérieur + de la db, à moins de la recréer de zéro. + +## Fusionner des migrations + +Quand on travaille sur une fonctionnalité +qui nécessite une modification de la base de données, +les fichiers de migration sont comme toute chose : +on peut se rendre compte que les changements +apportés pourraient être meilleurs. + +Par exemple, supposons que nous voulons créer un modèle +représentant une UE suivie par un étudiant +(ne demandez pas pourquoi on voudrait faire ça, +c'est juste pour l'exemple). +Un tel modèle aurait besoin des informations suivantes : + +- l'utilisateur +- le code de l'UE + +On écrirait donc, dans l'application `pedagogy` : +```python +from django.db import models +from core.models import User + +class UserUe(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + ue = models.CharField(max_length=10) +``` + +Et nous aurions le fichier de migration suivant : +```python +from django.db import migrations, models +from django.conf import settings + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("pedagogy", "0003_alter_uv_language"), + ] + + operations = [ + migrations.CreateModel( + name="UserUe", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("ue", models.CharField(max_length=10)), + ( + "user", + models.ForeignKey( + on_delete=models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] +``` + + +On finit son travail, on soumet la PR. +Mais là, quelqu'un fait remarquer qu'il existe déjà +un modèle pour représenter une UE. +On modifie donc le modèle : + +```python +from django.db import models +from core.models import User +from pedagogy.models import UV + +class UserUe(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + ue = models.ForeignKey(UV, on_delete=models.CASCADE) +``` + +On refait la commande `makemigrations` et on obtient : +```python +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("pedagogy", "0004_userue"), + ] + + operations = [ + migrations.AlterField( + model_name="userue", + name="ue", + field=models.ForeignKey( + on_delete=models.deletion.CASCADE, to="pedagogy.uv" + ), + ), + ] +``` + +Sauf que maintenant, nous avons deux fichiers de migration, +alors qu'en réalité, on ne souhaite faire qu'une seule migration, +une fois qu'on aura expédié le code en prod. +Certes, ça fonctionnerait d'appliquer les deux, mais ça pose +un problème d'encombrement. + +Plus il y a de fichiers de migrations, plus il y a de migrations +à résoudre au moment de l'installation du projet chez quelqu'un, +plus c'est embêtant à gérer et plus Django prendra du temps +à résoudre les migrations. + +C'est pourquoi il est bon de respecter le principe : +une PR = un fichier de migration maximum par application. + +Nous voulons donc fusionner les deux, pour n'en garder qu'une. +Pour ça, deux manières de procéder : + +- le faire à la main +- utiliser la commande squashmigrations + +Pour la méthode manuelle, on ne pourrait pas vous dire exhaustivement +comment faire. +Mais ne vous inquiétez pas, ce n'est pas très dur. +Regardez bien quelles sont les instructions utilisées par django +pour les opérations de migrations, +et avec un peu d'astuce et quelques copier-coller, +vous vous en sortirez comme des chefs. + +Pour la méthode `squashmigrations`, exécutez la commande + +```bash +python ./manage.py squasmigrations +``` + +Par exemple, dans notre cas, ça donnera : + +```bash +python ./manage.py squasmigrations pedagogy 0004 0005 +``` + +La commande vous donnera ceci : +```python +from django.conf import settings +from django.db import migrations, models + +class Migration(migrations.Migration): + replaces = [("pedagogy", "0004_userue"), ("pedagogy", "0005_alter_userue_ue")] + + dependencies = [ + ("pedagogy", "0003_alter_uv_language"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="UserUe", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "ue", + models.ForeignKey( + on_delete=models.deletion.CASCADE, to="pedagogy.uv" + ), + ), + ( + "user", + models.ForeignKey( + on_delete=models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] +``` + +Vous pouvez alors supprimer les deux autres fichiers. + +Vous remarquerez peut-être la présence de la ligne suivante : +```python +replaces = [("pedagogy", "0004_userue"), ("pedagogy", "0005_alter_userue_ue")] +``` + +Cela sert à dire que cette migration doit être appliquée +à la place des deux autres. +Une fois que vous aurez supprimé les deux fichiers, +supprimez également cette ligne. + +!!!warning + + Django sait quelles migrations ont été appliquées, + en les stockant dans une table de la db. + Si une migration est enregistrée en db, sans que le fichier + de migration correspondant existe, + la commande `migrate` échoue. + + Quand vous faites un `squashmigrations`, + pensez donc à appliquer la commande `migrate` + juste après (mais avant la suppression des anciens fichiers), + pour que Django supprime de la base de données + les migrations devenues inutiles. diff --git a/docs/howto/prod.md b/docs/howto/prod.md new file mode 100644 index 00000000..2e892fff --- /dev/null +++ b/docs/howto/prod.md @@ -0,0 +1,27 @@ +## Configurer Sentry + +Pour connecter l'application à une instance de sentry (ex: https://sentry.io), +il est nécessaire de configurer la variable `SENTRY_DSN` +dans le fichier `settings_custom.py`. +Cette variable est composée d'un lien complet vers votre projet sentry. + +## Récupérer les statiques + +Nous utilisons du SCSS dans le projet. +En environnement de développement (`DEBUG=True`), +le SCSS est compilé à chaque fois que le fichier est demandé. +Pour la production, le projet considère +que chacun des fichiers est déjà compilé et, +pour ce faire, il est nécessaire +d'utiliser les commandes suivantes dans l'ordre : + +```bash +python ./manage.py collectstatic # Pour récupérer tous les fichiers statiques +python ./manage.py compilestatic # Pour compiler les fichiers SCSS qu'ils contiennent +``` + +!!!tip + + Le dossier où seront enregistrés ces fichiers + statiques peut être changé en modifiant la variable + `STATIC_ROOT` dans les paramètres. \ No newline at end of file diff --git a/docs/howto/querysets.md b/docs/howto/querysets.md new file mode 100644 index 00000000..61576686 --- /dev/null +++ b/docs/howto/querysets.md @@ -0,0 +1,280 @@ +L'ORM de Django est puissant, très puissant, non par parce qu'il +est performant (après tout, ce n'est qu'une interface, le gros du boulot, +c'est la db qui le fait), mais parce qu'il permet d'écrire +de manière relativement simple un grand panel de requêtes. + +De manière générale, puisqu'un ORM est un système +consistant à manipuler avec un code orienté-objet +une db relationnelle (c'est-à-dire deux paradigmes +qui ne fonctionnent absolument pas pareil), +on rencontre un des deux problèmes suivants : + +- soit l'ORM n'offre pas assez d'abstraction, + auquel cas, quand on veut faire des requêtes + plus complexes qu'un `select` avec un `where`, + on s'emmêle les pinceaux et on se dit que + ça aurait été plus simple de le faire directement + en SQL. +- soit l'ORM offre trop d'abstraction, + auquel cas, on a tendance à ne pas prêter + assez attention aux requêtes envoyées en base + de données et on finit par se rendre compte + que les temps d'attente explosent + parce qu'on envoie trop de requêtes. + +Django est dans ce deuxième cas. + +C'est pourquoi nous ne parlerons pas ici +de son fonctionnement exact ni de toutes les fonctions +que l'on peut utiliser +(la doc officielle fait déjà ça mieux que nous), +mais plutôt des pièges courants +et des astuces pour les éviter. + +## Les `N+1 queries` + +### Le problème + +Normalement, quand on veut récupérer une liste, +on fait une requête et c'est fini. +Mais des fois, ça n'est pas si simple. +Par exemple, supposons que nous voulons +récupérer les 100 utilisateurs les plus riches, +avec leurs informations client : + +```python +from core.models import User + +for user in User.objects.order_by("-customer__amount")[:100]: + print(user.customer.amount) +``` + +Combien de requêtes le bout de code suivant effectue-t-il ? +101\. +En deux pauvres lignes de code, nous avons demandé +à la base de données d'effectuer 101 requêtes. +Une requête toute seule n'est déjà une opération anodine, +alors je vous laisse imaginer ce que ça donne pour 101. + +Si vous ne comprenez pourquoi ce nombre, c'est très simple : + +- Une requête pour sélectionner nos 100 utilisateurs +- Une requête supplémentaire pour récupérer les informations + client de chaque utilisateur, soit 100 requêtes. + +En effet, les informations client sont stockées dans une +autre table, mais le fait d'établir un lien de clef +étrangère permet de manipuler `customer` +comme si c'était un membre à part entière de `User`. + +Il est à noter cependant, que Django n'effectue une requête +que pour le premier accès à un membre d'une relation +de clef étrangère. +Toutes les fois suivantes, l'objet est déjà là, +et django le récupère : + +```python +from core.models import User + +# l'utilisateur le plus riche +user = User.objects.order_by("-customer__amount").first() # <-- requête db +print(user.customer.amount) # <-- requête db +print(user.customer.account_id) # on a déjà récupéré `customer`, donc pas de requête +``` + +Ce n'est donc pas gravissime si vous faites cette +erreur quand vous manipulez un seul objet. +En revanche, quand vous en manipulez plusieurs, +il faut régler le problème. +Pour ça, il y a plusieurs méthodes, en fonction de votre cas. + +### `select_related` + +La méthode la plus basique consiste à annoter le queryset, +avec la méthode `select_related()`. +En faisant ça, Django fera une jointure sur l'autre table +et demandera des informations en plus +à la db lors de la requête. + +De la sorte, lorsque vous appellerez le membre relié, +les informations seront déjà là. + +```python +from core.models import User + +richest = User.objects.order_by("-customer__amount") +for user in richest.select_related("customer")[:100]: + print(user.customer) +``` + +Le code ci-dessus effectue une seule requête. +Chaque fois qu'on veut accéder à `customer`, c'est bon, +ça a déjà été récupéré à travers le `annotate`. + +### `prefetch_related` + +Maintenant, un cas plus compliqué. +Supposons que vous ne vouliez pas récupérer des informations +reliées par une relation One-to-One, +mais par une relation One-to-Many. + +Par exemple, un utilisateur a un seul compte client, +mais il peut avoir plusieurs cotisations à son actif. +Et dans ces cas-là, `annotate` ne marche plus. +En effet, s'il peut exister plusieurs cotisations, +comment savoir laquelle on veut ? + +Il faut alors utiliser un `prefetch_related`. +C'est un mécanisme un peu différent : +au lieu de faire une jointure et d'ajouter les informations +voulues dans la même requête, Django va effectuer +une deuxième requête pour récupérer les éléments de l'autre table, +puis, à partir de ces éléments, peupler la relation +de son côté. + +C'est un mécanisme qui peut être un peu coûteux en mémoire +et qui demande une deuxième requête, +mais qui reste quand même largement préférable +à faire N requêtes en plus. + +```python +from core.models import User + +for user in User.objects.prefetch_related("subscriptions")[:100]: + # c'est bon, la méthode prefetch a récupéré en avance les `subscriptions` + print(user.subscriptions.all()) +``` + +!!! danger + + La méthode `prefetch_related` ne marche que si vous + utilisez la méthode `all()` pour accéder au membre. + Si vous utilisez une autre méthode (comme `filter` ou `annotate`), + alors Django effectuera une nouvelle requête, + et vous retomberez dans le problème initial. + + ```python + from core.models import User + from django.db.models import Count + + for user in User.objects.prefetch_related("subscriptions")[:100]: + # Le prefetch_related ne marche plus ! + print(user.subscriptions.annotate(count=Count("*"))) + ``` + +### Récupérer ce dont vous avez besoin + +Des fois (souvent, même), penser explicitement +à la jointure est le meilleur choix. + +En effet, vous remarquerez que dans tous +les exemples précédents, nous n'utilisions +qu'une partie des informations +(par exemple, nous ne récupérions que la somme +d'argent sur les comptes, et éventuellement le numéro de compte). + +Nous pouvons utiliser la méthode `annotate` +pour spécifier explicitement les données que l'on veut +joindre à notre requête. + +Quand nous voulions récupérer les informations utilisateur, +nous aurions tout aussi bien pu écrire : + +```python +from core.models import User +from django.db.models import F + +richest = User.objects.order_by("-customer__amount") +for user in richest.annotate(amount=F("customer__amount"))[:100]: + print(user.amount) +``` + +On aurait même pu réorganiser ça : +```python + +from core.models import User +from django.db.models import F + +richest = User.objects.annotate(amount=F("customer__amount")).order_by("-amount") +for user in richest[:100]: + print(user.amount) +``` + +Ça peut sembler moins bien qu'un `select_related`, comme ça. +Des fois, c'est en effet moins bien, et des fois c'est mieux. +La comparaison est plus évidente avec le `prefetch_related`. + +En effet, quand nous voulions récupérer +le nombre de cotisations des utilisateurs, +le `prefetch_related` ne marchait plus. +Pourtant, nous voulions récupérer une seule information. + +Il aurait donc été suffisant d'écrire : +```python +from core.models import User +from django.db.models import Count + +for user in User.objects.annotate(nb_subscriptions=Count("subscriptions"))[:100]: + # Et là ça marche, en une seule requête. + print(user.nb_subscriptions) +``` + +Faire une jointure, c'est normal en SQL. +Et pourtant avec Django on les oublie trop facilement. +Posez-vous toujours la question des données que vous pourriez +avoir besoin d'annoter, et vous éviterez beaucoup d'ennuis. + +## Les aggrégations manquées + +Il arrive souvent que l'on veuille une information qui +porte sur un ensemble d'objets de notre db. + +Imaginons par exemple que nous voulons connaitre +la somme totale des ventes faites à un comptoir. + +Nous avons tous suivi nos cours de programmation, +nous écrivons donc instinctivement : + +```python +from counter.models import Counter + +foyer = Counter.objects.get(name="Foyer") +total_amount = sum( + sale.amount * sale.unit_price + for sale in foyer.sellings.all() +) +``` + +On pourrait penser qu'il n'y a pas de problème. +Après tout, on ne fait qu'une seule requête. +Eh bien si, il y a un problème : +on fait beaucoup de choses en trop. + +Concrètement, on demande à la base de données +de renvoyer toutes les informations, +ce qui rallonge inutilement la durée +de l'échange entre le serveur et la db, +puis on perd du temps à convertir ces informations +en objets Python (opération qui a un coût également), +et enfin on reperd du temps à calculer en Python +quelque chose que la db aurait pu calculer +à notre plus bien plus vite. + +Nous aurions dû aggréger la requête, +avec la méthode `aggregate` : + +```python +from counter.models import Counter +from django.db.models import Sum, F + +foyer = Counter.objects.get(name="Foyer") +total_amount = ( + foyer.sellings.aggregate(amount=Sum(F("amount") * F("unit_price"), default=0)) +)["amount__sum"] +``` + +En effectuant cette requête, la base de données nous renverra exactement +l'information dont nous avons besoin. +Et de notre côté, nous n'aurons pas à faire de traitement en plus. + + diff --git a/docs/howto/subscriptions.md b/docs/howto/subscriptions.md new file mode 100644 index 00000000..c7b08f4a --- /dev/null +++ b/docs/howto/subscriptions.md @@ -0,0 +1,46 @@ +## Ajouter une nouvelle cotisation + +Il peut arriver que le type de cotisation +proposé varie en prix et en durée. +Ces paramètres sont configurables directement dans les paramètres du projet. + +Pour modifier les cotisations disponibles, +tout se gère dans la configuration avec la variable `SITH_SUBSCRIPTIONS`. + +Par exemple, si nous voulons ajouter une nouvelle cotisation d'un mois, +voici ce que nous ajouterons : + +```python title="settings.py" +from django.utils.translation import gettext_lazy as _ + +SITH_SUBSCRIPTIONS = { + # Voici un échantillon de la véritable configuration à l'heure de l'écriture. + # Celle-ci est donnée à titre d'exemple pour mieux comprendre comment cela fonctionne. + "un-semestre": {"name": _("One semester"), "price": 15, "duration": 1}, + "deux-semestres": {"name": _("Two semesters"), "price": 28, "duration": 2}, + "cursus-tronc-commun": { + "name": _("Common core cursus"), + "price": 45, + "duration": 4, + }, + "cursus-branche": {"name": _("Branch cursus"), "price": 45, "duration": 6}, + "cursus-alternant": {"name": _("Alternating cursus"), "price": 30, "duration": 6}, + "membre-honoraire": {"name": _("Honorary member"), "price": 0, "duration": 666}, + "un-jour": {"name": _("One day"), "price": 0, "duration": 0.00555333}, + + # On rajoute ici notre cotisation + # Elle se nomme "Un mois" + # Coûte 6€ + # Dure 1 mois (on raisonne en semestre, ici, c'est 1/6 de semestre) + "un-mois": {"name": _("One month"), "price": 6, "duration": 0.166} +} +``` + +Une fois ceci fait, il faut créer une nouvelle migration : + +```bash +python ./manage.py makemigrations subscription +python ./manage.py migrate +``` + +N'oubliez pas non plus les traductions (cf. [ici](./translation.md)) diff --git a/docs/howto/terminal.md b/docs/howto/terminal.md new file mode 100644 index 00000000..eb9f1dbc --- /dev/null +++ b/docs/howto/terminal.md @@ -0,0 +1,84 @@ +## Quel terminal utiliser ? + +Quel que soit votre configuration, si vous avez réussi à installer +le projet, il y a de fortes chances que bash existe sur +votre ordinateur. +Certains d'entre vous utilisent peut-être un autre shell, +comme `zsh`. + +En effet, `bash` est bien, il fait le taff ; +mais son ergonomie finit par montrer ses limites. +C'est pourquoi il existe des shells plus avancés, +qui peuvent améliorer l'ergonomie, la complétion des commandes, +et l'apparence. +C'est le cas de `zsh`. +Certains vont même plus loin et refont carrément la syntaxe. +C'est le cas de `nu`. + +Pour choisir un terminal, demandez-vous juste quel +est votre usage du terminal : + +- Si c'est juste quelques commandes basiques et +que vous ne voulez pas vous embêter à changer +votre configuration, `bash` convient parfaitement. +- Si vous commencez à utilisez le terminal +de manière plus intensive, à varier les commandes +que vous utilisez et/ou que vous voulez customiser +un peu votre expérience, `zsh` est parfait pour vous. +- Si vous aimez la programmation fonctionnelle, +que vous adorez les pipes et que vous voulez faire +des scripts complets mais qui restent lisibles, +`nu` vous plaira à coup sûr. + +!!! note + + Ce ne sont que des suggestions. + Le meilleur choix restera toujours celui + avec lequel vous êtes le plus confortable. + +## Commandes utiles + +### Compter le nombre de lignes du projet + +=== "bash/zsh" + + ```bash + sudo apt install cloc + cloc --exclude-dir=doc,env . + ``` + Ok, c'est de la triche, on installe un package externe. + Mais bon, ça marche, et l'équivalent pur bash + serait carrément plus moche. + +=== "nu" + + Nombre de lignes, groupé par fichier : + ```nu + ls **/*.py | insert linecount { get name | open | lines | length } + ``` + + Nombre de lignes total : + ```nu + ls **/*.py | insert linecount { get name | open | lines | length } | math sum + ``` + + Vous pouvez aussi exlure les lignes vides + et les les lignes de commentaire : + ```nu + ls **/*.py | + insert linecount { + get name | + open | + lines | + each { str trim } | + filter { |l| not ($l | str starts-with "#") } | # commentaires + filter { |l| ($l | str length) > 0 } | # lignes vides + length + } | + math sum + ``` + + + + + diff --git a/docs/howto/translation.md b/docs/howto/translation.md new file mode 100644 index 00000000..8f40501a --- /dev/null +++ b/docs/howto/translation.md @@ -0,0 +1,71 @@ +Le code du site est entièrement écrit en anglais, +le texte affiché aux utilisateurs l'est également. +La traduction en français se fait +ultérieurement avec un fichier de traduction. +Voici un petit guide rapide pour apprendre à s'en servir. + +## Dans le code du logiciel + +Imaginons que nous souhaitons afficher "Hello" +et le traduire en français. +Voici comment signaler que ce mot doit être traduit. + +Si le mot est dans le code Python : + +```python +from django.utils.translation import gettext as _ + +help_text=_("Hello") +``` + +Si le mot apparaît dans le template Jinja : + +```jinja +{% trans %}Hello{% endtrans %} +``` + +## Générer le fichier django.po + +La traduction se fait en trois étapes. +Il faut d'abord générer un fichier de traductions, +l'éditer et enfin le compiler au format binaire pour qu'il soit lu par le serveur. + +```bash +./manage.py makemessages --locale=fr --ignore "env/*" -e py,jinja +``` + +## Éditer le fichier django.po + +```locale +# locale/fr/LC_MESSAGES/django.po + +# ... +msgid "Hello" +msgstr "" # Ligne à modifier + +# ... +``` + +!!!note + + Si les commentaires suivants apparaissent, pensez à les supprimer. + Ils peuvent gêner votre traduction. + + ``` + #, fuzzy + #| msgid "Bonjour" + ``` + + +## Générer le fichier django.mo + +Il s'agit de la dernière étape. +Un fichier binaire est généré à partir du fichier django.mo. + +```bash +./manage.py compilemessages +``` + +!!!tip + + Pensez à redémarrer le serveur si les traductions ne s'affichent pas \ No newline at end of file diff --git a/docs/howto/weekmail.md b/docs/howto/weekmail.md new file mode 100644 index 00000000..426e859e --- /dev/null +++ b/docs/howto/weekmail.md @@ -0,0 +1,71 @@ +Le site est capable de générer des mails automatiques +contenant l’agrégation d'articles écrits par les administrateurs de clubs. +Le contenu est inséré dans un template standardisé +et contrôlé directement dans le code. +Il arrive régulièrement que l'équipe communication souhaite modifier ce template. +Que ce soient les couleurs, +l'agencement ou encore la bannière ou le footer, +voici tout ce qu'il y a à savoir sur le fonctionnement +du weekmail en commençant par la classe qui le contrôle. + +## Modifier la bannière et le footer + +Ces éléments sont contrôlés par les méthodes `get_banner` et `get_footer` +de la classe `Weekmail`. +Les modifier est donc très simple, +il suffit de modifier le contenu de la fonction et +de rajouter les nouvelles images dans les statics. + +Les images sont à ajouter dans `core/static/com/img` +et sont à nommer selon le type (banner ou footer), le semestre (Automne ou Printemps) et l'année. +Exemple : `weekmail_bannerA18.jpg` pour la bannière de l'automne 2018. + +```python +from django.conf import settings +from django.templatetags.static import static + +# Sélectionnez le fichier de bannière pour le weekmail de l'automne 2018 + +def get_banner(self): + return "http://" + settings.SITH_URL + static("com/img/weekmail_bannerA18.jpg") +``` + +!!!note + + Penser à prendre les images au format **jpg** et à les compresser un peu, + pour qu'elles soient le plus léger possible, + c'est bien mieux pour l'utilisateur final. + +!!!warning + + Pensez à laisser les anciennes images dans le dossier + pour que les anciens weekmails ne soient pas affectés par les changements. + +## Modifier le template + +Il existe deux templates différents : + +- Un en texte pur, qui sert pour le rendu dégradé des lecteurs + de mails ne supportant pas le HTML +- un qui fait du rendu html. + +Ces deux templates sont respectivement accessibles aux emplacements suivants : + +- `com/templates/com/weekmail_renderer_html.jinja` +- `com/templates/com/weekmail_renderer_text.jinja` + +!!!note + + Pour le rendu HTML, pensez à utiliser le CSS et le javascript + le plus simple possible pour que le rendu se fasse correctement + dans les clients mails qui sont souvent capricieux. + +!!!note + + Le CSS est inclus statiquement pour que toute modification + ultérieure de celui-ci n'affecte pas les versions précédemment envoyées. + +!!!warning + + Si vous souhaitez ajouter du contenu, + n'oubliez pas de bien inclure ce contenu dans les deux templates. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..12521504 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,43 @@ +# Documentation du site de l'association des étudiants de l'UTBM + +Bonjour, camarade. + +Si tu es ici, c'est sans doute pour mieux connaitre +le fonctionnement interne du site AE. +Peut-être même as-tu envie de contribuer à son développement. +Si tel est le cas, nous ne pouvons faire autrement +que te souhaiter la bienvenue sur cette documentation +et espérer que ce que nous avons écrit est assez +clair et assez complet pour satisfaire ton esprit +en quête de connaissances. + +Et si tu viens pour d'autres motifs, +ça ne change rien, soit le bienvenu (ou la bienvenue) +quand même. + +Pour que tu saches où chercher quelles informations, +voici comment nous avons découpé la documentation : + +- Dans un premier temps, les explications, où nous +discutons tout simplement de ce à quoi nous pensions +en faisant ceci ou cela, quels motifs ont guidé tel ou +tel choix... +Bref, nous discutons du projet en tant qu'ensemble +de choix, qu'en tant qu'accumulation de détails +techniques. +Des détails techniques, tu en trouveras quand même, +mais sans doute moins que dans les autres parties. +- Deuxièmement, les tutoriels, où nous +expliquons pas à pas comment installer le +projet et commencer à travailler dessus. +Vois-le comme une notice d'assemblage. +- Troisièmement, les recettes, ou *how-to*, +où nous présenterons des conseils, des procédures à suivre +et des patterns qui t'aideront peut-être. +- Enfin, la référence, où sera donnée en dur +les détails techniques les plus intimes du projet, +tirés directement du code, +qui ne seront sans doute pas d'une grande utilité +pour comprendre le projet dans sa globalité, +mais qui seront bien plus utiles pour appréhender +l'implémentation de telle ou telle partie du code. diff --git a/docs/reference/accounting/models.md b/docs/reference/accounting/models.md new file mode 100644 index 00000000..338581a2 --- /dev/null +++ b/docs/reference/accounting/models.md @@ -0,0 +1 @@ +::: accounting.models \ No newline at end of file diff --git a/docs/reference/accounting/views.md b/docs/reference/accounting/views.md new file mode 100644 index 00000000..44804886 --- /dev/null +++ b/docs/reference/accounting/views.md @@ -0,0 +1 @@ +::: accounting.views \ No newline at end of file diff --git a/docs/reference/club/models.md b/docs/reference/club/models.md new file mode 100644 index 00000000..deabce6d --- /dev/null +++ b/docs/reference/club/models.md @@ -0,0 +1 @@ +::: club.models \ No newline at end of file diff --git a/docs/reference/club/views.md b/docs/reference/club/views.md new file mode 100644 index 00000000..834986af --- /dev/null +++ b/docs/reference/club/views.md @@ -0,0 +1 @@ +::: club.views \ No newline at end of file diff --git a/docs/reference/com/models.md b/docs/reference/com/models.md new file mode 100644 index 00000000..a8fe8961 --- /dev/null +++ b/docs/reference/com/models.md @@ -0,0 +1 @@ +::: com.models \ No newline at end of file diff --git a/docs/reference/com/views.md b/docs/reference/com/views.md new file mode 100644 index 00000000..978da4ba --- /dev/null +++ b/docs/reference/com/views.md @@ -0,0 +1 @@ +::: com.views \ No newline at end of file diff --git a/docs/reference/core/models.md b/docs/reference/core/models.md new file mode 100644 index 00000000..e27c8431 --- /dev/null +++ b/docs/reference/core/models.md @@ -0,0 +1 @@ +::: core.models \ No newline at end of file diff --git a/docs/reference/core/views.md b/docs/reference/core/views.md new file mode 100644 index 00000000..ecf41637 --- /dev/null +++ b/docs/reference/core/views.md @@ -0,0 +1 @@ +::: core.views \ No newline at end of file diff --git a/docs/reference/counter/models.md b/docs/reference/counter/models.md new file mode 100644 index 00000000..35c0713f --- /dev/null +++ b/docs/reference/counter/models.md @@ -0,0 +1 @@ +::: counter.models \ No newline at end of file diff --git a/docs/reference/counter/views.md b/docs/reference/counter/views.md new file mode 100644 index 00000000..2e4e0d40 --- /dev/null +++ b/docs/reference/counter/views.md @@ -0,0 +1 @@ +::: counter.views \ No newline at end of file diff --git a/docs/reference/eboutic/models.md b/docs/reference/eboutic/models.md new file mode 100644 index 00000000..a380c20a --- /dev/null +++ b/docs/reference/eboutic/models.md @@ -0,0 +1 @@ +::: eboutic.models \ No newline at end of file diff --git a/docs/reference/eboutic/views.md b/docs/reference/eboutic/views.md new file mode 100644 index 00000000..235ef622 --- /dev/null +++ b/docs/reference/eboutic/views.md @@ -0,0 +1 @@ +::: eboutic.views \ No newline at end of file diff --git a/docs/reference/election/models.md b/docs/reference/election/models.md new file mode 100644 index 00000000..4f572149 --- /dev/null +++ b/docs/reference/election/models.md @@ -0,0 +1 @@ +::: election.models \ No newline at end of file diff --git a/docs/reference/election/views.md b/docs/reference/election/views.md new file mode 100644 index 00000000..e90efa19 --- /dev/null +++ b/docs/reference/election/views.md @@ -0,0 +1 @@ +::: election.views \ No newline at end of file diff --git a/docs/reference/forum/models.md b/docs/reference/forum/models.md new file mode 100644 index 00000000..98f24925 --- /dev/null +++ b/docs/reference/forum/models.md @@ -0,0 +1 @@ +::: forum.models \ No newline at end of file diff --git a/docs/reference/forum/views.md b/docs/reference/forum/views.md new file mode 100644 index 00000000..051f6d4c --- /dev/null +++ b/docs/reference/forum/views.md @@ -0,0 +1 @@ +::: forum.views \ No newline at end of file diff --git a/docs/reference/galaxy/models.md b/docs/reference/galaxy/models.md new file mode 100644 index 00000000..467698ec --- /dev/null +++ b/docs/reference/galaxy/models.md @@ -0,0 +1 @@ +::: galaxy.models \ No newline at end of file diff --git a/docs/reference/galaxy/views.md b/docs/reference/galaxy/views.md new file mode 100644 index 00000000..dc0729a8 --- /dev/null +++ b/docs/reference/galaxy/views.md @@ -0,0 +1 @@ +::: galaxy.views \ No newline at end of file diff --git a/docs/reference/launderette/models.md b/docs/reference/launderette/models.md new file mode 100644 index 00000000..e773ea38 --- /dev/null +++ b/docs/reference/launderette/models.md @@ -0,0 +1 @@ +::: launderette.models \ No newline at end of file diff --git a/docs/reference/launderette/views.md b/docs/reference/launderette/views.md new file mode 100644 index 00000000..5b942e44 --- /dev/null +++ b/docs/reference/launderette/views.md @@ -0,0 +1 @@ +::: launderette.views \ No newline at end of file diff --git a/docs/reference/matmat/models.md b/docs/reference/matmat/models.md new file mode 100644 index 00000000..e104e40c --- /dev/null +++ b/docs/reference/matmat/models.md @@ -0,0 +1 @@ +::: matmat.models \ No newline at end of file diff --git a/docs/reference/matmat/views.md b/docs/reference/matmat/views.md new file mode 100644 index 00000000..17424653 --- /dev/null +++ b/docs/reference/matmat/views.md @@ -0,0 +1 @@ +::: matmat.views \ No newline at end of file diff --git a/docs/reference/pedagogy/models.md b/docs/reference/pedagogy/models.md new file mode 100644 index 00000000..e874f03d --- /dev/null +++ b/docs/reference/pedagogy/models.md @@ -0,0 +1 @@ +::: pedagogy.models \ No newline at end of file diff --git a/docs/reference/pedagogy/views.md b/docs/reference/pedagogy/views.md new file mode 100644 index 00000000..0bab498e --- /dev/null +++ b/docs/reference/pedagogy/views.md @@ -0,0 +1 @@ +::: pedagogy.views \ No newline at end of file diff --git a/docs/reference/rootplace/models.md b/docs/reference/rootplace/models.md new file mode 100644 index 00000000..1f09fa3a --- /dev/null +++ b/docs/reference/rootplace/models.md @@ -0,0 +1 @@ +::: rootplace.models \ No newline at end of file diff --git a/docs/reference/rootplace/views.md b/docs/reference/rootplace/views.md new file mode 100644 index 00000000..88a1b31b --- /dev/null +++ b/docs/reference/rootplace/views.md @@ -0,0 +1 @@ +::: rootplace.views \ No newline at end of file diff --git a/docs/reference/sas/models.md b/docs/reference/sas/models.md new file mode 100644 index 00000000..8bb8bfc1 --- /dev/null +++ b/docs/reference/sas/models.md @@ -0,0 +1 @@ +::: sas.models \ No newline at end of file diff --git a/docs/reference/sas/views.md b/docs/reference/sas/views.md new file mode 100644 index 00000000..59e6fc6a --- /dev/null +++ b/docs/reference/sas/views.md @@ -0,0 +1 @@ +::: sas.views \ No newline at end of file diff --git a/docs/reference/stock/models.md b/docs/reference/stock/models.md new file mode 100644 index 00000000..761e05d8 --- /dev/null +++ b/docs/reference/stock/models.md @@ -0,0 +1 @@ +::: stock.models \ No newline at end of file diff --git a/docs/reference/stock/views.md b/docs/reference/stock/views.md new file mode 100644 index 00000000..12222a4d --- /dev/null +++ b/docs/reference/stock/views.md @@ -0,0 +1 @@ +::: stock.views \ No newline at end of file diff --git a/docs/reference/subscription/models.md b/docs/reference/subscription/models.md new file mode 100644 index 00000000..ed46d44e --- /dev/null +++ b/docs/reference/subscription/models.md @@ -0,0 +1 @@ +::: subscription.models \ No newline at end of file diff --git a/docs/reference/subscription/views.md b/docs/reference/subscription/views.md new file mode 100644 index 00000000..a019a68c --- /dev/null +++ b/docs/reference/subscription/views.md @@ -0,0 +1 @@ +::: subscription.views \ No newline at end of file diff --git a/docs/reference/trombi/models.md b/docs/reference/trombi/models.md new file mode 100644 index 00000000..708eb3e9 --- /dev/null +++ b/docs/reference/trombi/models.md @@ -0,0 +1 @@ +::: trombi.models \ No newline at end of file diff --git a/docs/reference/trombi/views.md b/docs/reference/trombi/views.md new file mode 100644 index 00000000..cbb1303d --- /dev/null +++ b/docs/reference/trombi/views.md @@ -0,0 +1 @@ +::: trombi.views \ No newline at end of file diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 00000000..bebeae83 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,3 @@ +.mermaid { + text-align: center; +} \ No newline at end of file diff --git a/docs/tutorial/devtools.md b/docs/tutorial/devtools.md new file mode 100644 index 00000000..b585b92b --- /dev/null +++ b/docs/tutorial/devtools.md @@ -0,0 +1,150 @@ +Le projet n'est en aucun cas lié à un +quelconque environnement de développement. +Il est possible pour chacun de travailler +avec les outils dont il a envie et d'utiliser +l'éditeur de code avec lequel il est le plus à l'aise. + +Pour donner une idée, Skia a écrit une énorme +partie de projet avec l'éditeur *Vim* sur du GNU/Linux +alors que Sli a utilisé *Sublime Text* sur MacOS +et que Maréchal travaille avec PyCharm +sur ~~Windows muni de WSL~~ Arch Linux btw. + +## Configurer les pre-commit hooks + +La procédure habituelle pour contribuer au +projet consiste à commit des modifications, +puis à les push sur le dépôt distant et +à ouvrir une pull request. +Cette PR va faire tourner les outils de vérification +de la qualité de code. +Si la vérification échoue, la PR est bloquée, +et il faut réparer le problème +(ce qui implique de push un micro-commit +ou de push force sur la branche). + +Dans l'idéal, on aimerait donc qu'il soit +impossible d'oublier de faire tourner ces vérifications. +Pour ça, il existe un mécanisme : les pre-commits hooks. +Ce sont des actions qui tournent automatiquement +lorsque vous effectuez un `git commit`. +Ces dernières vont analyser et éventuellement modifier le code, +avant que Git n'ajoute effectivement le commit sur l'arbre git. +Voyez ça comme une micro-CI qui tourne en local. + +Les git hooks sont une fonctionnalité par défaut de Git. +Cependant, leur configuration peut-être un peu +embêtante si vous le faites manuellement. +Pour gérer ça plus simplement, +nous utilisons le logiciel python [pre-commit](https://pre-commit.com/) +qui permet de contrôler leur installation via un seul fichier de configuration, +placé à la racine du projet +(plus précisément, il s'agit du fichier `.pre-commit-config.yaml`). + +!!!note + + Les pre-commits sont également utilisés dans la CI. + Si ces derniers fonctionnent localement, vous avez la garantie que la pipeline ne sera pas fachée. ;) + +C'est une fonctionnalité de git lui-même, +mais c'est assez embêtant à gérer manuellement. +Pour gérer ça plus simplement, +nous utilisons le logiciel python [pre-commit](https://pre-commit.com/) +qui permet de contrôller leur installation via un fichier yaml. + +Le logiciel est installé par défaut par poetry. +Il suffit ensuite de lancer : + +```bash +pre-commit install +``` +Une fois que vous avez fait cette commande, pre-commit +tournera automatiquement chaque fois que vous ferez +un nouveau commit. + +Il est également possible d'appeler soi-même les pre-commits : + +```bash +pre-commit run --all-files +``` + + +## Configurer Ruff pour son éditeur + +!!!note + + Ruff est inclus dans les dépendances du projet. + Si vous avez réussi à terminer l'installation, vous n'avez donc pas de configuration + supplémentaire à effectuer. + +Pour utiliser Ruff, placez-vous à la racine du projet et lancez la commande suivante : + +```bash +ruff format # pour formatter le code +ruff check # pour linter le code +``` + +Ruff va alors faire son travail sur l'ensemble du projet puis vous dire +si des documents ont été reformatés (si vous avez fait `ruff format`) +ou bien s'il y a des erreurs à réparer (si vous avez faire `ruff check`). + +Appeler Ruff en ligne de commandes avant de pousser votre code sur Github +est une technique qui marche très bien. +Cependant, vous risquez de souvent l'oublier. +Or, lorsque le code ne respecte pas les standards de qualité, +la pipeline bloque les PR sur les branches protégées. + +Pour éviter de vous faire régulièrement avoir, vous pouvez configurer +votre éditeur pour que Ruff fasse son travail automatiquement à chaque édition d'un fichier. +Nous tenterons de vous faire ici un résumé pour deux éditeurs de textes populaires +que sont VsCode et Sublime Text. + +### VsCode + +Installez l'extension Ruff pour VsCode. +Ensuite, ajoutez ceci dans votre configuration : + +```json +{ + "[python]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "charliermarsh.ruff" + } +} +``` + +### Sublime Text + +Vous devez installer ce plugin : https://packagecontrol.io/packages/LSP-ruff. +Suivez ensuite les instructions données dans la description du plugin. + +Dans la configuration de votre projet, ajoutez ceci: + +```json +{ + "settings": { + "lsp_format_on_save": true, + "LSP": { + "LSP-ruff": { + "enabled": true, + } + } + } +} +``` + +Si vous utilisez le plugin [anaconda](http://damnwidget.github.io/anaconda/), +pensez à modifier les paramètres du linter pep8 +pour éviter de recevoir des warnings dans le formatage +de ruff comme ceci : + +```json +{ + "pep8_ignore": [ + "E203", + "E266", + "E501", + "W503" + ] +} +``` diff --git a/docs/tutorial/etransaction.md b/docs/tutorial/etransaction.md new file mode 100644 index 00000000..44118856 --- /dev/null +++ b/docs/tutorial/etransaction.md @@ -0,0 +1,11 @@ + +La boutique en ligne nécessite une interaction +avec la banque pour son fonctionnement. + +Malheureusement, la manière dont cette interaction marche +est trop complexe pour être résumée ici. + +Nous ne pouvons donc que vous redirigez vers la doc du crédit +agricole : +https://www.ca-moncommerce.com/espace-client-mon-commerce/up2pay-e-transactions/ma-documentation/ + diff --git a/docs/tutorial/groups.md b/docs/tutorial/groups.md new file mode 100644 index 00000000..b8603d16 --- /dev/null +++ b/docs/tutorial/groups.md @@ -0,0 +1,64 @@ +Il existe deux types de groupes sur le site AE : + +- l'un se base sur des groupes enregistrés en base de données pendant le développement, + c'est le système de groupes réels. +- L'autre est plus dynamique et comprend tous les groupes générés + pendant l'exécution et l'utilisation du programme. + Cela correspond généralement aux groupes liés aux clubs. + Ce sont les méta-groupes. + +## La définition d'un groupe + +Les deux types de groupes sont stockés dans la même table +en base de données, et ne sont différenciés que par un attribut `is_meta`. + +### Les groupes réels + +Pour plus différencier l'utilisation de ces deux types de groupe, +il a été créé une classe proxy +(c'est-à-dire qu'elle ne correspond pas à une vraie table en base de donnée) +qui encapsule leur utilisation. +`RealGroup` peut être utilisé pour créer des groupes réels dans le code +et pour faire une recherche sur ceux-ci +(dans le cadre d'une vérification de permissions par exemple). + +### Les méta-groupes + +Les méta-groupes, comme expliqué précédemment, +sont utilisés dans les contextes où il est nécessaire de créer un groupe dynamiquement. +Les objets `MetaGroup`, bien que dynamiques, doivent tout de même s'enregistrer +en base de données comme des vrais groupes afin de pouvoir être affectés +dans les permissions d'autres objets, comme un forum ou une page de wiki par exemple. +C'est principalement utilisé au travers des clubs, +qui génèrent automatiquement deux groupes à leur création : + +- club-bureau : contient tous les membres d'un club **au dessus** + du grade défini dans `settings.SITH_MAXIMUM_FREE_ROLE`. +- club-membres : contient tous les membres d'un club + **en dessous** du grade défini dans `settings.SITH_MAXIMUM_FREE_ROLE`. + + +## Les groupes réels utilisés + +Les groupes réels que l'on utilise dans le site sont les suivants : + +Groupes gérés automatiquement par le site : + +- `Public` : tous les utilisateurs du site +- `Subscribers` : tous les cotisants du site +- `Old subscribers` : tous les anciens cotisants + +Groupes gérés par les administrateurs (à appliquer à la main sur un utilisateur) : + +- `Root` : administrateur global du site +- `Accounting admin` : les administrateurs de la comptabilité +- `Communication admin` : les administrateurs de la communication +- `Counter admin` : les administrateurs des comptoirs (foyer et autre) +- `SAS admin` : les administrateurs du SAS +- `Forum admin` : les administrateurs du forum +- `Pedagogy admin` : les administrateurs de la pédagogie (guide des UVs) +- `Banned from buying alcohol` : les utilisateurs interdits de vente d'alcool (non mineurs) +- `Banned from counters` : les utilisateurs interdits d'utilisation des comptoirs +- `Banned to subscribe` : les utilisateurs interdits de cotisation + + diff --git a/docs/tutorial/install.md b/docs/tutorial/install.md new file mode 100644 index 00000000..d6ee5f5e --- /dev/null +++ b/docs/tutorial/install.md @@ -0,0 +1,248 @@ +## Dépendances du système + +Certaines dépendances sont nécessaires niveau système : + +- poetry +- libssl +- libjpeg +- zlib1g-dev +- python +- gettext +- graphviz + +### Installer WSL + +Si vous utilisez Windows, je suis navré +de vous annoncer que, certaines dépendances étant uniquement disponibles sur des sytèmes UNIX, +il n'est pas possible de développer le site sur ce système d'exploitation. + +Heureusement, il existe une alternative qui ne requiert pas de désinstaller votre +OS ni de mettre un dual boot sur votre ordinateur : `WSL`. + +- **Prérequis:** vous devez être sur Windows 10 version 2004 ou ultérieure (build 19041 & versions ultérieures) ou Windows 11. +- **Plus d'info:** [docs.microsoft.com](https://docs.microsoft.com/fr-fr/windows/wsl/install) + +```shell +# dans un shell Windows +wsl --install + +# afficher la liste des distribution disponible avec WSL +wsl -l -o + +# installer WSL avec une distro (ubuntu conseillé) +wsl --install -d +``` + +Une fois `WSL` installé, mettez à jour votre distribution et +installez les dépendances (voir la partie installation sous Ubuntu). + +Pour accéder au contenu d'un répertoire externe à `WSL`, +il suffit d'utiliser la commande suivante : + +```bash +# oui c'est beau, simple et efficace +cd /mnt//vos/fichiers/comme/dhab +``` + +!!!note + + A ce stade, si vous avez réussi votre installation de `WSL` ou bien qu'il + était déjà installé, vous pouvez effectuer la mise en place du projet en suivant + les instructions pour votre distribution. + +### Installer les dépendances + +=== "Linux" + + === "Debian/Ubuntu" + + Si ce n'est pas déjà fait, installez Python : + ```bash + sudo apt install python3 + # on sait jamais + sudo apt install python-is-python3 + ``` + Si vous utilisez Ubuntu 22.04 ou Ubuntu 24.04, + votre version de Python devrait être compatible + par défaut avec celle du projet. + Si ce n'est pas le cas, nous vous conseillons + d'utiliser [pyenv](https://github.com/pyenv/pyenv) + + Puis installez les autres dépendances : + + ```bash + sudo apt install build-essentials libssl-dev libjpeg-dev zlib1g-dev python-dev \ + libffi-dev python-dev-is-python3 libgraphviz-dev pkg-config \ + gettext git pipx + + pipx install poetry + ``` + + === "Arch Linux" + + ```bash + sudo pacman -Syu # on s'assure que les dépôts et le système sont à jour + + sudo pacman -S python + + sudo pacman -S gcc git graphviz gettext graphviz pkgconf python-poetry + ``` + +=== "macOS" + + Pour installer les dépendances, il est fortement recommandé d'installer le gestionnaire de paquets `homebrew `_. + Il est également nécessaire d'avoir installé xcode + + ```bash + echo 'export PATH="$(brew --prefix graphviz)/bin:$PATH"' >> ~/.zshrc + echo 'export CFLAGS="-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -I $(brew --prefix graphviz)/include"' >> ~/.zshrc + echo 'export LDFLAGS="-L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -L $(brew --prefix graphviz)/lib"' >> ~/.zshrc + + brew install git python graphviz pipx + pipx install poetry + + # Pour bien configurer gettext + brew link gettext # (suivez bien les instructions supplémentaires affichées) + ``` + + !!!note + + Si vous rencontrez des erreurs lors de votre configuration, n'hésitez pas à vérifier l'état de votre installation homebrew avec :code:`brew doctor` + + +## Finaliser l'installation + +```bash +git clone https://github.com/ae-utbm/sith3.git +cd sith3 + +# Création de l'environnement et installation des dépendances +poetry install + +# Activation de l'environnement virtuel +poetry shell + +# Installation de Xapian +python ./manage.py install_xapian + +# Prépare la base de données +python ./manage.py setup + +# Installe les traductions +python ./manage.py compilemessages +``` + +!!!note + + La commande `install_xapian` est longue et affiche beaucoup + de texte à l'écran. + C'est normal, il ne faut pas avoir peur. + +!!!note + + Pour éviter d'avoir à utiliser la commande `poetry shell` + systématiquement, il est possible de consulter [direnv](../howto/direnv.md). + +## Configuration pour le développement + +Lorsqu'on souhaite développer pour le site, +il est nécessaire de passer le logiciel en mode debug +dans les settings_custom. +Il est aussi conseillé de définir l'URL du site sur localhost. +Voici un script rapide pour le faire. + +```bash +echo "DEBUG=True" > sith/settings_custom.py +echo 'SITH_URL = "localhost:8000"' >> sith/settings_custom.py +``` + +## Démarrer le serveur de développement + +Il faut toujours avoir préalablement activé +l'environnement virtuel comme fait plus haut +et se placer à la racine du projet. +Il suffit ensuite d'utiliser cette commande : + +```bash +python manage.py runserver +``` + +!!!note + + Le serveur est alors accessible à l'adresse + [http://localhost:8000](http://localhost:8000) ou bien [http://127.0.0.1:8000/](http://127.0.0.1:8000/). + +## Générer la documentation + +La documentation est automatiquement mise en ligne à chaque envoi de code sur GitHub. +Pour l'utiliser en local ou globalement pour la modifier, +il existe une commande du site qui génère +la documentation et lance un serveur la rendant +accessible à l'adresse [http://localhost:8080](http://localhost:8000). +Cette commande génère la documentation à +chacune de ses modifications, +inutile de relancer le serveur à chaque fois. + +!!!note + + Les dépendances pour la documentation sont optionnelles. + Avant de commencer à travailler sur la doc, il faut donc les installer + avec la commande `poetry install --with docs` + +```bash +mkdocs serve +``` + +## Lancer les tests + +Pour lancer les tests, il suffit d'utiliser +la commande suivante : + +```bash +# Lancer tous les tests +pytest + +# Lancer les tests de l'application core +pytest core + +# Lancer les tests de la classe UserRegistrationTest de core +pytest core.tests.UserRegistrationTest + +# Lancer une méthode en particulier de cette même classe +pytest core.tests.UserRegistrationTest.test_register_user_form_ok +``` + +!!!note + + Certains tests sont un peu longs à tourner. + Pour ne faire tourner que les tests les plus rapides, + vous pouvez exécutez pytest ainsi : + + ```bash + pytest -m "not slow" + + # vous pouvez toujours faire comme au-dessus + pytest core -m "not slow" + ``` + + A l'inverse, vous pouvez ne faire tourner que les tests + lents en remplaçant `-m "not slow"` par `-m slow`. + + De cette manière, votre processus de développement + devrait être un peu plus fluide. + Cependant, n'oubliez pas de bien faire tourner + tous les tests avant de push un commit. + + + +## Vérifier les dépendances Javascript + +Une commande a été écrite pour vérifier les éventuelles mises +à jour à faire sur les librairies Javascript utilisées. +N'oubliez pas de mettre à jour à la fois le fichier +de la librairie, mais également sa version dans `sith/settings.py`. + +```bash +# Vérifier les mises à jour +python manage.py check_front +``` diff --git a/docs/tutorial/perms.md b/docs/tutorial/perms.md new file mode 100644 index 00000000..f8e5ad14 --- /dev/null +++ b/docs/tutorial/perms.md @@ -0,0 +1,198 @@ + +## Les permissions + +Le site n'utilise pas le système de permissions intégré de Django, +mais un système de conception maison. + +### Protéger un modèle + +La gestion des permissions se fait directement par modèle. +Il existe trois niveaux de permission : + +- Éditer des propriétés de l'objet +- Éditer certaines valeurs l'objet +- Voir l'objet + +Chacune de ces permissions est vérifiée par une méthode +dédiée de la classe `User` : + +- Editer les propriéts : `User.is_owner(obj)` +- Editer les valeurs : `User.can_edit(obj)` +- Voir : `User.can_view(obj)` + +Ces méthodes vont alors résoudre les permissions +dans cet ordre : + +1. Si l'objet possède une méthode `can_be_viewed_by(user)` + (ou `can_be_edited_by(user)`, ou `is_owned_by(user)`) + et que son appel renvoie `True`, l'utilisateur a la permission requise. +2. Sinon, si le modèle de l'objet possède un attribut `view_groups` + (ou `edit_groups`, ou `owner_group`) et que l'utilisateur + est dans l'un des groupes indiqués, il a la permission requise. +3. Sinon, on regarde si l'utilisateur a la permission de niveau supérieur + (les droits `owner` impliquent les droits d'édition, et les droits + d'édition impliquent les droits de vue). +4. Si aucune des étapes si dessus ne permet d'établir que l'utilisateur + n'a la permission requise, c'est qu'il ne l'a pas. + +Voici un exemple d'implémentation de ce système : + +=== "Avec les méthodes" + + ```python + from django.db import models + from django.utils.translation import gettext_lazy as _ + + from core.models import User, Group + + # Utilisation de la protection par fonctions + class Article(models.Model): + + title = models.CharField(_("title"), max_length=100) + content = models.TextField(_("content")) + + # Donne ou non les droits d'édition des propriétés de l'objet + # Un utilisateur dans le bureau AE aura tous les droits sur cet objet + def is_owned_by(self, user): + return user.is_board_member + + # Donne ou non les droits d'édition de l'objet + # L'objet ne sera modifiable que par un utilisateur cotisant + def can_be_edited_by(self, user): + return user.is_subscribed + + # Donne ou non les droits de vue de l'objet + # Ici, l'objet n'est visible que par un utilisateur connecté + def can_be_viewed_by(self, user): + return not user.is_anonymous + ``` + +=== "Avec les groupes de permission" + + ```python + from django.db import models + from django.conf import settings + from django.utils.translation import gettext_lazy as _ + + from core.models import User, Group + + class Article(models.Model): + title = models.CharField(_("title"), max_length=100) + content = models.TextField(_("content")) + + # relation one-to-many + # Groupe possédant l'objet + # Donne les droits d'édition des propriétés de l'objet + owner_group = models.ForeignKey( + Group, related_name="owned_articles", default=settings.SITH_GROUP_ROOT_ID + ) + + # relation many-to-many + # Tous les groupes qui seront ajouté dans ce champ auront les droits d'édition de l'objet + edit_groups = models.ManyToManyField( + Group, + related_name="editable_articles", + verbose_name=_("edit groups"), + blank=True, + ) + + # relation many-to-many + # Tous les groupes qui seront ajouté dans ce champ auront les droits de vue de l'objet + view_groups = models.ManyToManyField( + Group, + related_name="viewable_articles", + verbose_name=_("view groups"), + blank=True, + ) + ``` + +### Appliquer les permissions + +#### Dans un template + +Il existe trois fonctions de base sur lesquelles +reposent les vérifications de permission. +Elles sont disponibles dans le contexte par défaut du +moteur de template et peuvent être utilisées à tout moment. + +- `can_edit_prop(obj, user)` : équivalent de `obj.is_owned_by(user)` +- `can_edit(obj, user)` : équivalent de `obj.can_be_edited_by(user)` +- `can_view(obj, user)` : équivalent de `obj.can_be_viewed_by(user)` + +Voici un exemple d'utilisation dans un template : + +```jinja +{# ... #} +{% if can_edit(club, user) %} + {{ club }} +{% endif %} +``` + +#### Dans une vue + +Généralement, les vérifications de droits dans les templates +se limitent aux urls à afficher puisqu'il +ne faut normalement pas mettre de logique autre que d'affichage à l'intérieur +(en réalité, c'est un principe qu'on a beaucoup violé, mais promis on le fera plus). +C'est donc habituellement au niveau des vues que cela a lieu. + +Notre système s'appuie sur un système de mixin +à hériter lors de la création d'une vue basée sur une classe. +Ces mixins ne sont compatibles qu'avec les classes récupérant +un objet ou une liste d'objet. +Dans le cas d'un seul objet, +une permission refusée est levée lorsque l'utilisateur +n'a pas le droit de visionner la page. +Dans le cas d'une liste d'objet, +le mixin filtre les objets non autorisés et si aucun ne l'est, +l'utilisateur recevra une liste vide d'objet. + +Voici un exemple d'utilisation en reprenant l'objet Article crée précédemment : + +```python +from django.views.generic import CreateView, ListView + +from core.views import CanViewMixin, CanCreateMixin + +from com.models import WeekmailArticle + +# Il est important de mettre le mixin avant la classe héritée de Django +# L'héritage multiple se fait de droite à gauche et les mixins ont besoin +# d'une classe de base pour fonctionner correctement. +class ArticlesListView(CanViewMixin, ListView): + model = WeekmailArticle + + +# Même chose pour une vue de création de l'objet Article +class ArticlesCreateView(CanCreateMixin, CreateView): + model = WeekmailArticle +``` + +Les mixins suivants sont implémentés : + +- `CanCreateMixin` : l'utilisateur peut-il créer l'objet ? +- `CanEditPropMixin` : l'utilisateur peut-il éditer les propriétés de l'objet ? +- `CanEditMixin` : L'utilisateur peut-il éditer l'objet ? +- `CanViewMixin` : L'utilisateur peut-il voir l'objet ? +- `UserIsRootMixin` : L'utilisateur a-t-il les droit root ? +- `FormerSubscriberMixin` : L'utilisateur a-t-il déjà été cotisant ? +- `UserIsLoggedMixin` : L'utilisateur est-il connecté ? + (à éviter ; préférez `LoginRequiredMixin`, fourni par Django) + +!!!danger "Performance" + + Ce système maison de permissions ne rend pas trop mal, d'un point de vue esthétique. + Mais d'un point de vue performance, c'est un désastre. + Vérifier une seule permission peut demander plusieurs requêtes à la db. + Et chaque vérification recommence dès le début. + Il n'y a aucune jointure en db. + Le mieux qu'on a trouvé comme pansement sur ça, c'est utiliser le cache, + mais c'est seulement un pansement, qui ne rattrape pas les erreurs architecturales. + + Sur une vue où on manipule un seul objet, passe encore. + Mais sur les `ListView`, on peut arriver à des temps + de réponse extrêmement élevés. + + Faites donc doublement, triplement, quadruplement attention, + quand vous manipulez le système de permissions. + diff --git a/docs/tutorial/structure.md b/docs/tutorial/structure.md new file mode 100644 index 00000000..1f6b351f --- /dev/null +++ b/docs/tutorial/structure.md @@ -0,0 +1,207 @@ +## La structure d'un projet Django + +Un projet Django est structuré en applications. +Une application est un package Python +contenant un ensemble de vues, de modèles, de templates, etc. +Sémantiquement, une application représente +un ensemble de fonctionnalités cohérentes. +Par exemple, dans notre cas, nous avons une application +chargée de la gestion des comptoirs, une autre de la gestion +des clubs, une autre de la gestion du SAS, etc. + +On trouve généralement dans un projet Django +une application principale qui contient les +fichiers de configuration du projet, +les urls et éventuellement des commandes d'administration. + +## Arborescence du projet + +Le code source du projet est organisé comme suit : + +
+``` +sith3/ +├── .github/ +│ ├── actions/ (1) +│ └── workflows/ (2) +├── accounting/ (3) +│ └── ... +├── api/ (4) +│ └── ... +├── club/ (5) +│ └── ... +├── com/ (6) +│ └── ... +├── core/ (7) +│ └── ... +├── counter/ (8) +│ └── ... +├── docs/ (9) +│ └── ... +├── eboutic/ (10) +│ └── ... +├── election/ (11) +│ └── ... +├── forum/ (12) +│ └── ... +├── galaxy/ (13) +│ └── ... +├── launderette/ (14) +│ └── ... +├── locale/ (15) +│ └── ... +├── matmat/ (16) +│ └── ... +├── pedagogy/ (17) +│ └── ... +├── rootplace/ (18) +│ └── ... +├── sas/ (19) +│ └── ... +├── sith/ (20) +│ └── ... +├── stock/ (21) +│ └── ... +├── subscription/ (22) +│ └── ... +├── trombi/ (23) +│ └── ... +│ +├── .coveragerc (24) +├── .envrc (25) +├── .gitattributes +├── .gitignore +├── .mailmap +├── .env.exemple +├── manage.py (26) +├── mkdocs.yml (27) +├── poetry.lock +├── pyproject.toml (28) +└── README.md +``` +
+ +1. Dossier contenant certaines actions réutilisables + dans des workflows Github. Par exemple, l'action + `setup-project` installe poetry puis appelle + la commande `poetry install`. +2. Dossier contenant les fichiers de configuration + des workflows Github. + Par exemple, le workflow `docs.yml` compile + et publie la documentation à chaque push sur la branche `master`. +3. Application de gestion de la comptabilité. +4. Application contenant des routes d'API. +5. Application de gestion des clubs et de leurs membres. +6. Application contenant les fonctionnalités + destinées aux responsables communication de l'AE. +7. Application contenant la modélisation centrale du site. + On en reparle plus loin sur cette page. +8. Application de gestion des comptoirs, des permanences + sur ces comptoirs et des transactions qui y sont effectuées. +9. Dossier contenant la documentation. +10. Application de gestion de la boutique en ligne. +11. Application de gestion des élections. +12. Application de gestion du forum +13. Application de gestion de la galaxie ; la galaxie + est un graphe des niveaux de proximité entre les différents + étudiants. +14. Gestion des machines à laver de l'AE +15. Dossier contenant les fichiers de traduction. +16. Fonctionnalités de recherche d'utilisateurs. +17. Le guide des UEs du site, sur lequel les utilisateurs + peuvent également laisser leurs avis. +18. Fonctionnalités utiles aux utilisateurs root. +19. Le SAS, où l'on trouve toutes les photos de l'AE. +20. Application principale du projet, contenant sa configuration. +21. Gestion des stocks des comptoirs. +22. Gestion des cotisations des utilisateurs du site. +23. Gestion des trombinoscopes. +24. Fichier de configuration de coverage. +25. Fichier de configuration de direnv. +26. Fichier généré automatiquement par Django. C'est lui + qui permet d'appeler des commandes de gestion du projet + avec la syntaxe `python ./manage.py ` +27. Le fichier de configuration de la documentation, + avec ses plugins et sa table des matières. +28. Le fichier où sont déclarés les dépendances et la configuration + de certaines d'entre elles. + + +## L'application principale + +L'application principale du projet est le package `sith`. +Ce package contient les fichiers de configuration du projet, +la racine des urls. + +Il est organisé comme suit : + +
+``` +sith/ +├── settings.py (1) +├── settings_custom.py (2) +├── toolbar_debug.py (3) +├── urls.py (4) +└── wsgi.py (5) +``` +
+ +1. Fichier de configuration du projet. + Ce fichier contient les paramètres de configuration du projet. + Par exemple, il contient la liste des applications + installées dans le projet. +2. Configuration maison pour votre environnement. + Toute variable que vous définissez dans ce fichier sera prioritaire + sur la configuration donnée dans `settings.py`. +3. Configuration de la barre de debug. + C'est inutilisé en prod, mais c'est très pratique en développement. +4. Fichier de configuration des urls du projet. +5. Fichier de configuration pour le serveur WSGI. + WSGI est un protocole de communication entre le serveur + et les applications. + Ce fichier ne vous servira sans doute pas sur un environnement + de développement, mais il est nécessaire en production. + +## Les applications + +Les applications sont des packages Python. +Dans ce projet, les applications sont généralement organisées +comme suit : + +
+``` +. +├── migrations/ (1) +│ └── ... +├── templates/ (2) +│ └── ... +├── admin.py (3) +├── models.py (4) +├── tests.py (5) +├── urls.py (6) +└── views.py (7) +``` +
+ +1. Dossier contenant les migrations de la base de données. + Les migrations sont des fichiers Python qui permettent + de mettre à jour la base de données. + cf. [Gestion des migrations](../howto/migrations.md) +2. Dossier contenant les templates jinja utilisés par cette application. +3. Fichier de configuration de l'interface d'administration. + Ce fichier permet de déclarer les modèles de l'application + dans l'interface d'administration. +4. Fichier contenant les modèles de l'application. + Les modèles sont des classes Python qui représentent + les tables de la base de données. +5. Fichier contenant les tests de l'application. +6. Configuration des urls de l'application. +7. Fichier contenant les vues de l'application. + Dans les plus grosses applications, + ce fichier peut être remplacé par un package + `views` dans lequel les vues sont réparties entre + plusieurs fichiers. + +L'organisation peut éventuellement être un peu différente +pour certaines applications, mais le principe +général est le même. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..7b53fead --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,157 @@ +site_name: Site AE UTBM +site_description: Le site de l'association des étudiants de l'UTBM +dev_addr: 127.0.0.1:8080 + +repo_name: sith3 +repo_url: https://github.com/ae-utbm/sith3 +site_url: https://ae-utbm.github.io/sith3 + +theme: + features: + - navigation.footer + - content.code.annotate + - content.code.copy + - content.tabs.link + name: material + palette: + - media: "(prefers-color-scheme: light)" + scheme: default + primary: deeppurple + accent: deeppurple + toggle: + icon: material/toggle-switch + name: Switch to dark mode + + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: blue + accent: blue + toggle: + icon: material/toggle-switch-off-outline + name: Switch to light mode + + language: fr + icon: + repo: fontawesome/brands/git-alt + favicon: img/favicon.png + + +plugins: + - mkdocstrings: + default_handler: python + handlers: + python: + options: + members: true + members_order: source + show_source: true + show_inherited_members: true + merge_init_into_class: true + show_root_toc_entry: false + - search +nav: + - Accueil: index.md + - Explications: + - Accueil: explanation/index.md + - Technologies utilisées: explanation/technos.md + - Conventions: explanation/conventions.md + - Tutoriels: + - Installer le projet: tutorial/install.md + - Configurer son éditeur: tutorial/devtools.md + - Structure du projet: tutorial/structure.md + - Gestion des permissions: tutorial/perms.md + - Gestion des groupes: tutorial/groups.md + - Etransactions: tutorial/etransaction.md + - How-to: + - Terminal: howto/terminal.md + - Direnv: howto/direnv.md + - L'ORM de Django: howto/querysets.md + - Gérer les migrations: howto/migrations.md + - Gérer les traductions: howto/translation.md + - Configurer pour la production: howto/prod.md + - Ajouter une cotisation: howto/subscriptions.md + - Modifier le weekmail: howto/weekmail.md + - Reference: + - accounting: + - reference/accounting/models.md + - reference/accounting/views.md + - club: + - reference/club/models.md + - reference/club/views.md + - com: + - reference/com/models.md + - reference/com/views.md + - core: + - reference/core/models.md + - reference/core/views.md + - counter: + - reference/counter/models.md + - reference/counter/views.md + - eboutic: + - reference/eboutic/models.md + - reference/eboutic/views.md + - election: + - reference/election/models.md + - reference/election/views.md + - forum: + - reference/forum/models.md + - reference/forum/views.md + - galaxy: + - reference/galaxy/models.md + - reference/galaxy/views.md + - launderette: + - reference/launderette/models.md + - reference/launderette/views.md + - matmat: + - reference/matmat/models.md + - reference/matmat/views.md + - pedagogy: + - reference/pedagogy/models.md + - reference/pedagogy/views.md + - rootplace: + - reference/rootplace/models.md + - reference/rootplace/views.md + - sas: + - reference/sas/models.md + - reference/sas/views.md + - stock: + - reference/stock/models.md + - reference/stock/views.md + - subscription: + - reference/subscription/models.md + - reference/subscription/views.md + - trombi: + - reference/trombi/models.md + - reference/trombi/views.md + + +markdown_extensions: + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - admonition + - attr_list + - def_list + - md_in_html + - pymdownx.details + - pymdownx.inlinehilite + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + clickable_checkbox: true + - pymdownx.tilde: + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - toc: + permalink: true + toc_depth: 3 + +extra_css: + - stylesheets/extra.css \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index d42d0573..7629b8c9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -256,6 +256,20 @@ files = [ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + [[package]] name = "colorama" version = "0.4.6" @@ -477,13 +491,13 @@ test = ["djangorestframework", "graphene-django", "pytest", "pytest-cov", "pytes [[package]] name = "django-debug-toolbar" -version = "4.4.5" +version = "4.4.6" description = "A configurable set of panels that display various debug information about the current request/response." optional = false python-versions = ">=3.8" files = [ - {file = "django_debug_toolbar-4.4.5-py3-none-any.whl", hash = "sha256:91425606673ee674d780f7aeedf3595c264eb382dcf41f55c6779577900904c0"}, - {file = "django_debug_toolbar-4.4.5.tar.gz", hash = "sha256:8298ce966b4c8fc71430082dd4739ef2badb5f867734e1973a413c4ab2ea81b7"}, + {file = "django_debug_toolbar-4.4.6-py3-none-any.whl", hash = "sha256:3beb671c9ec44ffb817fad2780667f172bd1c067dbcabad6268ce39a81335f45"}, + {file = "django_debug_toolbar-4.4.6.tar.gz", hash = "sha256:36e421cb908c2f0675e07f9f41e3d1d8618dc386392ec82d23bcfcd5d29c7044"}, ] [package.dependencies] @@ -614,13 +628,13 @@ django = ">=4.2" [[package]] name = "docutils" -version = "0.18.1" +version = "0.19" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, - {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, + {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, + {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, ] [[package]] @@ -681,6 +695,37 @@ files = [ [package.dependencies] python-dateutil = ">=2.7" +[[package]] +name = "ghp-import" +version = "2.1.0" +description = "Copy your docs directly to the gh-pages branch." +optional = false +python-versions = "*" +files = [ + {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, + {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, +] + +[package.dependencies] +python-dateutil = ">=2.8.1" + +[package.extras] +dev = ["flake8", "markdown", "twine", "wheel"] + +[[package]] +name = "griffe" +version = "0.47.0" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." +optional = false +python-versions = ">=3.8" +files = [ + {file = "griffe-0.47.0-py3-none-any.whl", hash = "sha256:07a2fd6a8c3d21d0bbb0decf701d62042ccc8a576645c7f8799fe1f10de2b2de"}, + {file = "griffe-0.47.0.tar.gz", hash = "sha256:95119a440a3c932b13293538bdbc405bee4c36428547553dc6b327e7e7d35e5a"}, +] + +[package.dependencies] +colorama = ">=0.4" + [[package]] name = "identify" version = "2.6.0" @@ -816,6 +861,21 @@ files = [ {file = "libsass-0.22.0.tar.gz", hash = "sha256:3ab5ad18e47db560f4f0c09e3d28cf3bb1a44711257488ac2adad69f4f7f8425"}, ] +[[package]] +name = "markdown" +version = "3.6" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, + {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, +] + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + [[package]] name = "markupsafe" version = "2.1.5" @@ -899,6 +959,17 @@ files = [ [package.dependencies] traitlets = "*" +[[package]] +name = "mergedeep" +version = "1.3.4" +description = "A deep merge function for ðŸ." +optional = false +python-versions = ">=3.6" +files = [ + {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, + {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, +] + [[package]] name = "mistune" version = "3.0.2" @@ -910,6 +981,149 @@ files = [ {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] +[[package]] +name = "mkdocs" +version = "1.6.0" +description = "Project documentation with Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7"}, + {file = "mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +ghp-import = ">=1.0" +jinja2 = ">=2.11.1" +markdown = ">=3.3.6" +markupsafe = ">=2.0.1" +mergedeep = ">=1.3.4" +mkdocs-get-deps = ">=0.2.0" +packaging = ">=20.5" +pathspec = ">=0.11.1" +pyyaml = ">=5.1" +pyyaml-env-tag = ">=0.1" +watchdog = ">=2.0" + +[package.extras] +i18n = ["babel (>=2.9.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-autorefs" +version = "1.0.1" +description = "Automatically link across pages in MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_autorefs-1.0.1-py3-none-any.whl", hash = "sha256:aacdfae1ab197780fb7a2dac92ad8a3d8f7ca8049a9cbe56a4218cd52e8da570"}, + {file = "mkdocs_autorefs-1.0.1.tar.gz", hash = "sha256:f684edf847eced40b570b57846b15f0bf57fb93ac2c510450775dcf16accb971"}, +] + +[package.dependencies] +Markdown = ">=3.3" +markupsafe = ">=2.0.1" +mkdocs = ">=1.1" + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, + {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, +] + +[package.dependencies] +mergedeep = ">=1.3.4" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" + +[[package]] +name = "mkdocs-material" +version = "9.5.28" +description = "Documentation that simply works" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material-9.5.28-py3-none-any.whl", hash = "sha256:ff48b11b2a9f705dd210409ec3b418ab443dd36d96915bcba45a41f10ea27bfd"}, + {file = "mkdocs_material-9.5.28.tar.gz", hash = "sha256:9cba305283ad1600e3d0a67abe72d7a058b54793b47be39930911a588fe0336b"}, +] + +[package.dependencies] +babel = ">=2.10,<3.0" +colorama = ">=0.4,<1.0" +jinja2 = ">=3.0,<4.0" +markdown = ">=3.2,<4.0" +mkdocs = ">=1.6,<2.0" +mkdocs-material-extensions = ">=1.3,<2.0" +paginate = ">=0.5,<1.0" +pygments = ">=2.16,<3.0" +pymdown-extensions = ">=10.2,<11.0" +regex = ">=2022.4" +requests = ">=2.26,<3.0" + +[package.extras] +git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"] +imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"] +recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] + +[[package]] +name = "mkdocs-material-extensions" +version = "1.3.1" +description = "Extension pack for Python Markdown and MkDocs Material." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, + {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, +] + +[[package]] +name = "mkdocstrings" +version = "0.25.1" +description = "Automatic documentation from sources, for MkDocs." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocstrings-0.25.1-py3-none-any.whl", hash = "sha256:da01fcc2670ad61888e8fe5b60afe9fee5781017d67431996832d63e887c2e51"}, + {file = "mkdocstrings-0.25.1.tar.gz", hash = "sha256:c3a2515f31577f311a9ee58d089e4c51fc6046dbd9e9b4c3de4c3194667fe9bf"}, +] + +[package.dependencies] +click = ">=7.0" +Jinja2 = ">=2.11.1" +Markdown = ">=3.3" +MarkupSafe = ">=1.1" +mkdocs = ">=1.4" +mkdocs-autorefs = ">=0.3.1" +platformdirs = ">=2.2.0" +pymdown-extensions = ">=6.3" + +[package.extras] +crystal = ["mkdocstrings-crystal (>=0.3.4)"] +python = ["mkdocstrings-python (>=0.5.2)"] +python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] + +[[package]] +name = "mkdocstrings-python" +version = "1.10.5" +description = "A Python handler for mkdocstrings." +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocstrings_python-1.10.5-py3-none-any.whl", hash = "sha256:92e3c588ef1b41151f55281d075de7558dd8092e422cb07a65b18ee2b0863ebb"}, + {file = "mkdocstrings_python-1.10.5.tar.gz", hash = "sha256:acdc2a98cd9d46c7ece508193a16ca03ccabcb67520352b7449f84b57c162bdf"}, +] + +[package.dependencies] +griffe = ">=0.47" +mkdocstrings = ">=0.25" + [[package]] name = "nodeenv" version = "1.9.1" @@ -932,6 +1146,16 @@ files = [ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "paginate" +version = "0.5.6" +description = "Divides large result sets into pages for easier browsing" +optional = false +python-versions = "*" +files = [ + {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, +] + [[package]] name = "parso" version = "0.8.4" @@ -947,6 +1171,17 @@ files = [ qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["docopt", "pytest"] +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + [[package]] name = "pexpect" version = "4.9.0" @@ -1273,6 +1508,24 @@ files = [ {file = "pygraphviz-1.13.tar.gz", hash = "sha256:6ad8aa2f26768830a5a1cfc8a14f022d13df170a8f6fdfd68fd1aa1267000964"}, ] +[[package]] +name = "pymdown-extensions" +version = "10.8.1" +description = "Extension pack for Python Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"}, + {file = "pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940"}, +] + +[package.dependencies] +markdown = ">=3.6" +pyyaml = "*" + +[package.extras] +extra = ["pygments (>=2.12)"] + [[package]] name = "pytest" version = "8.2.2" @@ -1404,6 +1657,108 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +description = "A custom YAML tag for referencing environment variables in YAML files. " +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, + {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, +] + +[package.dependencies] +pyyaml = "*" + +[[package]] +name = "regex" +version = "2024.5.15" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.8" +files = [ + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, + {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, + {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, + {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, + {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, + {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, + {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, + {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, + {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, + {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, + {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, + {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, +] + [[package]] name = "reportlab" version = "4.2.2" @@ -1575,43 +1930,6 @@ docs = ["sphinxcontrib-websupport"] lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"] test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] -[[package]] -name = "sphinx-copybutton" -version = "0.4.0" -description = "Add a copy button to each of your code cells." -optional = false -python-versions = ">=3.6" -files = [ - {file = "sphinx-copybutton-0.4.0.tar.gz", hash = "sha256:8daed13a87afd5013c3a9af3575cc4d5bec052075ccd3db243f895c07a689386"}, - {file = "sphinx_copybutton-0.4.0-py3-none-any.whl", hash = "sha256:4340d33c169dac6dd82dce2c83333412aa786a42dd01a81a8decac3b130dc8b0"}, -] - -[package.dependencies] -sphinx = ">=1.8" - -[package.extras] -code-style = ["pre-commit (==2.12.1)"] -rtd = ["ipython", "sphinx", "sphinx-book-theme"] - -[[package]] -name = "sphinx-rtd-theme" -version = "1.3.0" -description = "Read the Docs theme for Sphinx" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -files = [ - {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"}, - {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"}, -] - -[package.dependencies] -docutils = "<0.19" -sphinx = ">=1.6,<8" -sphinxcontrib-jquery = ">=4,<5" - -[package.extras] -dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] - [[package]] name = "sphinxcontrib-applehelp" version = "1.0.8" @@ -1660,20 +1978,6 @@ lint = ["docutils-stubs", "flake8", "mypy"] standalone = ["Sphinx (>=5)"] test = ["html5lib", "pytest"] -[[package]] -name = "sphinxcontrib-jquery" -version = "4.1" -description = "Extension to include jQuery on newer Sphinx releases" -optional = false -python-versions = ">=2.7" -files = [ - {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, - {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, -] - -[package.dependencies] -Sphinx = ">=1.8" - [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" @@ -1839,6 +2143,50 @@ platformdirs = ">=3.9.1,<5" docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] +[[package]] +name = "watchdog" +version = "4.0.1" +description = "Filesystem events monitoring" +optional = false +python-versions = ">=3.8" +files = [ + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"}, + {file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"}, + {file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"}, + {file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"}, + {file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"}, +] + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + [[package]] name = "wcwidth" version = "0.2.13" @@ -1868,4 +2216,4 @@ filelock = ">=3.4" [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "7141b65a46fc8dda32aed5df6ca3873e40ff36f2fdb55f0e4732c58660738c52" +content-hash = "d6d524c293fe2560487d9b9e6287f0d4a369294ba30be0de4a3ff092844b9a4e" diff --git a/pyproject.toml b/pyproject.toml index ec918b14..09fb4df4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ license = "GPL-3.0-only" [tool.poetry.dependencies] python = "^3.10" -Django = "^4.2.13" +Django = "^4.2.14" Pillow = "^10.4.0" mistune = "^3.0.2" django-jinja = "^2.11" @@ -37,7 +37,6 @@ libsass = "^0.22" django-ordered-model = "^3.7" django-simple-captcha = "^0.5.17" python-dateutil = "^2.8.2" -psycopg2-binary = "^2.9" sentry-sdk = "^1.21.0" pygraphviz = "^1.1" Jinja2 = "^3.1" @@ -47,21 +46,33 @@ Sphinx = "^5" # Needed for building xapian tomli = "^2.0.1" django-honeypot = "^1.2.0" +# deps used in prod, but unnecessary for development +[tool.poetry.group.prod.dependencies] +psycopg2-binary = "^2.9" + +[tool.poetry.group.prod] +optional = true + +# deps used for development purposes, but unneeded in prod [tool.poetry.group.dev.dependencies] django-debug-toolbar = "^4.0.0" ipython = "^8.26.0" pre-commit = "^3.7.1" ruff = "^0.5.1" # Version used in pipeline is controlled by pre-commit hooks in .pre-commit.config.yaml +# deps used for testing purposes [tool.poetry.group.tests.dependencies] freezegun = "^1.2.2" # used to test time-dependent code pytest = "^8.2.2" pytest-cov = "^5.0.0" pytest-django = "^4.8.0" +# deps used to work on the documentation [tool.poetry.group.docs.dependencies] -sphinx-rtd-theme = "^1.0.0" -sphinx-copybutton = "^0.4.0" +mkdocs = "^1.6.0" +mkdocs-material = "^9.5.28" +mkdocstrings = "^0.25.1" +mkdocstrings-python = "^1.10.5" [tool.poetry.group.docs] optional = true