Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to isolated, pyproject.toml-based builds #9175

Open
dstufft opened this issue Nov 29, 2020 · 27 comments
Open

Default to isolated, pyproject.toml-based builds #9175

dstufft opened this issue Nov 29, 2020 · 27 comments
Labels
C: build logic Stuff related to metadata generation / wheel generation type: enhancement Improvements to functionality UX User experience related

Comments

@dstufft
Copy link
Member

dstufft commented Nov 29, 2020

Update on Oct 7 2022: Once setup.py install and setup.py develop code paths are killed, there is no reason for pip to use the legacy setup.py-based builds by default, other than to avoid the additional overhead of the creation of build environments.


Currently if you try to pip install something that only is provided a "legacy" setuptools only sdist without a pyproject.toml, that will be installed using the "legacy" path unless you explicitly invoke --use-pep517.

This is particularly troublesome in cases where you don't have (or want to have) setuptools installed in the environment, since the legacy path depends on having setuptools preinstalled.

This flag does not affect editable installs in any way, and those still require having setuptools preinstalled in either case.

This seems like it would be a good stepping stone on the way to #6334, since it narrows the cases where we're using the legacy path to just editable installs.

@pfmoore
Copy link
Member

pfmoore commented Nov 29, 2020

This sounds like a good idea to me. I think PEP 517 has been around long enough to make this a reasonable change.

One thought I had was whether we needed a deprecation period here. But we're not actually deprecating anything, just changing the default, so I don't think we necessarily need one. It is an incompatible change, so some might argue otherwise, though.

@dstufft
Copy link
Member Author

dstufft commented Nov 29, 2020

I'm not actually sure what a deprecation period would look like for something like this. We don't have a good way to message this I think, if we just message on any thing that might break with the new default we're going to produce a lot of false positives/noise. The only thing I could think of is implement an intermediate state where we switch to something like --use-pep517 by default, but if that fails for whatever reason we fall back to the legacy behavior.

I don't personally feel like that's a high value win, since I think a lot of the subtle issues have gotten worked out now, and I think that --no-use-pep517 is not a particularly onerous burden.

I do think it would be worthwhile to wait until next year for this change, I think 20.3 is close enough now that sneaking it in would be counterproductive AND I think the new resolver is a big enough change on it's own that this change would only muddy the waters.

@pradyunsg
Copy link
Member

pradyunsg commented Nov 29, 2020

