Voici le backend de l'application pass Culture; il est lancé via docker-compose
en utilisant le fichier
docker-compose-backend.yml
du répertoire parent de api
: pass-culture-main
.
Plus de détails sur le lancement de l'infra docker-compose sont accessibles dans le README de pass-culture-main
Une documentation Swagger des APIs est générée selon l'OpenAPI Specification (OAS3) grâce à un schéma généré par Spectree:
- API Contremarque
- App Native
- Adage
- API privée et API publique dépréciée
- API pro publique v2
- API pro privée
- API publique d'offres individuelles
Avec poetry
et Python 3.11 :
curl -sSL https://install.python-poetry.org | python3 -
poetry env use python3.11
poetry install --with dev
La bonne version de python est à installer soit à travers le gestionnaire de paquet du système d'exploitation,
soit en utilisant pyenv
.
La génération de PDF via weasyprint
nécessite également de suivre
ces étapes d'installation.
Le lint des migrations, effectué lors du hook de precommit, nécessite Squawk — a linter for Postgres migrations.
npm install --global squawk-cli
On utilise Poetry pour gérer nos dépendances. Par défaut, Poetry crée l'environnement virtuel dans un dossier qui dépend du système d'exploitation.
La méthode recommandée d'activer son environnement virtuel est avec la commande poetry shell
.
Pour un usage avancé comme avoir plusieurs environnements virtuels, il existe d'autres manières d'activer son environnement virtuel.
Une gestion plus fine de l'environnement virtuel utilisé par poetry
peut être trouvée sur ce lien : Managing environments | Documentation | Poetry
NOTE : Poetry n'est pas utilisé dans les conteneurs Docker, i.e. la commande flask
est directement accessible.
NOTE : L'ajout de dépendance doit se faire par Poetry pour mettre à jour le fichier lock.
- Verifier que
PostGIS
est bien installé. Si ce n'est pas le cas: pour installerPostGIS
dans les systèmes d'exploitation qui ne le fournissent pas avecPostgreSQL
:- Linux :
apt install postgis
pour Ubuntu oupacman -S postgis
pour Arch Linux - Windows : après l'installation de
PostgreSQL
, Stackbuilder permet d'installerPostGIS
- MacOS :
PostGIS
est fourni avec la distribution Postgres.app. Si une autre manière d'installerPostgreSQL
a été choisie, alors la commande d'installation estbrew install postgis
- Linux :
- Démarrer les services postgresql et redis, par exemple lorsqu'ils ont été installés via Homebrew:
brew services start postgresql brew services start redis
Prérequis au lancement des tests
Une base de données de test et un cache redis sont nécessaires à l'exécution des tests.
- Soit en démarrant les conteneurs de la base de données pc-postgres-test (spécifique aux tests) et du cache redis via docker-compose
docker-compose -f ../docker-compose-backend.yml up -d postgres-test redis
- Soit en démarrant ces conteneurs via docker
docker run -d --name postgres -p 5434:5432 \
--env-file ../env_file \
-v postgres_local_data:/var/lib/postgresql/data \
postgis/postgis:15-3.4-alpine
docker run -d --name redis -p 6379:6379 \
-v redis_local_data:/data \
redis redis-server
Les tests pourront ensuite être exécutés avec ou sans docker-compose
-
Lancement des tests via docker-compose
pc test-backend # Pour lancer tous les tests pc test-backend tests/core/offers/test_api.py::CreateOfferTest::test_create_offer_from_scratch # Pour lancer un test en particulier
-
Lancement des tests depuis la ligne de commande dans un
poetry shell
. Il est ainsi très simple d'accéder àstdin
/stdout
via le paramètre-s
, par exemple pour utiliser des breakpoints.pytest # Pour lancer tous les tests pytest tests/core/offers/test_api.py::CreateOfferTest::test_create_offer_from_scratch # Pour lancer un test en particulier
-
Les tests du backoffice ne peuvent pas être exécutés en même temps que le reste. Pour jouer tous les tests en une commande, il est possible d'utiliser dans un
poetry shell
pytest -m 'not backoffice' && \ pytest -m 'backoffice'
Les tests utilisent leur propre base de données. Si un test a besoin d'accéder à la base de données, il faut décorer la fonction ou la classe avec:
@pytest.mark.usefixtures("db_session")
pour encapsuler le test dans une transaction. On peut aussi marquer le module entier en ajoutant sous les imports:
pytestmark = pytest.mark.usefixtures("db_session")
Les différentes fixtures utilisées dans les tests sont définies dans tests/conftest.py
Les variables d'environnement nécessaires au bon fonctionnement mais qui porte des données sensibles (identifiants, clés d'API, ...)
ne sont pas enregistrés dans les fichiers d'environnement du dépôt.
Il faut les ajouter dans le fichier api/.env.local.secret
.
Une Github Action est lancée à chaque push sur le repo, lançant un scan de fuites de secrets GitGuardian.
Pour ignorer un faux positif, il convient d'ajouter un commentaire inline dans le code: # ggignore
cf https://github.com/GitGuardian/ggshield#in-code
pc start-backend
Si la base de données n'a pas été initialisée, vous devez suivre les étapes suivantes :
-
Soit en lançant la commande suivante qui va créer les bases de données pour l'api et pour les tests, installer les extensions postgres et jouer les migrations
pc setup-no-docker
-
Soit en réalisant les étapes suivantes une par une:
-
créer les users suivants:
CREATE ROLE pass_culture SUPERUSER LOGIN PASSWORD 'passq'; CREATE ROLE pytest SUPERUSER LOGIN PASSWORD 'pytest';
-
Ajouter ces variables au fichier
.env.local.secret
à la racine du dossierapi/
(en complétant par le port de votre serveur postgresql, habituellement5432
):DATABASE_URL=postgresql://pass_culture:passq@localhost:<port>/pass_culture DATABASE_URL_TEST=postgresql://pytest:pytest@localhost:<port>/pass_culture_test
-
créer les databases associés (cf. les commandes
recreate_database
recreate_database_test
dans le fichierstart_backend_no_docker
) -
Installer les extensions et jouer les migrations en ayant dans le
poetry shell
:flask install_postgres_extensions alembic upgrade pre@head alembic upgrade post@head
-
-
Vous pouvez maintenant lancer l'application Flask
python src/pcapi/app.py
-
Vous pouvez également lancer les tests sans docker depuis un
poetry shell
avecpytest
de la même façon qu'expliqué précédemment -
Vous pouvez également utiliser les commandes suivantes
# Lancer l'API pc start-api-no-docker # Lancer le Backoffice pc start-backoffice-no-docker # Nettoyer les DB, reconstruire la sandbox et jouer les migrations pc restart-api-no-docker # Supprimer et recréer les DB (test et data) pc reset-db-no-docker # Supprimer et recréer la DB de test pc reset-db-test-no-docker
Si vous souhaitez (ré)utiliser docker par la suite, n'oubliez pas de commenter DATABASE_URL
et DATABASE_URL_TEST
dans .env.local.secret
, et d'arrêter le service redis-server
Afin de naviguer/tester différentes situations de données, il existe dans api des scripts permettant d'engendrer des bases de données "sandbox".
La plus conséquente est industrial
, elle se créée depuis un poetry shell
via la commande:
flask sandbox -n industrial
Troubleshooting:
Si la commande sandbox renvoie des erreurs que je n'arrive pas à résoudre, tester de supprimer et reconstruire sa BDD locale. Pour ça:
- stopper les images lancées
- run:
docker rm -f pc-postgres
<= suppression container - run:
docker volume rm pass-culture-main_postgres_data
<= suppression données - relancer:
pc start-backend
- puis relancer:
pc sandbox -n industrial
Le backend ne permet pas (encore) de s'authentifier directement. On peut s'authentifier de deux manières:
- En se connectant sur Pro. Une fois authentifié, un cookie de session est stocké et le back validera le cookie.
- Sans session depuis le front Pro, une authentification est proposée via Google Account. Seuls les utilisateurs du projet passculture.app sont autorisés.
Il est possible de se connecter aux bases de données lancées via docker compose en utilisant les informations ci-dessous
-
pc-postgres
- user : pass_culture
- password : passq
- port : 5434
- database : pass_culture
-
pc-postgres-test
- user : pytest
- password : pytest
- port : 5433
- database : pass_culture
- Lancer python avec docker:
pc python
- Dans l'éditeur de code, identifier la factory
pcapi.core
. Tous les arguments sont renseignés par défaut et peuvent être surchargés. - importer la factory et l'utiliser: les données sont disponibles en localhost
>>> from pcapi.core.users.factories import UserFactory;
>>> UserFactory(email='user@example.com’);
On peut ensuite se connecter avec ce mail et le mot de passe par défaut en localhost.
>>> from pcapi.core.users.factories import UserFactory;
>>> user = UserFactory(email='marie2@app.com’)
>>> from pcapi.core.offerers.factories import OffererFactory
>>> factory = OffererFactory(siren=444444444)
>>> from pcapi.core.offerers.factories import UserOffererFactory
>>> UserOffererFactory(user, offerer)
On peut aussi surcharger directement les arguments des factories appelées par d'autres factories, en préfixant l'argument avec le nom de la factory secondaire suivie d'un double underscore. Les deux lignes suivantes sont équivalentes à celles qui précèdent:
>>> from pcapi.core.offerers.factories import UserOffererFactory
>>> UserOffererFactory(user__email='marie2@app.com’, offerer__siren=444444444)
>>> from pcapi.models import db
>>> db.session.rollback()
Pour une meilleure expérience de développement sur le repo API, des hooks (pre-commit , pre-push ) s'exécutent lorsqu'un commit est effectué sur le projet API,
L'environnement python en local est nécessaire pour que les outils d'analyse de code (isort
, batch
, pylint
...) se
lancent.
Si les hooks ne se lancent pas, lancer pc install-hooks
(commande incluse dans pc install
)
Des fichiers CONTRIBUTING.md
à la racine de différents modules Python du projet apporteront des détails et conseils
spécifiques.
Installer openssl
avec brew install openssl
.
Ajouter openssl
au path LIBRARY_PATH
(path for intel chip brew) export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/opt/openssl/lib/
.
Sur mac, vous pouvez aussi avoir besoin de lancer brew install postgresql
.
Autre piste.
Après avoir lancé les tests avec Docker (pc test-backend
), les tests peuvent échouer en les lançant avec Python (python -m pytest
)
Il faut supprimer les fichiers de cache de pré-compilation de Python, par exemple avec la commande suivante
find . -type f -name "*.py[co]" -delete -or -type d -name "__pycache__" -delete
En lançant les tests avec python -m pytest
, si les tests échouent avec ce message E DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13
, il faut les relancer en ajoutant le flag suivant à la commande : -W ignore::DeprecationWarning
(ou éventuellement ajouter un alias au terminal)
Lors d'un changement dans le fichier requirements.py
, une nouvelle image docker de l'api est générée. Il convient de régulièrement supprimer les images "dangling" pour ne pas qu'elles prennent trop de place sur le disque local. (cf doc docker).
docker image prune
Configurer le working directory par défaut pour être toujours à la racine de ce projet
Pour debugger sous IntelliJ Pycharm, configurer la configuration de lancement python en précisant :
-
Le script à lancer :
scr/pcapi/app.py
-
Les variables d'environnement
DATABASE_URL
etPORT
(Sinon le port sera 5001) -
Le répertoire de lancement (Working directory) qui doit pointer vers api
Le fichier de configuration vscode permet notamment de lancer black
et isort
lorsqu'un
fichier est sauvegardé.
Vérifier que l'interpréteur python utilisé par VSCode est le bon. Taper cmd+shift+P
puis Python: select interpreter
et choisir le python précédemment installé en local (virtual env ou pyenv).
Les commandes à lancer régulièrement (par example des synchro journalières) sont définies dans les fichiers src/pcapi/*/commands.py
Pour que les commandes soient enregistrées par Flask, il faut que le fichier path/to/commands.py
soit référencé dans la fonction install_commands
de api/src/pcapi/scripts/install.py
Pour que les commandes soient exécutées, il faut ouvrir une PR sur le repo pass-culture/pass-culture-deployment Les infos sont dans le README