pypa / pip

The Python package installer
https://pip.pypa.io/
MIT License
9.52k stars 3.03k forks source link

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

Open dstufft opened 3 years ago

dstufft commented 3 years ago

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 https://github.com/pypa/pip/issues/6334, since it narrows the cases where we're using the legacy path to just editable installs.

pfmoore commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

xavfernandez commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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

jaraco commented 3 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

Heh, nvm me. I tripped on the double negative

pradyunsg commented 2 years ago

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.

flying-sheep commented 2 years ago

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 commented 2 years ago

This is a minor related motivation for what I think this issue is ultimately trying to solve, but currently the last blocker for Flake8 developers to support configuration in pyproject.toml is:

pip to change its behaviour so mere presence of [pyproject.toml] does not change functionality

The reasoning is if they want to eventually drop support for the other configuration files they support (setup.cfg, tox.ini, .flake8), this pip issue could cause unintended side effects for a legacy project (that isn't already using the modern build isolation) that simply wants to use Flake8 during development.

Removing this blocker would be very welcome for those wanting to consolidate all tool configuration into pyproject.toml.

pfmoore commented 2 years ago

The flake8 issue isn't really relevant here. Whatever reasons the flake8 maintainers have for not reading config from pyproject.toml[^1] don't affect the reasons we have for how we interpret PEP 518 in pip[^2].

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

[^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 commented 2 years ago

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.

flying-sheep commented 1 year ago

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 commented 8 months ago

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: https://github.com/astral-sh/uv/issues/2252.

covracer commented 3 months ago

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

sbidoul commented 3 months ago

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 commented 1 month ago

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:

Plus in the wider ecosystem:

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