Setuptools: Discussion: support for pyproject.toml configuration

Created on 17 Feb 2019  路  23Comments  路  Source: pypa/setuptools

Over the last few months, I've been using setup.cfg more, and I find the syntax and types and such to be super counter-intuitive. I don't find TOML to be a breeze per se, but it's at least a lot clearer to me how to specify a string, a list, etc. We also hear a lot of cries to move towards supporting pyproject.toml as the "one file" for setup configuration, in favor of setup.cfg. I'm not terribly opposed to this, but I want to open up the discussion for a few options:

  1. Add pyproject.toml as the one true way to do declarative builds, moving all setuptools configuration over there and deprecating setup.cfg (partially what is discussed in #1160, and if we decide on that option we can move over to that issue).
  2. Add pyproject.toml as a second supported way to do a declarative configuration, alongside setup.cfg.
  3. Stay the course with setup.cfg indefinitely.

I am deeply concerned with the large amount of churn that we're introducing into the Python packaging space, so I don't want to make a lot of changes for the sake of changes, but I do think that at least having the option to use a pyproject.toml would be a real benefit, so I'm basically in favor of option 2.

I think the biggest downside of option 2 is that it means maintaining, testing and documenting three separate locations for all of our options - how to do it in setup.cfg, how to do it in pyproject.toml, and how to do it in setup.py. I think the hard part is going from 1 way to do everything to 2 ways. Our documentation is a mess anyway, but my beautiful vision for the future is that all our examples have "tabs" that allow you to toggle them between setup.cfg and setup.py. Adding a pyproject.toml in there would probably not be the worst thing.

Needs Implementation enhancement help wanted major

Most helpful comment

FWIW, PEP 621 for _Storing project metadata in pyproject.toml_ has been provisionally accepted.

All 23 comments

I'd prefer option 1. I imagine during the deprecation period that the setup.cfg documentation could be removed, but a permalink to the old documentation made available for projects still relying on that technique.

One way to ease the transition could be for the setup.cfg code to _generate_ a .toml file and consume then have the pyproject.toml consumer just load both files. That way, a project seeking to transition would only need to do one build, manually merge the two .toml files, and delete setup.cfg.

My second choice would be option 3. I'd really like to avoid supporting multiple formats that do essentially the same thing.

Another consideration I'd like to mention is the proposal I only recently started fleshing out in pypa/packaging-problems#248. Such an approach would be _yet another_ declarative format. However, this proposed approach would enable project developers to supply metadata decoratively in the canonical format (or in a format suitable for the requisite build steps). If such an approach is deemed viable and comes to fruition, the value in migrating to pyproject.toml may prove small. I suggest postponing this transition at least until that more ambitious proposal is disposed or reaches fruition.

I imagine during the deprecation period that the setup.cfg documentation could be removed, but a permalink to the old documentation made available for projects still relying on that technique.

I'm pretty sure the deprecation period would be literally forever. I bet there are projects on PyPI that (a) are dead and will never see another release, (b) are still used, and (c) depend on setup.cfg to install.

I'm not opposed to adding features to setuptools and better ways to do things, but I think it's about 100x less important than not breaking stuff.

I'm in favour of 1, with deprecated forever status (ideally keep the heading聽in documentation and just remove all the content, replacing it with a paragraph saying use pyproject.toml)

There is an ETA for this? Or there is still some discussion pending?.I think that Option 1 is the best, but here is not stated for sure if this will be done.

@qlixed There is no ETA.

I think we probably have a rough consensus for Option 1 with an indefinite deprecation period (we don't have to specify the length of the deprecation period anyway). I won't have time to do this any time soon, but I think we can accept a contribution that does.

I think we'll need to:

  1. Vendor the toml library
  2. Build out a tool that converts setup.cfg to pyproject.toml
  3. Make it the default way that setup.cfg is processed.

I think we can say that if options are specified in both setup.cfg and pyproject.toml (under tool:setuptools), that we throw an error and refuse to build (use one or the other, not both). I don't think we should warn if people use setup.cfg even when pyproject.toml is available, we should wait for pyproject.toml configuration to be stable for at least a year before actively pushing it like that.

We'll also need to decide how to handle the little ad-hoc "types" we've implemented like file:, attr:, etc. Are we parsing these as strings (I really hate how much string parsing we do in setup.cfg as it is)? Using a dict? Is there some facility in the TOML language that would make this easy for us?

Is there some facility in the TOML language that would make this easy for us?

Yes, TOML supports both nested and inline tables. For example, the version could be hardcoded as a string:

version = "0.0.0"

... or it could be a table specifying one of attr or file:

version = { attr = "setuptools.version" }

The same 'trick' is used by Poetry to separate dependency markers from version specifiers.

In the fundable packaging improvements list I summarized this as follows (if it's inaccurate, I'd appreciate a correction, especially as a pull request):

Add support for pyproject.toml as a way to configure setuptools

setuptools does not yet allow project creators to use the new pyproject.toml standard configuration file to configure setuptools behavior. This distracts and confuses package creators, and prevents platforms and tools from depending on the presence of standard pyproject.toml metadata in packages. We'd like to implement pyproject.toml configuration support in setuptools. This requires backend development work, technical writing, and coordination and publicity work among Python users.

I'd also like to better work out what this entails and how long it would take. To dig into @pganssle's proposed sequence:

I think we'll need to:

1. Vendor the `toml` library

2. Build out a tool that converts `setup.cfg` to `pyproject.toml`

Would this live within setuptools or be part of some other codebase?

3. Make it the default way that `setup.cfg` is processed.

One subtask being: decide and implement how to deal with it if people use setup.cfg even when pyproject.toml is available.

Also: should this task include implementing a deprecation notices to output when the user's supplied a setup.cfg file, advising them to switch to pyproject.toml in the future?

So that's the backend development work. I'd add in:

  1. technical writing, and coordination and publicity work among Python users:
  • update all the bits of PyPUG that mention setup.cfg
  • announce on Discourse & distutils-sig and deal with any questions/concerns that come up from other packaging tools maintainers
  • write/update user help for https://setuptools.readthedocs.io/
  • get user testing for the change (for instance, look around GitHub for issues that stem from setuptools not having this feature, and point them at the branch to test it)
  • once it's landed in a released version, advertise a bit with some blog posts, Twitter threads, conference talks, and podcast appearances

What have I missed or gotten wrong? Is this mostly right?

Thanks @brainwane for pushing this forward. Your outline looks good to me. And nicely done making docs and the user experience first-class considerations.

Would this live within setuptools or be part of some other codebase?

My instinct is within, as it has little value outside the context of setuptools. I would expect it to be largely uncoupled with most of the functionality in setuptools except config-related handling.

One thing to note: There is an as-yet-unreleased PEP that is in its final stages that intends to standardize the form of all the build metadata in pyproject.toml. I believe that should be released for public comment soonish. (Hopefully I'm not spilling the beans too much by mentioning it here).

It's fine to start work on pyproject.toml support, but we should be aware that any ad-hoc configuration we come up with in the tool:setuptools table may become Yet Another Location for build metadata if the PEP is accepted. If someone is itching to get started on this and doesn't have access to the PEP, they can let me know and I'll see about arranging to get them a copy. Otherwise I'll link to it here when it is made public. Even before it's accepted I think coding assuming it will be accepted is reasonable; we can always rename the tables later, and actually trying to implement the thing will probably give the authors good feedback.

If someone is itching to get started on this and doesn't have access to the PEP

Are there any deep reasons to prepare it non-publicly?

Are there any deep reasons to prepare it non-publicly?

It was not my choice, but PEPs are usually prepared privately, by a single individual or a small group. This one has a decent number of authors on it (as you'll see), so it's a bit unusual in that respect, but I think it was probably a smart strategy to get an initial draft that is agreeable to a bunch of the stakeholders before bringing it forward for wider comment. It's super easy to get bogged down in random details when there are "too many cooks in the kitchen".

Honestly, it's not some secretive packaging cabal, just a project that people have been putting a lot of effort into that I happen to know about. I'm fairly certain the number of goats sacrificed was in the single digits.

Nice! I've been wondering for a long time why every tool inefficiently reimplements the exact same metadata verbatim in a non-introspectable manner. Good to hear this mistake is being rectified. :)

the number of goats sacrificed was in the single digits

WAIT. Who sacrificed goats!? :o

tool.setuptools table may become Yet Another Location for build metadata if the PEP is accepted

I mean, to an extent. The tool.setuptools will still be relevant since there's a lot of stuff that's just not performed/treated the same way (eg: C extensions, including/excluding specific files, package data etc), so there would still be setuptools specific options/flags, which it'd be nice to be able to declare in pyproject.toml.

I talked with a few maintainers and here is a rough estimate of how much time this would take, assuming that the Python developer(s), tech writer(s), coordinator(s), etc. involved already know some things about Python packaging but haven't previously worked on the setuptools codebase.

Here's a very rough idea (always assuming people are working about 35 hrs/week, and including testing and iterating in response to code review):

  1. Ramp-up time for everyone who doesn't already know the setuptools codebase: ~2 weeks
  2. Vendor the toml library: ~1 week (should be fairly straightforward except for review coordination)
  3. Build out a tool, to live within setuptools, that converts setup.cfg to pyproject.toml: ~4 weeks (including a few weeks of finding sample setup.cfg files, testing those, finding bugs, making design decisions about validity)
  4. Make it the default way that setup.cfg is processed (including: dealing with simultaneous setup.cfg & pyproject.toml presence, and implementing deprecation notices): ~4-6 weeks

Simultaneous with a bunch of that: technical writing, and coordination and publicity work among Python users:

  • update all the bits of PyPUG that mention setup.cfg: ~3 days, including review coordination
  • announce on Discourse & distutils-sig and deal with any questions/concerns that come up from other packaging tools maintainers: ~3 days
  • write/update user help for https://setuptools.readthedocs.io/ : ~1-2 weeks, including review coordination and finding other stuff that needs fixing
  • get user testing for the change (for instance, look around GitHub, StackOverflow, the Python subreddit, etc. for people with issues that stem from setuptools not having this feature, and recruit those users at the branch to test it), and respond to those user tests: ~1 week
  • once it's landed in a released version, advertise a bit with some blog posts, Twitter threads, conference talks, and podcast appearances: 2 days to 3 weeks

Some comments:

  1. Since we don't directly define console_scripts entry points anymore, I'd like to make a step further and also standardize an icon per a script. An icon is given as a relative path to a graphic file of PNG format (further other formats may be added). The action of it is following: metadata dir is given a subdir icons where icons are placed using last components of their paths as names (so they must be unique), and icons names are placed into entry points metadata (not yet standardized, I gonna probably write a pep, basically it is entry_point_name @ {"icon":"a.png"}). Different scripts can have the same icon, in this case only 1 file is kept. pip or other tools may use this info for creating shortcuts.
  2. instead of dynamic I propose the following scheme: the metadata may be set by build plugins, like setuptools_scm, so instead of mentioning the name in dynamic we just mention it within the key that it is set using the plugin somehow. When a plugin is installed, it contains in its entry point metadata the list of pyproject.toml metadata keys it can (and must, if mentioned) set, so everything can be verified statically without invoking the plugin.

What do icons have to do with console scripts which are only relevant on the console, which doesn't have the concept of graphics?

How does this relate to consolidating existing metadata into pyproject.toml?

What do icons have to do with console scripts which are only relevant on the console, which doesn't have the concept of graphics?

  1. CLI apps may have icons. In Windows.
  2. shortcuts / .desktop files to cli apps may have icons.

How does this relate to consolidating existing metadata into pyproject.toml?

In no way to consolidating, but this is also a good moment to introduce something new

This issue is focused on defining a new way of specifying existing information.
Please create a new thread on https://discuss.python.org/c/packaging/14 to propose changes to the metadata spec. Thanks!

FWIW, PEP 621 for _Storing project metadata in pyproject.toml_ has been provisionally accepted.

@brainwane how to apply to https://github.com/psf/fundable-packaging-improvements/blob/master/FUNDABLES.md#add-support-for-pyprojecttoml-as-a-way-to-configure-setuptools ? I can start on vendoring toml and code that reads values from it for setup.cfg override. Logging hours on UpWork, working through gitcoin.co contract are all fine with me.

Hi @abitrolly, that list is projects that need funding, not projects that we already have funding for. We'd need to find funding for this first.

Was this page helpful?
0 / 5 - 0 ratings