Skill de création de paquets Python PyPI
Un guide complet et éprouvé pour construire, tester, linter, versioner, typer et publier une bibliothèque Python de qualité production sur PyPI — du premier commit à la version prête pour la communauté.
Instruction pour agent IA : Lisez ce fichier entièrement avant d'écrire une seule ligne de code ou de créer un fichier quelconque. Chaque décision — mise en page, backend, stratégie de versioning, patterns, CI — possède une règle de décision ici. Suivez les arbres de décision dans l'ordre. Ce skill s'applique à tout type de paquet Python (utilitaire, SDK, CLI, plugin, bibliothèque de données). Ne sautez pas de sections.
Navigation rapide
| Section de ce fichier | Ce qu'elle couvre |
|---|---|
| 1. Déclencheur du skill | Quand charger ce skill |
| 2. Décision sur le type de paquet | Identifier ce que vous construisez |
| 3. Décision sur la structure de dossiers | src/ vs plat vs monorepo |
| 4. Décision sur le backend de build | setuptools / hatchling / flit / poetry |
| 5. Flux d'empaquetage PyPA | Le pipeline de publication canonique |
| 6. Templates de structure de projet | Mises en page complètes pour chaque option |
| 7. Stratégie de versioning | PEP 440, semver, dynamique vs statique |
| Fichier de référence | Ce qu'il couvre |
|---|---|
references/pyproject-toml.md |
Tous les quatre templates de backend, setuptools_scm, py.typed, configs d'outils |
references/library-patterns.md |
OOP/SOLID, type hints, conception de classe principale, factory, protocols, CLI |
references/testing-quality.md |
conftest.py, tests unitaires/backend/async, ruff/mypy/pre-commit |
references/ci-publishing.md |
ci.yml, publish.yml, Trusted Publishing, TestPyPI, CHANGELOG, checklist de release |
references/community-docs.md |
README, docstrings, CONTRIBUTING, SECURITY, anti-patterns, master checklist |
references/architecture-patterns.md |
Système backend (plugin/strategy), couche de config, couche de transport, CLI, injection de backend |
references/versioning-strategy.md |
PEP 440, SemVer, pre-release, setuptools_scm deep-dive, flit statique, moteur de décision |
references/release-governance.md |
Stratégie de branche, protection de branche, OIDC, validation d'auteur de tag, prévention de tags invalides |
references/tooling-ruff.md |
Setup Ruff uniquement (remplace black/isort), config mypy, pre-commit, asyncio_mode=auto |
Script de scaffold : exécutez python skills/python-pypi-package-builder/scripts/scaffold.py --name your-package-name
pour générer l'intégralité de la mise en page de répertoires, des fichiers stub, et pyproject.toml en une seule commande.
1. Déclencheur du skill
Chargez ce skill chaque fois que l'utilisateur souhaite :
- Créer, faire du scaffold, ou publier un paquet ou une bibliothèque Python sur PyPI
- Construire un SDK installable via pip, un utilitaire, un outil CLI, ou une extension de framework
- Configurer
pyproject.toml, linting, mypy, pre-commit, ou GitHub Actions pour un projet Python - Comprendre le versioning (
setuptools_scm, PEP 440, semver, versioning statique) - Comprendre les specs PyPA :
py.typed,MANIFEST.in,RECORD, classifiers - Publier sur PyPI en utilisant Trusted Publishing (OIDC) ou des tokens API
- Refactoriser un paquet existant pour suivre les standards modernes d'empaquetage Python
- Ajouter des type hints, protocols, ABCs, ou dataclasses à une bibliothèque Python
- Appliquer des patterns de design OOP/SOLID à un paquet Python
- Choisir entre les backends de build (setuptools, hatchling, flit, poetry)
Déclenchez aussi pour les phrases comme : "créer un SDK Python", "publier ma bibliothèque", "configurer PyPI CI", "créer un paquet pip", "comment publier sur PyPI", "aide pyproject.toml", "PEP 561 typed", "version setuptools_scm", "semver Python", "PEP 440", "git tag release", "Trusted Publishing".
2. Décision sur le type de paquet
Identifiez ce que l'utilisateur construit avant d'écrire du code. Chaque type possède des patterns distincts.
Tableau de décision
| Type | Pattern fondamental | Point d'entrée | Dépendances clés | Paquets exemples |
|---|---|---|---|---|
| Bibliothèque utilitaire | Module de fonctions pures + helpers | API d'import uniquement | Minimal | arrow, humanize, boltons, more-itertools |
| Client API / SDK | Classe avec méthodes, authentification, logique de retry | API d'import uniquement | httpx ou requests |
boto3, stripe-python, openai |
| Outil CLI | Fonctions de commande + analyseur d'arguments | [project.scripts] ou [project.entry-points] |
click ou typer |
black, ruff, httpie, rich |
| Plugin framework | Classe de plugin, enregistrement de hook | [project.entry-points."framework.plugin"] |
Dépendance de framework | pytest-*, django-*, flask-* |
| Bibliothèque de traitement de données | Classes + pipeline fonctionnel | API d'import uniquement | Optionnel : numpy, pandas |
pydantic, marshmallow, cerberus |
| Mixte / générique | Combinaison des options ci-dessus | Varie | Varie | Beaucoup de paquets réels |
Règle de décision : Posez la question à l'utilisateur si ce n'est pas clair. Un paquet peut combiner des types (par ex., SDK avec un point d'entrée CLI) — utilisez le type principal pour les décisions structurelles et ajoutez les patterns de type secondaire par-dessus.
Pour les patterns d'implémentation de chaque type, voir references/library-patterns.md.
Règles de nommage de paquet
- Nom PyPI : tout en minuscules, tirets —
my-python-library - Nom d'import Python : underscores —
my_python_library - Vérifier la disponibilité : https://pypi.org/search/ avant de commencer
- Évitez de masquer les paquets populaires (vérifiez que
pip install <name>échoue d'abord)
3. Décision sur la structure de dossiers
Arbre de décision
Le paquet a-t-il 5+ modules internes OU plusieurs contributeurs OU des sous-paquets complexes?
├── OUI → Utilisez la mise en page src/
│ Raison : empêche l'import accidentel de code non installé pendant le développement;
│ sépare la source des fichiers racine du projet ; recommandé par PyPA pour les grands projets.
│
├── NON → Est-ce un paquet à module unique et ciblé (par ex., un fichier + helpers)?
│ ├── OUI → Utilisez la mise en page plat
│ └── NON (complexité moyenne) → Utilisez la mise en page plat, migrez vers src/ s'il grandit
│
└── Est-ce plusieurs paquets associés sous un namespace (par ex., myorg.http, myorg.db)?
└── OUI → Utilisez la mise en page namespace/monorepo
Résumé de règle rapide
| Situation | Utilisez |
|---|---|
| Nouveau projet, taille future inconnue | Mise en page src/ (défaut le plus sûr) |
| Paquet à usage unique, 1–4 modules | Mise en page plat |
| Grande bibliothèque, nombreux contributeurs | Mise en page src/ |
| Plusieurs paquets dans un repo | Namespace / monorepo |
| Migration d'ancien projet plat | Gardez plat ; migrez vers src/ à la prochaine version majeure |
4. Décision sur le backend de build
Arbre de décision
L'utilisateur a-t-il besoin d'une version dérivée automatiquement des tags git?
├── OUI → Utilisez setuptools + setuptools_scm
│ (git tag v1.0.0 → c'EST votre workflow de release)
│
└── NON → L'utilisateur veut-il un outil tout-en-un (dépendances + build + publish)?
├── OUI → Utilisez poetry (v2+ supporte la table [project] standard)
│
└── NON → Le paquet est-il du Python pur sans extensions C?
├── OUI, config minimale préférée → Utilisez flit
│ (config zéro, détecte auto la version depuis __version__)
│
└── OUI, moderne & rapide préféré → Utilisez hatchling
(config zéro, système de plugins, pas de setup.py requis)
Le paquet a-t-il des extensions C/Cython/Fortran?
└── OUI → DOIT utiliser setuptools (seul backend avec support complet des extensions natives)
Comparaison des backends
| Backend | Source de version | Config | Extensions C | Meilleur pour |
|---|---|---|---|---|
setuptools + setuptools_scm |
Tags git (automatique) | pyproject.toml + shim setup.py optionnel |
Oui | Projets avec releases par tag git ; toute complexité |
hatchling |
Manuel ou plugin | pyproject.toml uniquement |
Non | Nouveaux projets pure-Python ; rapide, moderne |
flit |
__version__ dans __init__.py |
pyproject.toml uniquement |
Non | Paquets très simples, mono-module |
poetry |
Champ pyproject.toml |
pyproject.toml uniquement |
Non | Équipes voulant une gestion de dépendances intégrée |
Pour tous les quatre templates pyproject.toml complets, voir references/pyproject-toml.md.
5. Flux d'empaquetage PyPA
C'est le flux canonique de bout en bout de code source à installation utilisateur. Chaque étape doit être comprise avant de publier.
1. ARBRE SOURCE
Votre code en contrôle de version (git)
└── pyproject.toml décrit les métadonnées + système de build
2. BUILD
python -m build
└── Produit deux artefacts dans dist/:
├── *.tar.gz → source distribution (sdist)
└── *.whl → built distribution (wheel) — préféré par pip
3. VALIDER
twine check dist/*
└── Vérifie les métadonnées, rendu README, compatibilité PyPI
4. TESTER PUBLIER (première release seulement)
twine upload --repository testpypi dist/*
└── Vérifier: pip install --index-url https://test.pypi.org/simple/ your-package
5. PUBLIER
twine upload dist/* ← fallback manuel
OU GitHub Actions publish.yml ← recommandé (Trusted Publishing / OIDC)
6. INSTALLATION UTILISATEUR
pip install your-package
pip install "your-package[extra]"
Concepts clés PyPA
| Concept | Ce que cela signifie |
|---|---|
| sdist | Source distribution — votre source + métadonnées ; utilisé quand aucun wheel n'est disponible |
| wheel (.whl) | Binary pré-construit — pip l'extrait directement dans site-packages ; pas d'étape de build |
| PEP 517/518 | Interface standard du système de build via la table [build-system] de pyproject.toml |
| PEP 621 | Table [project] standard dans pyproject.toml ; tous les backends modernes la supportent |
| PEP 639 | Clé license comme chaîne SPDX (par ex., "MIT", "Apache-2.0") — pas {text = "MIT"} |
| PEP 561 | Fichier marqueur py.typed vide — indique à mypy/IDEs que ce paquet livre des informations de type |
Pour le workflow CI complet et la configuration de publishing, voir references/ci-publishing.md.
6. Templates de structure de projet
A. Mise en page src/ (Défaut recommandé pour les nouveaux projets)
your-package/
├── src/
│ └── your_package/
│ ├── __init__.py # API publique : __all__, __version__
│ ├── py.typed # Marqueur PEP 561 — FICHIER VIDE
│ ├── core.py # Implémentation principale
│ ├── client.py # (Type client API) ou supprimer
│ ├── cli.py # (Type CLI) commandes click/typer, ou supprimer
│ ├── config.py # Settings / dataclass configuration
│ ├── exceptions.py # Hiérarchie des exceptions custom
│ ├── models.py # Data classes, modèles Pydantic, TypedDicts
│ ├── utils.py # Helpers internes (préfixe _utils si privé)
│ ├── types.py # Alias de type partagés et TypeVars
│ └── backends/ # (Pattern plugin) — supprimer si non nécessaire
│ ├── __init__.py # Définition d'interface Protocol / ABC
│ ├── memory.py # Implémentation par défaut sans dépendance
│ └── redis.py # Implémentation optionnelle lourde
├── tests/
│ ├── __init__.py
│ ├── conftest.py # Fixtures partagées
│ ├── unit/
│ │ ├── __init__.py
│ │ ├── test_core.py
│ │ ├── test_config.py
│ │ └── test_models.py
│ ├── integration/
│ │ ├── __init__.py
│ │ └── test_backends.py
│ └── e2e/ # Optionnel : tests de bout en bout
│ └── __init__.py
├── docs/ # Optionnel : mkdocs ou sphinx
├── scripts/
│ └── scaffold.py
├── .github/
│ ├── workflows/
│ │ ├── ci.yml
│ │ └── publish.yml
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ └── feature_request.md
├── .pre-commit-config.yaml
├── pyproject.toml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── SECURITY.md
├── LICENSE
├── README.md
└── .gitignore
B. Mise en page plat (Paquets petits / ciblés)
your-package/
├── your_package/ # ← à la racine, pas dans src/
│ ├── __init__.py
│ ├── py.typed
│ └── ... (même structure interne)
├── tests/
└── ... (mêmes fichiers de haut niveau)
C. Mise en page namespace / monorepo (Plusieurs paquets associés)
your-org/
├── packages/
│ ├── your-org-core/
│ │ ├── src/your_org/core/
│ │ └── pyproject.toml
│ ├── your-org-http/
│ │ ├── src/your_org/http/
│ │ └── pyproject.toml
│ └── your-org-cli/
│ ├── src/your_org/cli/
│ └── pyproject.toml
├── .github/workflows/
└── README.md
Chaque sous-paquet a son propre pyproject.toml. Ils partagent le namespace your_org via les paquets namespace implicites PEP 420 (pas __init__.py à la racine du namespace).
Directives de module interne
| Fichier | Objectif | Quand l'inclure |
|---|---|---|
__init__.py |
Surface API publique ; ré-exports ; __version__ |
Toujours |
py.typed |
Marqueur paquet typé PEP 561 (vide) | Toujours |
core.py |
Classe principale / logique principale | Toujours |
config.py |
Dataclass Settings ou modèle Pydantic | Quand configurable |
exceptions.py |
Hiérarchie d'exceptions (YourBaseError → spécifiques) |
Toujours |
models.py |
Modèles de données / DTOs / TypedDicts | Quand data-heavy |
utils.py |
Helpers internes (pas part de l'API publique) | Au besoin |
types.py |
Définitions TypeVar, TypeAlias, Protocol partagées |
Quand typage complexe |
cli.py |
Points d'entrée CLI (click/typer) | Type CLI uniquement |
backends/ |
Pattern plugin/strategy | Quand implémentations échangeables |
_compat.py |
Shims compatibilité version Python | Quand compat 3.9–3.13 nécessaire |
7. Stratégie de versioning
PEP 440 — Le standard
Forme canonique: N[.N]+[{a|b|rc}N][.postN][.devN]
Exemples:
1.0.0 Release stable
1.0.0a1 Alpha (pre-release)
1.0.0b2 Beta
1.0.0rc1 Release candidate
1.0.0.post1 Post-release (par ex., correction d'empaquetage uniquement)
1.0.0.dev1 Snapshot de développement (pas pour PyPI)
Semantic Versioning (recommandé)
MAJOR.MINOR.PATCH
MAJOR: Breaking API change (supprimer/renommer fonction/classe/argument public)
MINOR: Nouvelle fonctionnalité, entièrement rétro-compatible
PATCH: Correction de bug, pas de changement d'API
Versioning dynamique avec setuptools_scm (recommandé pour workflows avec tags git)
# Comment ça fonctionne:
git tag v1.0.0 → version installée = 1.0.0
git tag v1.1.0 → version installée = 1.1.0
(commits après tag) → version = 1.1.0.post1 (suffixe supprimé pour PyPI)
# Dans le code — NE JAMAIS coder en dur quand vous utilisez setuptools_scm:
from importlib.metadata import version, PackageNotFoundError
try:
__version__ = version("your-package")
except PackageNotFoundError:
__version__ = "0.0.0-dev" # Fallback pour checkouts dev non installés
Config pyproject.toml requise:
[tool.setuptools_scm]
version_scheme = "post-release"
local_scheme = "no-local-version" # Prévient +g<hash> de casser les uploads PyPI
Critique : définissez toujours fetch-depth: 0 à chaque étape de checkout CI. Sans l'historique git complet,
setuptools_scm ne peut pas trouver les tags et la version de build tombe silencieusement à 0.0.0+dev.
Versioning statique (flit, hatchling manuel, poetry)
# your_package/__init__.py
__version__ = "1.0.0" # Mettre à jour avant chaque release
Bonnes pratiques de spécificateur de version pour les dépendances
# Dans les dépendances [project]:
"httpx>=0.24" # Version minimum — PRÉFÉRÉ pour les bibliothèques
"httpx>=0.24,<1.0" # Limite supérieure seulement quand un breaking change connu existe
"httpx==0.27.0" # Épingler exactement UNIQUEMENT dans les applications, PAS les bibliothèques
# JAMAIS faire ceci dans une bibliothèque — ça casse la résolution de dépendances pour les utilisateurs:
# "httpx~=0.24.0" # Trop strict
# "httpx==0.27.*" # Fragile
Version bump → flux de release
# 1. Mettre à jour CHANGELOG.md — déplacer les entrées [Unreleased] vers [x.y.z] - YYYY-MM-DD
# 2. Commiter le changelog
git add CHANGELOG.md
git commit -m "chore: prepare release vX.Y.Z"
# 3. Tagger et push — ceci déclenche publish.yml automatiquement
git tag vX.Y.Z
git push origin main --tags
# 4. Surveiller GitHub Actions → vérifier sur https://pypi.org/project/your-package/
Pour les templates pyproject.toml complets pour tous les quatre backends, voir references/pyproject-toml.md.
Où aller ensuite
Après avoir compris les décisions et la structure :
-
Configurer
pyproject.toml→references/pyproject-toml.mdTous les quatre templates de backend (setuptools+scm, hatchling, flit, poetry), configs d'outils complètes, setuppy.typed, config de versioning. -
Écrire votre code de bibliothèque →
references/library-patterns.mdPrincipes OOP/SOLID, type hints (PEP 484/526/544/561), conception de classe principale, fonctions factory,__init__.py, pattern plugin/backend, point d'entrée CLI. -
Ajouter tests et qualité de code →
references/testing-quality.mdconftest.py, tests unitaires/backend/async, parametrize, setup ruff/mypy/pre-commit. -
Configurer CI/CD et publish →
references/ci-publishing.mdci.yml,publish.ymlavec Trusted Publishing (OIDC, pas de tokens API), format CHANGELOG, checklist de release. -
Polir pour la communauté/OSS →
references/community-docs.mdSections README, format docstring, CONTRIBUTING, SECURITY, templates d'issues, tableau anti-patterns, et master checklist de release. -
Concevoir backends, config, transport, CLI →
references/architecture-patterns.mdSystème backend (pattern plugin/strategy), Settings dataclass, couche de transport HTTP, CLI avec click/typer, règles d'injection de backend. -
Choisir et implémenter une stratégie de versioning →
references/versioning-strategy.mdFormes canoniques PEP 440, règles SemVer, identifiants pre-release, setuptools_scm deep-dive, versioning statique flit, moteur de décision (DEFAULT/BEGINNER/MINIMAL). -
Gouverner les releases et sécuriser le pipeline de publish →
references/release-governance.mdStratégie de branche, règles de protection de branche, setup OIDC Trusted Publishing, validation d'auteur de tag dans CI, mise en place du format de tag,publish.ymlcomplet gouverné. -
Simplifier les outils avec Ruff →
references/tooling-ruff.mdSetup Ruff uniquement remplaçant black/isort/flake8, config mypy, hooks pre-commit, asyncio_mode=auto (supprimer @pytest.mark.asyncio), guide de migration.