Comment construire une distribution source sans utiliser le fichier setup.py?

10

Avec la structure de package suivante

.
├── my_package
   └── __init__.py
├── setup.cfg
└── setup.py

Contenu de setup.py

from setuptools import setup
setup()

Contenu de setup.cfg

[metadata]
name = my_package
version = 0.1

[options]
packages = find:

Je peux construire une roue ou une distribution source my_packagecomme celle-ci

pip wheel --no-deps -w dist .
# generates file ./dist/my_package-0.1-py3-none-any.whl
python setup.py sdist
# generates file ./dist/my_package-0.1.tar.gz

Mais selon le responsable de setuptools , une configuration de construction déclarative est idéale et l'utilisation d'une construction impérative va être une odeur de code. Nous remplaçons donc setup.pypar pyproject.toml:

.
├── my_package
   └── __init__.py
├── setup.cfg
└── pyproject.toml

Contenu de pyproject.toml

[build-system]
build-backend = "setuptools.build_meta"
requires = ["setuptools", "wheel"]

Et vous pouvez toujours construire une roue de la même manière qu'auparavant, cela fonctionne. Mais sdist ne fonctionne pas:

python: can't open file 'setup.py': [Errno 2] No such file or directory

Alors, comment devez-vous réellement créer le fichier .tar.gz à l' aide de setuptools ? Quel est l'outil accessible à l'utilisateur pour créer sdist? Je ne veux pas changer le backend de build. Il semble que d'autres outils de conditionnement écrivent tous leurs propres points d'entrée de génération, mais je pensais que l'intérêt de définir un système de génération déclaratif dans les métadonnées était de sorte que vous n'ayez pas à vous familiariser avec le système de génération, en apprenant comment chacun un outil de packaging différent s'attend à être appelé ou à devoir aller dans l'interpréteur et appeler une API Python manuellement. Mais le PEP pour les exigences du système de construction a maintenant plus de 2 ans. Suis-je en train de manquer quelque chose d'évident ici?

Comment construire une distribution source sans utiliser de setup.pyfichier?

ornithorynque
la source

Réponses:

10

C'est un sujet quelque peu controversé, et la réponse pour le moment est qu'il n'y a pas un seul outil dont tout le monde convienne est la "bonne façon" de construire des distributions sources, ni ce que serait cet outil. Vous pouvez voir un long fil à ce sujet sur le discours de Python Packaging .

Je hésite à donner trop de conseils d'emballage dans des formats durables parce que les sables se déplacent toujours, mais à partir de Novembre 2019, setup.py sdistest pas déconseillés, mais il n'avoir tous les inconvénients que la PPE 517 et PEP 518 ont été destinés à fixer - à savoir que vous avez pour créer vous-même l'environnement de build (et connaître toutes les dépendances de build), et cela ne fonctionne qu'avec setuptools / distutils et leurs équivalents.

Ce n'est pas une recommandation "officielle", mais le meilleur remplacement actuel pour setup.py sdistet setup.py bdist_wheelinvoque la version en ligne de commande de pep517. Le remplacement sdistest:

python -m pep517.build --source .

Vous pouvez construire la roue et la distribution source en même temps comme ceci:

python -m pep517.build --source --binary .

C'est ainsi que je crée mes packages compatibles PEP 517.

Cela nécessite que votre projet ait un pyproject.tomlet les clés pyproject.tomlmust have build-system.requireset build-system.build-backend, mais cela fonctionnera pour tout projet avec un backend compatible PEP 517 (y compris flit).

Autres outils :

Pourquoi ne pas utiliser flitou poetryou hatch? Ces outils sont tous disponibles pour ceux qui veulent les utiliser, mais ils ne sont pas une réponse à cette question . Cette question concerne les projets construits avec setuptoolsqui utilisent le setup.cfgformat déclaratif . Ni , flitni poetryagir comme PEP génériques 517 construction frontaux, et ils ne le travail que les commandes de construction pour des projets en utilisant leurs backends respectifs.