Given that we currently have a fairly non-trivial performance penalty to using PEP 517, I'm very much a -1 to making this switch without trying to address them. Thinking a bit more, there's also the issue of poor end-user control over isolated environments (our isolation also has bugs, but I'm too tired to locate them right now). Unless we address these two concerns, I expect this to cause more churn than our original PEP 517 rollout.

I'd consider things like #7294, #9081 to be essential pre-requisites for this -- overall, I feel like there's a lot of need for improvements to PEP 517's quality-of-implementation based on all the things we've learned and the changes in pip, since the original implementation.

It'd be a good thing if we can make it so that this doesn't make pip's own test suite slower. :)

@pradyunsg
Copy link
Member

That said, I'm very very on board to actually figuring out what all do we consider as critical path to doing this.

@xavfernandez
Copy link
Member

FWIW I agree with Pradyun that our PEP 517 implementation should first be improved (#7294 & #9081 are great examples) before making it the default.

@pfmoore
Copy link
Member

pfmoore commented Nov 30, 2020

This is probably true (it hadn't occurred to me because I tend to think of build isolation as a separate thing, because it was introduced with PEP 518 support, not with PEP 517). Is anyone planning to work on those two issues? They are both marked as "needs discussion", and I'd be very keen on not having the path to making PEP 517 the default blocked by proposals we can't decide on.

@pradyunsg
Copy link
Member

I think the discussion needed on those two, at least, is how the implementation looks and not whether we wanna do them.

@jaraco
Copy link
Member

jaraco commented Mar 23, 2021

As maintainer of Setuptools, I've been trying to wean myself off of environments where setuptools is installed. I've been using get-pip.py --no-setuptools and virtualenv --no-setuptools and aggressively uninstalling setuptools from whatever environments I can. Doing so causes problems: packages fail to install (no module named setuptools) and when they fail to install, backtracking causes lots of failed attempts. Passing --use-pep517 works around the issue, but that's clumsy. In my opinion, if PEP-517 installs are recommended and the default for projects to opt into, then they should be suitable for projects in general. I'd very much like to see this change enacted as soon as bearable.

@hroncok
Copy link
Contributor

hroncok commented Nov 8, 2021

I've mentioned this issue in https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810 -- my idea is that pip might want to default to --use-pep517 at least when setuptools is not installed.

@jaraco
Copy link
Member

jaraco commented Nov 11, 2021

I found one case where --use-pep517 breaks the build. My advice would be to migrate the project to a more conventional structure, but I wanted to share here for context.

@uranusjr
Copy link
Member

default to --use-pep517 at least when setuptools is not installed

This makes sense to me. And it could be a sensible way to move things forward as well since our current problem is blanket-defaulting to --use-pep517 is much too disruptive, but without this being a default there’s little incentive for offending packages to fix their build chain. We could, say, convince CPython to not provision populate setuptools in ensurepip, or ask virtualenv to only install pip by default. But I’m getting too much ahead of myself.

@pradyunsg
Copy link
Member

pradyunsg commented Nov 11, 2021

We "control" both those modes -- the reason that setuptools and virtualenv ship setuptools, is because pip depends on them. Once we default to PEP 517 workflows, we'll need to go around and remove setuptools from the default shipped packages as well.

@uranusjr
Copy link
Member

Yes, but the “problem” is that we are currently unable to come up with a scenario that not shipping setuptools is a good practical idea; even though we have a “long term goal” to remove it, it’s unclear how we can move closer to the goal. Those who are (still currently) publishing non-PEP-517 projects have little incentive to move to PEP 517 because every environment comes with setuptools and only packaging nerds contrieve weird scenarios where setuptools is unavailable, and we can’t make removing setuptools a less weird scenario because way too many packages are non-installable by default in this situation. It’s a circular dependency.

By making --use-pep517 the default behaviour, most of those non-PEP-517 packages will no longer be non-installable without setuptools. With that, we can more confidently advertise that creating an environment without seeding setuptools is not actually a weird choice because it works for most of the things. And thus the cycle can be broken.

@pfmoore
Copy link
Member

pfmoore commented Nov 15, 2021

That was always my intention when I first added --use-pep517. It was an --enable-feature flag before we'd invented that mechanism, and TBH, if that feature had been around at the time, I'd have used it and we wouldn't be hesitating as much as we are over enabling the feature by default...

@pradyunsg
Copy link
Member

pradyunsg commented Nov 15, 2021

most of those non-PEP-517 packages will no longer be non-installable without setuptools.

Could you elaborate on how/why this would be the case?

The only packages that wouldn't work are packages that are somehow incompatible with build-isolation. And they can use --no-build-isolation.

Everything else gets setuptools and wheel installed in the build environment, by default.

@pfmoore
Copy link
Member

pfmoore commented Nov 15, 2021

Note that "no longer be non-installable" = "will be installable". By using PEP 517, and consequently build isolation, projects that rely on setuptools will get setuptools and wheel installed in the build environment, and so will work.

Without PEP 517. projects that rely on setuptools will go down the legacy path and fail if setuptools isn't in the user's main environment. So if we stop shipping setuptools by default, those projects will fail to build. Making --use-pep517 the default will retain the current situation (that the projects will build).

@pradyunsg
Copy link
Member

Heh, nvm me. I tripped on the double negative

@pradyunsg
Copy link
Member

We're already set up to build with pyproject.toml based builds, when setuptools is not in the environment.

Once we kill setup.py install and setup.py develop, we should be good to flip the switch on build isolation and pyproject.toml-based builds as well.

@pradyunsg pradyunsg changed the title Default to --use-pep517 Default to isolated, pyproject.toml-based builds Aug 11, 2022
@flying-sheep
Copy link

Once we kill setup.py install and setup.py develop

Is there a place where the progress on this is tracked? Or is that place here?

@johnthagen

This comment was marked as off-topic.

@pfmoore
Copy link
Member

pfmoore commented Aug 18, 2022

The flake8 issue isn't really relevant here. Whatever reasons the flake8 maintainers have for not reading config from pyproject.toml1 don't affect the reasons we have for how we interpret PEP 518 in pip2.

But can we please avoid the flake8 controversy spilling over into pip's tracker? Thanks.

Footnotes

  1. Which, you need to remember, can be as simple as "because we don't want to" - this is open source and there's no requirement on maintainers to do anything they don't want to.

  2. On a personal note, I'm pretty strongly against tools putting their config in pyproject.toml - for my own projects, all I want to see in that file is standardised data and build backend configuration. So I'd be significantly inconvenienced on a personal basis if flake8 switched to only allow pyproject.toml for configuration.

@sbidoul
Copy link
Member

sbidoul commented Aug 18, 2022

Once we kill setup.py install and setup.py develop

Is there a place where the progress on this is tracked? Or is that place here?

That would be #8102. All issues and PRs towards that goal reference it.

@pradyunsg pradyunsg added type: enhancement Improvements to functionality UX User experience related labels Sep 16, 2022
@pradyunsg pradyunsg added the C: build logic Stuff related to metadata generation / wheel generation label Sep 16, 2022
@flying-sheep
Copy link

OK, since I keep stumbling upon this issue:

Once we kill setup.py install and setup.py develop, we should be good to flip the switch on build isolation and pyproject.toml-based builds as well.

the individual steps are at the time of writing:

charliermarsh added a commit to astral-sh/uv that referenced this issue Jan 10, 2024
## Summary

Our current setup uses the legacy `setup.py`-based builds if a
`pyproject.toml` file isn't present. This matches pip's behavior.
However, `pypa/build` uses PEP 517-based builds in such cases, and it
looks like pip plans to make that the default
(pypa/pip#9175), with the limiting factor
being performance issues related to isolated builds.

This is now the default behavior, but the `--legacy-setup-py` flag
allows users to opt-in to using `setup.py` directly for distributions
that lack a `pyproject.toml`.
@charliermarsh
Copy link
Contributor

If helpful: we use PEP 517 builds by default in uv. I've been tracking projects that fail to install with uv under PEP 517 build isolation, and similarly fail with pip under --use-pep517: astral-sh/uv#2252.

@covracer
Copy link

Is it possible to turn off build isolation for one line (or several specific lines) in requirements.txt?

@sbidoul
Copy link
Member

sbidoul commented Jul 11, 2024

Is it possible to turn off build isolation for one line (or several specific lines) in requirements.txt?

That is not possible at the moment. The documentation lists the 3 options that are allowed per requirement line.

@edmorley
Copy link
Contributor

edmorley commented Sep 8, 2024

Once we kill setup.py install and setup.py develop, we should be good to flip the switch on build isolation and pyproject.toml-based builds as well.

I'm curious, why does enabling build isolation by default depend on removing support for pip's fallback to setup.py develop?

When using build isolation with a setup.py-using package (that hasn't migrated to a build system declared in pyproject.toml), pip will already use the fallback setuptools build backend which uses a modern setuptools that already supports PEP-660. Therefore in that case:

  1. pip won't need to call setup.py develop, since the fallback setuptools build backend will pull in latest setuptools, which supports PEP-660 for editable mode
  2. even if pip did still call setup.py develop, I presume this would still work with the setuptools installed inside the isolated build environment, since latest setuptools still supports the develop command?

ie: Whilst deprecating setup.py develop (#11457) is a worthwhile venture in its own right, I'm not sure it blocks making isolated build environments the default?

Lastly, since pip already defaults to isolated build environments if either setuptools or wheel are not installed, this means isolated build environments are already used by pip in many more places than one might expect, given that:

  • The Python stdlib modules venv and ensurepip have never installed wheel (only setuptools) - regardless of Python version.
  • The third-party virtualenv package doesn't install setuptools or wheel for Python 3.12+.
  • get-pip.py no longer installs setuptools or wheel for Python 3.12+.
  • the official Python docker images (python:*) no longer install setuptools or wheel for Python 3.12+.
  • the GitHub Actions Python distributions (used by eg setup-python) rely on ensurepip to provide pip/other tools, so they also no longer install setuptools or wheel for Python 3.12+.
  • Homebrew Python only installs wheel (not setuptools) for Python 3.12+.
  • (and no doubt more...)

Plus in the wider ecosystem:

  • many of the packages that weren't originally compatible with build isolation have either made themselves compatible, or have updated their docs to explicitly say to use --no-build-isolation with pip install (since they already can't rely upon pip not using build isolation, since many of their users won't have setuptools or wheel installed given the above)
  • all of Poetry, Pipenv and uv already default to isolated builds

As such, it seems like we're now finally at the point where we can make this change? (With of course a mention of --no-build-isolation in the release notes to help those who can't use the new default.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: build logic Stuff related to metadata generation / wheel generation type: enhancement Improvements to functionality UX User experience related
Projects
None yet
Development

No branches or pull requests