TL;DR: is it time to just use pyproject.toml, and which build backend should be recommended?
With many build backends now implementing PEP 621 (including PyPA’s setuptools, hatch, and flit), there’s a desire to simplify and modernize the packaging tutorial to just use pyproject.toml. However, there’s been a lot of discussion about the scope of that, and there are currently two PR’s that take different approaches:
#1031 shows how to use different build backends, and currently recommends hatchling, flit, PDM, and setuptools (in that order) (preview)
There’s been a lot of lively philosophical discussion in #1031 and the PyPA Discord. However, as a relative new maintainer of PyPUG, given that setuptools has been the recommendation for so long, I don’t feel comfortable changing that based solely on those discussions. I’d like to get feedback from long-time packaging folks, so I came to this forum (another option being the pypa-committers list).
Keeping in mind that the primary audience for the tutorial is folks who have no packaging experience, here are the philosophical issues that I see:
Is it helpful or confusing to document multiple backends?
Backends like hatchling, flit, and PDM are part of CLI’s that manage more of the packaging lifecycle, and their documentation rightly focuses on those CLI’s. Could this be confusing for folks who’ve only completed the tutorial, which uses standalone tools like build, twine, and venv? By contrast, setuptools is just a build backend, and its documentation has seen a lot of improvement.
Newer backends provide a better build experience, with faster builds and friendlier output than setuptools. How important is this?
I have no strong opinions on the particular backend, but as someone who maintains a lot of Python packages, I care about the Python packaging process in general. My observation it that “packaging” is currently very much in the flux, with a lot of competing projects trying to improve the situation.
My rationale, which is somewhat documented here, is that you currently only need setup.py (and depending on the project, a requirements.txt), pip and twine. However in the current packaging tutorial it is recommended that you use setup.py, setup.cfg and pyproject.toml, which is a lot of clutter, considering that you can achieve the same with just setup.py or apparently nowadays with only pyproject.toml. So my main goal is to simplify the recommendation to the minimum number of files required to get the job done.
It’s probably a bit early to recommend a pyproject.toml-only
configuration with Setuptools, at least. At the moment, it raises
warning “Support for project metadata in pyproject.toml is still
experimental and may be removed (or change) in future releases.”
Further, for editable/develop installs with Setuptools you do need a
setup.py for the time being.
Yes, I was talking specifically about Setuptools, not Flit. If the
suggestion is to switch the tutorial to recommend Flit with just a
pyproject.toml then that may work even for editable/develop
installs. If the idea is to stick with Setuptools in the tutorial,
then its not quite there yet (and not just because of editables, but
also because it clearly declares its pyproject.toml metadata API as
experimental right now).
That would be true of the main page of any tool that offers a CLI. You’d have to link to the relevant page(s).
If a build backend has a CLI component, or a GUI, or some other feature, why would we be linking to those parts of the docs? I don’t understand the concern at all.
I think this view comes from not having an opportunity to read the docs in question, basically what you said after this comment. Poetry’s docs, which puts the most emphasis on its CLI, is almost all about configuration outside of the landing page.
Also, there’s been talk of setuptools gaining its own CLI
I think this more broadly speaks to a cost/benefit analysis. In particular, what is age worth?
I don’t have an answer to that, but I think we should maintain the spirit of PEP 517 and make it clear that it’s valid to use any tools that implement the specs.
Doing so allows users to choose what’s best for them. For example, Project Jupyter & IPython are almost done switching their entire packaging ecosystem. I tried to link to most of the changes here: Users - Hatch
If we’re looking at build backends that support PEP 621, and we are happy to assume the developer is writing a pure Python package, then there should be very little practical difference between backends (that’s the point of standards, after all!). The main difference for a tutorial is how you specify what files go into the distribution (which isn’t standardised). If we wanted to cover the UI and workflow of a backend tool, that would be different, but I don’t think anyone is proposing that, are they?
I think we should be able to write most of the tutorial in a backend-agnostic way. And where we have to be backend specific (the build-system key, and how to specify what files to include) we can do the same sort of tabbed approach we have for OS differences. There’s clearly still going to be a “main thread” to the tutorial which will need to focus on a specific backend, but it should be possible to do so in a way that doesn’t exclude the other alternatives.
For the record, I’d support either flit or hatch as a default - both have a nice clean interface. Setuptools has a lot of historical baggage, and while we can show people how to do things the modern way, they will undoubtedly end up searching the web at some point and come across a lot of information that’s based on the “old way” of doing things, which is bound to be confusing. Poetry is excellent, but it feels like there’s more expectation that you do things “the poetry way” which isn’t as ideal for a generic tutorial.
Which seems valid, given that we’re targetting newcomers. ↩︎
While I’d personally like to see a comparison of the differences and benefits of the various backends, I suspect the packaging tutorial isn’t the right place for such a thing. ↩︎
Given that PEP 518 is explicit that the build-system table is not required:
Tools should not require the existence of the [build-system] table… If the file exists but is lacking the [build-system] table then the default values as specified above should be used.
And that the default is to use setuptools + wheel, which should be enough for the large majority of users, I think we should omit this entirely from the guide, which is very beginner focused.
Instead, we could probably write an entire separate guide on choosing an alternate build backend for cases when the defaults don’t work, which would likely be welcomed by people trying to understand build backends, but entirely unnecessary for the average user of this guide.
I agree. Omitting the [build-system] table is only really for legacy purposes. PEP 517 makes it clear that if the table is missing, frontends should invoke setuptools using the setuptools.build_meta:__legacy__ backend, which is solely for backward compatibility (and I believe is subtly different to the real setuptools backend).
We definitely don’t want to encourage new users to do this.
I ran a quick test and noticed that hatch and flit both support currently editable installs via pip install -e . – for the sake of keeping the tutorial simple and not so much tool specific, i think it would be sufficient to stick to one of the ones that is currently working and just mention the others. If a tool, e.g. hatch supports other tool-specific annotations in the pyproject.toml we shouldn’t bother mentioning them, and rather stick to the common subset that should be understood by all tools.
I don’t see much value in providing an example for every possible tool that supports a build-backend, it is probably more confusing than helpful for people needing this tutorial.
A related aside: it is very confusing from a user’s point of view that the very organization responsible for Python Packaging (i.e. the Authority), comes up with several tools seemingly covering the same aspects, e.g. flit, hatch and maybe even build and pipenv. I think a consolidation on the tooling and the documentation is really needed here.
-1. We’ve worked hard to open up the ecosystem to allow users to have a choice of backends. Promoting and encouraging that choice is part of that work.
Of course, another part is to make sure we help users be comfortable with having that choice. So while I disagree that we should focus on a single backend, I do agree that we should be careful with our docs and messaging to ensure that choice isn’t overwhelming to newcomers (or experienced developers for that matter!)
I’m not suggesting linking to hatch’s CLI docs. However, trying to put myself in a newcomer’s shoes, I can imagine wanting to learn more about configuring metadata. For hatchling, it seems like the right place to go is Metadata - Hatch. Whether I get there via the tutorial or my own searching, it seems like I’m very quickly going to be reading docs referencing the hatch CLI (e.g. versioning), which I might find confusing, because that tool wasn’t what I used in the tutorial.