Je ne suis pas assez familier pour hatchdire s'il peut gérer des projets avec des backends autres que setuptools, mais (encore une fois, en novembre 2019), ce n'est pas un frontend PEP 517, et cela ne fonctionnera pas si vous n'avez pas a setup.py(cela soulèvera l'erreur "impossible d'ouvrir le fichier setup.py" et ignorera votre pyproject.tomlfichier).

Paul
la source
Pourquoi se concentrer sur pep517.buildce qui ne se veut qu'une expérience, une béquille temporaire lorsqu'il existe des outils productifs tels que le flit, la poésie, la trappe, et probablement encore plus?
sinoroc
1
Parce que c'était une expérience réussie à mon avis (moi et beaucoup d'autres gens de PyPA l'utilisons), car il a la bonne sémantique pour le travail, et parce que c'est le seul front-end de construction PEP 517 à usage général que je connaisse. flit et poésie sont intégrés verticalement en ce sens qu'ils attendent de vous que vous utilisiez leur backend. L'écoutille semble faire beaucoup d'autres choses. pep517.buildest un outil simple conçu à cet effet.
Paul
Ah oui, bon point. Je me concentrais sur les back-ends de construction. Et je pensais vraiment que pep517.buildc'était l'un d'entre eux. Mais pas du tout, c'est en fait un front-end de build. L' écoutille n'est pas non plus prête pour le PEP517 comme je le vois maintenant.
sinoroc
1
J'ai mis à jour ma réponse pour répondre à votre question.
Paul
Oui parfait. Je supprime ma réponse.
sinoroc
-1

Il n'y a rien "d'évident" en ce qui concerne le packaging Python. En effet, pour le moment, au moins si vous utilisez distutils / setuptools, il est nécessaire de créer un setup.pyfichier (presque) vide , même si vous utilisez un fichier entièrement déclaratif setup.cfg:

#!/usr/bin/env python
from setuptools import setup
setup()

Je recommande aussi chmod +x setup.py.

Dans ce cas, vous écrivez vous-même le «point d'entrée» dans le système de génération, et vous n'en êtes setup()que la main()fonction - mais maintenant tous les arguments qui étaient traditionnellement passés setup()peuvent être lus à la setup.cfgplace.

Maintenant, vous pouvez toujours utiliser setup.py sdistsi vous voulez faire un tarball source:

./setup.py sdist

Vous pouvez également essayer l'un des systèmes de construction alternatifs qui sont activés via pyproject.toml, comme Flit .

Iguananaut
la source
Je ne sais pas pourquoi cela fait l'objet d'un vote négatif; c'est fondamentalement correct même s'il existe d'autres solutions.
Iguananaut
2
Le titre de la question est "Comment créer une distribution source sans utiliser le fichier setup.py?" Cette réponse semble simplement démontrer "voici comment recréer le même fichier setup.py que vous venez de supprimer", ce qui n'est pas utile.
ornithorynque
Oui, mais cela était basé sur un malentendu selon lequel écrire un déclaratif setup.cfgsignifie qu'il setup.pyn'est plus nécessaire d'utiliser setuptools, ce qui n'est pas vrai. Ce n'est pas parce que le titre de la question est trompeur que la réponse l'est. Ils ont écrit dans le corps de la question "Alors, comment devriez-vous réellement construire le fichier .tar.gz en utilisant setuptools ?" auquel cela répond correctement.
Iguananaut
1
C'est vrai. setuptools ne nécessite pas de fichier setup.py si vous utilisez PEP 517.
Paul
"si vous utilisez le PEP 517" Sauf que la plupart des gens ne le font pas. C'est encore provisoire, et est à peine mentionné dans packaging.python.org . Ce n'est pas quelque chose que vous auriez sauf si vous savez aller le chercher. Si vous voulez juste que setuptools fonctionne comme d'habitude, c'est correct.
Iguananaut