273 lines
5.7 KiB
Markdown
273 lines
5.7 KiB
Markdown
|
# Faire ses paquets
|
|||
|
En respectant les standards.
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Se présenter, hackinscience, formations, ...
|
|||
|
|
|||
|
|
|||
|
## Donc on va parler de distutils ?
|
|||
|
|
|||
|
PEP 632 (septembre 2020) : Deprecate distutils module.
|
|||
|
|
|||
|
La doc dit de ne plus l'utiliser depuis ~2014…
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
setuptools à commencé en étant du monkey-patch de distutils,
|
|||
|
maintenant setuptools intègre sa copie de distutils.
|
|||
|
|
|||
|
|
|||
|
## Donc on va parler de {buzzword} ?
|
|||
|
|
|||
|
- pipenv : 304k lignes de code.
|
|||
|
- bento : 37k lignes de code.
|
|||
|
- poetry : 16k lignes de code.
|
|||
|
- flit : 4k lignes de code.
|
|||
|
- build : <1k lignes de code.
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Ils utilisent tous setuptools ^^
|
|||
|
|
|||
|
|
|||
|
## Non mais pourquoi pas {buzzword} ?
|
|||
|
|
|||
|
- Ça demande du temps pour migrer d'un standard à un outil tiers.
|
|||
|
- Ça demande à une partie de l'équipe d'apprendre ce nouvel outil.
|
|||
|
- Puis ça demande du temps pour migrer à nouveau vers le standard quand l'outil est abandonné.
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
On a mieux a faire de notre temps.
|
|||
|
|
|||
|
|
|||
|
## Mais les Pipfile ?
|
|||
|
|
|||
|
En fait oui et non, Pipfile c'est une spec à part :
|
|||
|
|
|||
|
=> https://github.com/pypa/pipfile
|
|||
|
|
|||
|
Rien n'empêche d'un jour pouvoir faire un :
|
|||
|
```
|
|||
|
pip install --pipfile Pipfile.lock
|
|||
|
```
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Cherchez dans les issues de pypa/pip, la discussion est ouverte.
|
|||
|
|
|||
|
Et puis pipenv c'est abandonné ?
|
|||
|
|
|||
|
|
|||
|
# OK, bon, comment on fait sans buzzwords ?
|
|||
|
|
|||
|
## pyproject.toml
|
|||
|
|
|||
|
Les PEP 517 et 518 normalisent la construction de paquets en déclarant son outil de build dans `pyproject.toml` :
|
|||
|
|
|||
|
```toml
|
|||
|
[build-system]
|
|||
|
requires = ["setuptools", "wheel"]
|
|||
|
build-backend = "setuptools.build_meta"
|
|||
|
```
|
|||
|
|
|||
|
Le backend étant `setuptools.build_meta`, on aura besoin d'un `setup.cfg`.
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
C'est typiquement utilisé par pip lors d'un `pip install .`.
|
|||
|
|
|||
|
## setup.py
|
|||
|
|
|||
|
En 2020 il ne prenait plus qu'une ou deux lignes, bienvenu en 2021.
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
`setuptools` autorise depuis la v40.0.9 de ne pas avoir de `setup.py`,
|
|||
|
à condition d'avoir un `pyproject.toml`.
|
|||
|
|
|||
|
(La PEP517 ne gère pas encore les installations éditables, si vous les utilisez,
|
|||
|
vous aurez donc tout de même besoin d'un `setup.py`.)
|
|||
|
|
|||
|
https://setuptools.readthedocs.io/en/latest/setuptools.html#setup-cfg-only-projects
|
|||
|
|
|||
|
Bon c'est quand même pratique les installations éditables, et `pip-compile setup.py`.
|
|||
|
|
|||
|
|
|||
|
## setup.cfg
|
|||
|
|
|||
|
```
|
|||
|
[metadata]
|
|||
|
name = oeis
|
|||
|
version = attr: oeis.__version__
|
|||
|
description = Implementation of a few integer sequences.
|
|||
|
long_description = file: README.md
|
|||
|
long_description_content_type = text/markdown; charset=UTF-8
|
|||
|
...
|
|||
|
```
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Voir mon setup.cfg sur le projet githup.com/JulienPalard/oeis.
|
|||
|
|
|||
|
|
|||
|
## Vous venez de 2020 ?
|
|||
|
|
|||
|
Ne faites pas la conversion à la main !
|
|||
|
|
|||
|
```text
|
|||
|
pip install setup-py-upgrade
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
## Comment je build ?
|
|||
|
|
|||
|
On peut utiliser `build` de la PyPA, un outil qui ne fait qu'une chose mais qui le fait bien :
|
|||
|
|
|||
|
```
|
|||
|
pip install build
|
|||
|
python -m build --sdist --wheel .
|
|||
|
```
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Les dépendances de build sont installées dans un environnement isolé (*isolated build*).
|
|||
|
Oui oui il crée vraiment un venv, avec le module venv de Python.
|
|||
|
|
|||
|
Pas besoin de `pip install setuptools wheel`
|
|||
|
|
|||
|
|
|||
|
## Et comment j'upload ?
|
|||
|
|
|||
|
On peut utiliser `twine` de la PyPA, un outil qui ne fait qu'une chose mais qui le fait bien :
|
|||
|
|
|||
|
```text
|
|||
|
pip install twine
|
|||
|
twine upload -r test dist/*
|
|||
|
pip install --index-url https://test.pypi.org/simple/ oeis
|
|||
|
twine upload dist/*
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
# Et les dépendances !?
|
|||
|
|
|||
|
Les dépendances « runtime » (`install_requires`) sont décrites dans le `setup.cfg`.
|
|||
|
|
|||
|
|
|||
|
## Épinglées ou pas ?
|
|||
|
|
|||
|
Ça dépend de ce que vous faites, mais généralement on vise le plus large possible.
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Vous voulez que votre lib, ou votre programme puisse s'installer sans conflit avec une autre lib ou un autre programme.
|
|||
|
|
|||
|
Et on ne va pas maintenir, à la main, dans le setup.cfg, des versions précisément.
|
|||
|
|
|||
|
|
|||
|
## Épingler saybien !
|
|||
|
|
|||
|
Je n'ai pas dit que c'était mal, c'est très bien pour les développeurs, pour la CI, pour la prod…
|
|||
|
|
|||
|
|
|||
|
## Épingler saybien !
|
|||
|
|
|||
|
J'utilise un outil qui ne fait qu'une chose mais qui le fait bien :
|
|||
|
|
|||
|
`pip-compile` du paquet `pip-tools`, ça ne fait *que* geler les dépendances, et ça le fait bien.
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Oui on sent que je n'aime pas les projets qui essayent de tout résoudre d'un coup.
|
|||
|
|
|||
|
|
|||
|
## Épingler saybien !
|
|||
|
|
|||
|
On peut donc "geler" les dépendances du projet via un :
|
|||
|
|
|||
|
```
|
|||
|
pip-compile setup.py
|
|||
|
```
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
https://github.com/jazzband/pip-tools/issues/1047
|
|||
|
|
|||
|
|
|||
|
## Épingler saybien !
|
|||
|
|
|||
|
On peut ensuite documenter ses dépendances de dev dans un `requirements-dev.in` :
|
|||
|
|
|||
|
```txt
|
|||
|
-r requirements.txt
|
|||
|
tox
|
|||
|
```
|
|||
|
|
|||
|
## Épingler saybien !
|
|||
|
|
|||
|
Et épingler aussi les requirements de dev, afin de les utiliser dans des tests reproductibles :
|
|||
|
|
|||
|
```txt
|
|||
|
pip-compile requirements-dev.in
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
## Épingler saybien !
|
|||
|
|
|||
|
On peut même hasher les dépendances pour les plus paranos :
|
|||
|
|
|||
|
```txt
|
|||
|
pip-compile --generate-hashes setup.py
|
|||
|
```
|
|||
|
|
|||
|
## Qu'est-ce que ça donne ?
|
|||
|
|
|||
|
```
|
|||
|
pyproject.toml // 3 lignes
|
|||
|
setup.cfg
|
|||
|
requirements.txt // autogénéré par pip-compile
|
|||
|
requirements-dev.in
|
|||
|
requirements-dev.txt // autogénéré par pip-compile
|
|||
|
```
|
|||
|
|
|||
|
## Mettre à jour
|
|||
|
|
|||
|
```txt
|
|||
|
pip-compile --upgrade requirements-dev.in
|
|||
|
```
|
|||
|
|
|||
|
# Installer
|
|||
|
|
|||
|
Il existe un outil qui ne fait qu'une chose, mais qui le fait bien : `pip`.
|
|||
|
|
|||
|
```
|
|||
|
pip install oeis
|
|||
|
```
|
|||
|
|
|||
|
|
|||
|
## Installer
|
|||
|
|
|||
|
Vous connaissez alors je passe sur le plus gros, mais n'oubliez pas :
|
|||
|
|
|||
|
```txt
|
|||
|
pip install git+https://github.com/org/project@branch
|
|||
|
```
|
|||
|
|
|||
|
::: notes
|
|||
|
|
|||
|
Typiquement pour tester la PR de quelqu'un (et oui ça déclenche la construction d'une wheel via les dépendances
|
|||
|
et le point d'entrée décrit dans pyproject.toml).
|
|||
|
|
|||
|
|
|||
|
# RTFM
|
|||
|
|
|||
|
- https://setuptools.readthedocs.io/en/latest/build_meta.html
|
|||
|
- https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html
|
|||
|
- https://packaging.python.org/guides/using-testpypi/
|
|||
|
- https://setuptools.readthedocs.io/en/latest/setuptools.html#setup-cfg-only-projects
|
|||
|
|
|||
|
|
|||
|
# Questions
|
|||
|
|
|||
|
?
|