Removing setup.cfg and from the packaging tutorial

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)
  • #1085 just drops the setup.* files (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:

  1. Is it helpful or confusing to document multiple backends?
  2. 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.
  3. Newer backends provide a better build experience, with faster builds and friendlier output than setuptools. How important is this?

Hi, thanks for opening the discussion.

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 (and depending on the project, a requirements.txt), pip and twine. However in the current packaging tutorial it is recommended that you use, setup.cfg and pyproject.toml, which is a lot of clutter, considering that you can achieve the same with just 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.

1 Like

Good to see this happening. My setuptools-based projects currently have a blank setup.cfg because editable installs don’t work w/o that yet. I’m hopeful that this will be resolved soon though.

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 for the time being.

Or at least a blank setup.cfg as mentioned above.

I thought this was no longer required with recent versions of pip. For example, Twine doesn’t have a, but I can still pip install -e . in a local clone.

As noted, I should have said or setup.cfg, point being
it’s not yet working with just a pyproject.toml as far as I’ve
been able to tell.

Same here, I tried yesterday a dummy flit project that only contained a pyproject.toml and no setup.(py|cfg) and i was able to pip install -e . it without problems.

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).

I’ve managed to get rid of my and setup.cfg in favor of pyproject.toml (and tox.ini for testing environments). I’m happy and I’m not going back :smiley:



As long as there is a default UI selection, it is incredibly useful for discovery, especially for newcomers without the knowledge of where to look for alternatives. The current PR #1031 does this.

As I said in this comment:

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 :slightly_smiling_face:

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[1], 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[2].

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.

  1. Which seems valid, given that we’re targetting newcomers. ↩︎

  2. 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. ↩︎


I think that’s a good assumption to make, else the possibilities of what the user needs is endless.

Tangentially, I think this tutorial might be suggesting to us that’s the next thing to standardize in pyproject.toml (at least for sdists).

Ditto, and based on @takluyver having said they are not comfortable with that and @ofek is comfortable with it, I say make Hatch the default.

1 Like

Please don’t standardize the “how” i.e. config, only the “what”.

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.

1 Like

I think we’d be doing beginners a disservice by omitting that table when every pyproject.toml file they encounter will have one. I’ve never seen one without it.

edit: also that’s teaching a bad practice imo, build deps should be bounded/pinned


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 Like

-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!)

1 Like

Following up on my concern about a backend’s documentation:

and @ofek’s response:

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.