Jak zbudować dystrybucję źródłową bez użycia pliku setup.py?

10

Z następującą strukturą pakietu

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

Zawartość setup.py

from setuptools import setup
setup()

Zawartość setup.cfg

[metadata]
name = my_package
version = 0.1

[options]
packages = find:

Mogę zbudować koło lub dystrybucję źródła dla my_packagetego typu

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

Jednak według opiekuna setuptools konfiguracja kompilacji deklaratywnej jest idealna, a użycie kompilacji rozkazowej będzie zapachem kodu. Więc zastąpić setup.pyz pyproject.toml:

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

Zawartość pyproject.toml

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

I nadal możesz zbudować koło w taki sam sposób, jak wcześniej, działa. Ale sdist nie działa:

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

Jak więc właściwie zbudować plik .tar.gz za pomocą setuptools ? Jakie narzędzie do tworzenia sdist jest przeznaczone dla użytkownika? Nie chcę zmieniać backendu kompilacji. Wygląda na to, że wszystkie inne narzędzia do pakowania zapisują własne punkty wejścia kompilacji, ale pomyślałem, że cały sens definiowania deklaratywnego systemu kompilacji w metadanych polegał na tym, że nie trzeba było wchodzić w interakcję z systemem budowania, ucząc się, jak każdy inne narzędzie do pakowania oczekuje na wywołanie lub konieczność wejścia do interpretera i ręcznego wywołania API Pythona. Ale PEP dla wymagań systemowych kompilacji ma już ponad 2 lata. Czy brakuje mi czegoś oczywistego?

Jak zbudować dystrybucję źródłową bez użycia setup.pypliku?

dziobak
źródło

Odpowiedzi:

10

Jest to nieco kontrowersyjny temat, a na razie odpowiedź jest taka, że ​​nie ma jednego narzędzia, które wszyscy zgodziliby się, że jest „właściwą drogą” do budowania dystrybucji źródeł, ani czym byłoby to narzędzie. Długi wątek na ten temat można zobaczyć w dyskursie Python Packaging .

Waham się dać zbyt wiele porad opakowaniowe w trwałych formatów ponieważ piaski są zawsze przesunięcie, ale od listopada 2019, setup.py sdistjest nie przestarzałe, ale nie mają wszystkie wady, które PEP 517 i PEP 518 były przeznaczone do poprawki - a mianowicie, że trzeba aby samodzielnie stworzyć środowisko kompilacji (i wiedzieć o wszystkich zależnościach kompilacji) i działa tylko z setuptools / distutils i ich odpowiednikami.

Nie jest to „oficjalna” rekomendacja, ale obecnie najlepszy zamiennik setup.py sdisti setup.py bdist_wheelwywołuje wersję wiersza poleceń pep517. Zamiennikiem sdistjest:

python -m pep517.build --source .

Możesz zbudować koło i dystrybucję źródła w następujący sposób:

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

W ten sposób buduję pakiety zgodne z PEP 517.

Wymaga to, aby twój projekt miał pyproject.toml, i pyproject.tomlmusi mieć build-system.requiresi build-system.build-backendklucze, ale będzie działał dla każdego projektu z backendem kompatybilnym z PEP 517 (w tym flit).

Inne narzędzia :

Dlaczego nie użyć flitlub poetrylub hatch? Wszystkie te narzędzia są dostępne dla tych, którzy chcą z nich korzystać, ale nie są odpowiedzią na to pytanie . To pytanie dotyczy projektów budowanych przy setuptoolsużyciu setup.cfgformatu deklaratywnego . Ani flitnie poetrydziałają jako ogólne interfejsy kompilacji PEP 517, dlatego działają tylko jako komendy kompilacji dla projektów korzystających z ich wewnętrznych backendów.

Nie jestem na tyle obeznany z hatchpowiedzieć, czy nie może zarządzać projektami z backendów innych (znowu, a od listopada 2019) niż setuptools, ale to nie Pep 517 frontend, a to nie będzie działać, jeśli nie masz a setup.py(spowoduje błąd „nie można otworzyć pliku setup.py” i zignoruje twój pyproject.tomlplik).

Paweł
źródło
Po co skupiać się na pep517.buildczymś, co ma być tylko eksperymentem, chwilową kulą, gdy istnieją produktywne narzędzia, takie jak flit, poezja, kreskowanie i prawdopodobnie jeszcze więcej?
sinoroc,
1
Ponieważ moim zdaniem był to udany eksperyment (używam go i wielu innych osób PyPA), ponieważ ma on odpowiednią semantykę do tego zadania, i ponieważ jest to jedyny znany mi front-end kompilacji PEP 517. flit i poezja są zintegrowane pionowo, ponieważ oczekują, że użyjesz ich zaplecza. właz wydaje się robić wiele innych rzeczy. pep517.buildjest prostym narzędziem zbudowanym właśnie do tego celu.
Paul,
Ach racja, dobra uwaga. Skupiłem się na back-endach kompilacji. I tak naprawdę myślałem, że pep517.buildto jeden z nich. Ale wcale nie jest to front-end kompilacji. Również klapa nie jest PEP517 gotowy jak widzę teraz.
sinoroc,
1
Zaktualizowałem swoją odpowiedź, aby odpowiedzieć na twoje pytanie.
Paul,
Tak, idealnie. Usuwam swoją odpowiedź.
sinoroc,
-1

Nie ma nic „oczywistego”, jeśli chodzi o opakowanie Pythona. Rzeczywiście, na razie, przynajmniej jeśli używasz distutils / setuptools, konieczne jest utworzenie (prawie) pustego setup.pypliku, nawet jeśli używasz w pełni deklaratywnego setup.cfg:

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

Polecam również chmod +x setup.py.

W tym przypadku sam piszesz „punkt wejścia” do systemu kompilacji i setup()jest on po prostu jego main()funkcją - ale teraz zamiast tego setup()można odczytać wszystkie argumenty, które zostały tradycyjnie przekazane setup.cfg.

Teraz możesz nadal używać, setup.py sdistjeśli chcesz zrobić archiwum źródłowe:

./setup.py sdist

Możesz także wypróbować jeden z alternatywnych systemów kompilacji, które są włączane przez pyproject.toml, na przykład Flit .

Iguananaut
źródło
Nie jestem pewien, dlaczego jest to lekceważone; jest to w zasadzie poprawne, nawet jeśli istnieją inne rozwiązania.
Iguananaut
2
Tytuł pytania brzmi „Jak zbudować dystrybucję źródłową bez użycia pliku setup.py?” Wydaje się, że ta odpowiedź pokazuje „oto, jak odtworzyć ten sam plik setup.py, który właśnie usunąłeś”, co nie jest przydatne.
dziobak
Tak, ale było to oparte na nieporozumieniu, że napisanie deklaratywnego setup.cfgoznacza, że setup.pykorzystanie z setuptools nie jest już konieczne, co nie jest prawdą. To, że tytuł pytania wprowadza w błąd, nie oznacza, że ​​odpowiedź brzmi. Napisali w treści pytania „Więc jak właściwie zbudować plik .tar.gz za pomocą setuptools ?” na co odpowiada to poprawnie.
Iguananaut
1
To prawda. setuptools nie wymaga pliku setup.py, jeśli używasz PEP 517.
Paul
„jeśli używasz PEP 517” Tyle że większość ludzi nie. Jest to wciąż tymczasowe i prawie nie wspomniano o nim w pliku.p.phonon.org . Nie jest to coś, co byś miał, gdybyś nie wiedział, żeby tego poszukać. Jeśli chcesz, aby setuptools działał tak, jak zawsze to robił, jest to poprawne.
Iguananaut