Pour proposer un package Python bien entretenu et utilisable à la communauté open source ou même à l’intérieur de votre entreprise, vous devez accomplir un ensemble d’étapes critiques. Assurez-vous d’abord que votre code est testé unitaire. Deuxièmement, respectez les styles d’écriture et de format courants. Automatisez ces étapes et intégrez-les dans un pipeline d’intégration continue pour éviter toute régression liée aux modifications appliquées à votre code source. Enfin, fournissez une documentation suffisante pour les futurs utilisateurs. Une fois cela fait, il est courant de publier votre package Python sur le Index des packages Python (PyPI). Nous allons voir ici comment accomplir chacune de ces étapes en utilisant Poésie, Toxique et Actions GitHub. Le code utilisé pour notre cas d’utilisation peut être trouvé sur notre référentiel.
Cet article est le dernier d’une série de trois dans laquelle nous partageons nos meilleures pratiques.
Automatisez les vérifications et les tests de charpie avec tox
Si ce n’est pas fait, activez votre environnement virtuel.
Pour vérifier la conformité de notre code, nous utilisons quelques packages qui vont évaluer si le code respecte les directives d’écriture Python courantes. Ensuite, pour automatiser leur exécution ainsi que nos tests unitaires, nous utilisons toxique. Pour les installer, lancez :
poetry add black flake8 pylint tox --dev
tox
et poetry
ne fonctionnent pas bien ensemble par défaut. Ils sont quelque peu redondants. Pour les utiliser ensemble, il faut implémenter quelques astuces (voir problèmes 1941 et 1745). tox
installer son propre environnement et ses dépendances pour exécuter ses tâches. Mais pour installer des dépendances, il faut déclarer la commande poetry install
dans notre tox
configuration. Cela entraîne une redondance et peut conduire à certains problèmes. De plus, cela ne permet pas d’installer les dépendances des développeurs nécessaires à l’exécution de nos tests. Il est plus productif de laisser tox
Utilisez le poetry.lock
fichier pour installer les dépendances nécessaires. Pour cela, je vous conseille d’utiliser le tox-poetry-installer package développé pour résoudre ces problèmes :
poetry add tox-poetry-installer[poetry] --dev
Maintenant, nous déclarons notre tox
configuration dans un tox.ini
fichier dont le contenu est :
[tox]
envlist = py38
isolated_build = true
[testenv]
description = Linting, checking syntax and running tests
require_locked_deps = true
install_dev_deps = true
commands =
poetry run black summarize_dataframe/summarize_df.py
poetry run flake8 summarize_dataframe/summarize_df.py
poetry run pylint summarize_dataframe/summarize_df.py
poetry run pytest -v
Vous pouvez voir deux sections ici :
[tox]
: Définissez les paramètres globaux de votretox
pipeline d’automatisation incluant la version Python des environnements de test.[testenv]
: Définir les environnements de test. Dans notre cas, nous avons des variables supplémentairesrequire_locked_deps
etinstall_dev_deps
qui sont apportés par le tox-poetry-installer forfait.require_locked_deps
est de choisir si vous voulez ou nontox
pour exploiter lepoetry.lock
fichier pour installer les dépendances.install_dev_deps
est de choisir sitox
installe les dépendances du développeur.
Se référer au
tox
Documentation pour en savoir plus sur la configuration ainsi que surtox-poetry-installer
Documentation pour en savoir plus sur la configuration supplémentaire.
Exécutez le tox
pipeline:
tox
py38 run-test: commands[0] | poetry run black summarize_dataframe/summarize_df.py
All done! ✨ 🍰 ✨
1 file left unchanged.
py38 run-test: commands[1] | poetry run flake8 summarize_dataframe/summarize_df.py
py38 run-test: commands[2] | poetry run pylint summarize_dataframe/summarize_df.py
************* Module summarize_dataframe.summarize_df
summarize_dataframe/summarize_df.py:1:0: C0114: Missing module docstring (missing-module-docstring)
summarize_dataframe/summarize_df.py:4:0: C0103: Argument name "df" doesn't conform to snake_case naming style (invalid-name)
summarize_dataframe/summarize_df.py:11:4: C0103: Argument name "df" doesn't conform to snake_case naming style (invalid-name)
summarize_dataframe/summarize_df.py:23:4: C0103: Argument name "df" doesn't conform to snake_case naming style (invalid-name)
summarize_dataframe/summarize_df.py:43:0: C0103: Argument name "df" doesn't conform to snake_case naming style (invalid-name)
------------------------------------------------------------------
Your code has been rated at 7.62/10 (previous run: 7.62/10, +0.00)
ERROR: InvocationError for command /home/fbraza/Documents/python_project/summarize_dataframe/.tox/py38/bin/poetry run pylint summarize_dataframe/summarize_df.py (exited with code 16)
________________________________________________________ summary ________________________________________________________________
ERROR: py38: commands failed
Une erreur est générée car pylint mettre en lumière certaines incohérences de style. Par défaut, tox
se ferme si des avertissements ou des erreurs se sont produits pendant l’exécution des commandes. Les erreurs sont en elles-mêmes assez explicites. Après les avoir corrigés, relancez le pipeline :
tox
py38 run-test: commands[0] | poetry run black summarize_dataframe/summarize_df.py
All done! ✨ 🍰 ✨
1 file left unchanged.
py38 run-test: commands[1] | poetry run flake8 summarize_dataframe/summarize_df.py
py38 run-test: commands[2] | poetry run pylint summarize_dataframe/summarize_df.py
--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
py38 run-test: commands[3] | poetry run pytest -v
================================================= test session starts =============================================================
platform linux -- Python 3.8.7, pytest-5.4.3, py-1.10.0, pluggy-0.13.1 -- /home/fbraza/Documents/python_project/summarize_dataframe/.tox/py38/bin/python
cachedir: .tox/py38/.pytest_cache
rootdir: /home/fbraza/Documents/python_project/summarize_dataframe
collected 2 items
tests/test_summarize_dataframe.py::TestDataSummary::test_data_summary PASSED [ 50%]
tests/test_summarize_dataframe.py::TestDataSummary::test_display PASSED [100%]
================================================= 2 passed in 0.30s ===============================================================
______________________________________________________ summary ____________________________________________________________________
py38: commands succeeded
congratulations :)
Parfait. La tox
le pipeline d’automatisation réussit localement. L’étape suivante commence à implémenter le pipeline CI avec GitHub Actions.
Intégration continue avec les actions GitHub
Les actions GitHub facilitent l’automatisation de tous vos workflows logiciels. Ce service est événementiel, ce qui signifie qu’un ensemble de commandes est déclenché lorsqu’un événement spécifique se produit. De tels événements peuvent être un commit poussé vers la branche ou une demande d’extraction. Les actions GitHub sont assez pratiques pour exécuter tous les tests nécessaires sur votre code.
Plus important encore, GitHub Actions offre la possibilité de tester votre package Python en utilisant plusieurs versions de Python et sur différents systèmes d’exploitation (Linux, macOS et Windows). La seule chose dont vous avez besoin est un référentiel existant et un .github/workflows/
dossier:
mkdir -p .github/workflows
touch .github/workflows/ci.yml
Le contenu de la .github/workflows/ci.yml
fichier est :
name: CI Pipeline for summarize_df
on:
- push
- pull_request
jobs:
build:
runs-on: $matrix.platform
strategy:
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.7, 3.8, 3.9]
steps:
- uses: actions/checkout@v1
- name: Set up Python $ matrix.python-version
uses: actions/setup-python@v2
with:
python-version: $ matrix.python-version
- name: Install dependencies
run: |
python -m pip install poetry
poetry install
- name: Test with tox
run: poetry run tox
Quelques mots sur les différents domaines :
on
: ce champ définit le type d’événement qui va déclencher le pipeline.jobs
: ce champ définit les multiples étapes de votre pipeline. Ils s’exécutent dans une instance d’un environnement virtuel.build
: c’est là que toute la magie opère :- La
strategy.matrix.platform
Le champ définit les différents systèmes d’exploitation que vous souhaitez utiliser pour tester votre package. Utilisez des modèles pour transmettre ces valeurs aubuild.runs-on
champ ($matrix.platform
). - La
strategy.matrix.python-version
définit les différentes versions de Python que vous souhaitez utiliser pour tester votre package. - La
steps
champ vous permet de spécifier les actions que vous utilisez (steps.uses
) et quelle commande vous voulez exécuter (steps.run
)
- La
Avant de terminer, modifiez le tox.ini
et pyporject.toml
fichiers en conséquence. Au départ, nous avons choisi la 3.8
Version Python pour tox
. Mais nous voulons qu’il soit compatible avec 3.7
et 3.9
. Pour le pyproject.toml
fichier, choisissez une version censée être compatible avec votre package. Ici, nous choisissons de rendre notre package compatible à partir de 3.7.1
et ci-dessus. Voici les modifications ajoutées à nos fichiers :
[tox]
envlist = py37,py38,py39
isolated_build = true
skip_missing_interpreters = true
[...]
[...]
[tool.poetry.dependencies]
python = "^3.7.1"
[...]
Lorsque vous modifiez le
pyproject.toml
dossier, toujours exécuter lepoetry update
commande qui peut vérifier certaines incompatibilités inattendues entre vos dépendances et la version de Python que vous souhaitez utiliser.
Pour finir, nous allons installer un package, appelé tox-gh-actionscourir tox
en parallèle sur GitHub en utilisant plusieurs versions de Python :
poetry add tox-gh-actions --dev
La canalisation est prête. Ajoutez, validez et transférez vos modifications pour voir le pipeline en cours d’exécution :
echo "!.github/" >> .gitignore
git add .gitignore
git commit -m "build: update .gitignore to unmask .github/ folder"
git add pyproject.toml tox.ini poetry.lock `.github/workflows/ci.yml`
git commit -m "build: tox pipeline + github actions CI pipeline"
Accédez à votre référentiel GitHub et cliquez sur le Actions languette:
Vous voyez tous les pipelines précédents et en cours :
Cliquons sur le pipeline en cours. Le pipeline s’exécute sur chaque système d’exploitation et pour chaque version de Python. Attendez quelques minutes pour voir les résultats :
Tous les pipelines réussissent ! Nous sommes prêts à publier notre package sur le registre PyPi.
Publiez des packages sur PyPi avec poetry
Pour rendre votre package publiable, ajoutez quelques détails dans le [tool.poetry]
rubrique de votre pyproject.toml
dossier:
[tool.poetry]
name = "summarize_dataframe"
version = "0.1.0"
description = "A package to provide summary data about pandas DataFrame"
license = "MIT"
authors = ["fbraza <[email protected]>"]
keywords = ["pandas", "dataframe"]
readme = "README.md"
homepage = "https://github.com/fbraza/summarize_dataframe"
repository = "https://github.com/fbraza/summarize_dataframe"
include = ["CHANGELOG.md"]
[...]
Toutes les variables ici sont assez explicites. Ce sont des métadonnées nécessaires à la publication du package. La include
La variable est intéressante pour ajouter tous les fichiers que vous voulez. Dans notre cas, nous allons ajouter un CHANGELOG.md
dossier. Te souviens tu commitizen
? Sinon, prenez le temps de lire notre article sur Commitizen et commits conventionnels. Utilisez la commande suivante :
Il imprime la version sémantique de votre pyproject.toml
file et vous demande de créer une balise Git. La version sera mise à jour en fonction de votre commit Git. Ensuite, nous créons le CHANGELOG.md
:
cz changelog
cat CHANGELOG.md
- correct pylint warnings
- split the function into two: one returning df other for output
- implementation of the summary function to summarize dataframe
Ton CHANGELOG.md
a été créé sur la base de l’historique Git que vous avez généré grâce à commitizen
. Plutôt chouette n’est-ce pas ? ! Une fois cela fait, concentrons-nous sur la publication de notre package :
poetry build
Building summarize_dataframe (0.1.0)
- Building sdist
- Built summarize_dataframe-0.1.0.tar.gz
- Building wheel
- Built summarize_dataframe-0.1.0-py3-none-any.whl
Cela crée un dossier appelé dist
où se trouve le paquet construit. Pour tester si tout fonctionne, vous pouvez utiliser pip
:
Faites cela en dehors de votre environnement virtuel pour ne pas le polluer.
pip install path/to/your/package/summarize_dataframe-0.1.0-py3-none-any.whl
Maintenant, nous devons créer un compte sur PyPi. Entrez simplement les détails attendus, validez votre e-mail et exécutez :
poetry publish
Username: ***********
Password: ***********
Publishing summarize_dataframe (0.1.0) to PyPI
- Uploading summarize_dataframe-0.1.0-py3-none-any.whl 100%
- Uploading summarize_dataframe-0.1.0.tar.gz 100%
Le package est maintenant en ligne et partagé avec la communauté.
Conclusion
tox
fournit une interface agréable pour automatiser tous vos tests unitaires et contrôles de validation. L’écosystème autour poetry
gagne en maturité et apporte des solutions pour travailler avec tox
sans trop de soucis. Ensemble, ces deux solutions permettent d’établir un pipeline CI très efficace et cohérent. Pour exécuter le pipeline et tester vos packages sur différents systèmes d’exploitation ou versions de Python, vous pouvez tirer parti des actions GitHub comme décrit ci-dessus.
poetry
était au centre de notre approche. De l’initialisation du projet à sa publication en passant par la gestion de ses packages et dépendances. poetry
a démontré sa facilité d’utilisation et son efficacité qui faciliteront à coup sûr la vie des développeurs, Data Scientists ou Data Engineers qui développent des projets en Python.
Nos articles décrivent une configuration complète que vous pouvez exploiter pour créer votre propre projet Python afin de respecter les bonnes pratiques d’ingénierie logicielle.
Aide-mémoire
tox
-
Exécutez votre pipeline de toxines
poetry
-
Composez votre forfait
-
Publiez votre colis
More Stories
Test des écouteurs Jabra Elite 5 ANC : superbe design, bon son
La filiale londonienne du CWU dit aux ingénieurs de BT de rejeter l’offre de rémunération
Revue du générateur solaire Jackery Explorer 1500 : la protection contre les pannes de courant à son meilleur