Remove wheel as minimum requirement from PEP 518

Under § build-system table, PEP 518 says that the minimum requirements must include setuptools and wheel. However, (a) wheel is not required for building an sdist and (b) has always been provided by setuptool’s own get_requires_for_build_wheel. Installing wheel when building an sdist is wasteful, and as adoption of build, the build tool, increases and users migrate away from python setup.py bdist_wheel, wheel will be reinstalled every time an sdist is built without exception. I would then suggest to remove “wheel” from the minimum requirements.

1 Like

Yes, I had looked into that too. IIRC get_requires_for_build_wheel was not returning wheel, but I can be wrong. Did you check older versions?

I don’t think we can do this for backward compatibility reasons, though I’d like it. Maybe I’m wrong though.

This example in PEP 518 can probably remove wheel since it implies latest setuptools (which would populate wheel automatically). I agree tools can’t do this due to backwards compatibility reasons (at least for maybe like another five years or so to wait for pre-installed non-isolated setuptools to catch up).

1 Like

setuptools 42, which I believe is the earliest version to officially support PEP 517, returns wheel:

❯ python -m pip show setuptools | rg Version
Version: 42.0.0

❯ python -c 'import build

  pb = build.ProjectBuilder(".")
  print(pb.get_dependencies("wheel"))
  '
[...]
{'wheel'}

That isn’t just an example, the following text states that those values should be used by tools if pyproject.toml or the build-system section is missing.

Why can’t we change the default from "setuptools", "wheel" to "setuptools >= X.Y.Z", where X.Y.Z is the version that added wheel to get_requires_for_build_wheel? That would be a correct change, whereas defaulting to a bare "setuptools" is flat-out wrong, to be blunt.

Such a change is still backward incompatible, in the case where a user has an old setuptools installed and is using a non-isolated build. But at least it’s reporting the problem correctly. And the user can work around it by adding a pyproject.toml specifying "setuptools", "wheel" if they don’t want to upgrade their setuptools.

As with any other incompatible change, we wouldn’t be able to make it until we’re comfortable that the number of people who would be affected by the breakage is sufficiently small (and honestly, I have no feel for when that’s a reasonable thing to think). But in the interim, changing the example (but not the spec!) to advise users to include a versioned constraint on setuptools and not include wheel, is definitely worth doing.

1 Like

I don’t see where the backwards incompatibility might arise. wheel was there from the start as far as I can tell, see pep517: add module · pypa/setuptools@b59076e · GitHub, the commit introducing build_meta (then called pep517).

I am not so sure.

try:
    _run_setup()
except SetupRequirementsError as e:
    requirements += e.specifiers

This will only return wheel if _run_setup fails, but AFAIK wheel is only required at wheel build time.

The original implementation had get_requires_for_build_x return both setuptools and wheel as a baseline when building both an sdist and a wheel. You will notice that e.specifiers are appended to ['setuptools', 'wheel']. build_meta.get_requires_for_build_sdist does not include wheel · pypa/setuptools@2fabfd3 · GitHub removed wheel from sdist and Backend should not say that setuptools is needed to build · pypa/setuptools@ed22402 · GitHub removed setuptools from both.

If we’re making an update to the spec (example or text), I’d request whoever makes the change to also move the specification to packaging.python.org and then update it. Similar to what we just did for wheels.

3 Likes

That seems bizarre. Why would it include setuptools? The setuptools backend is being run, so clearly the frontend already knows that setuptools is needed.

An unqualified setuptools is wrong, anyway, because a setuptools that’s so old it doesn’t include the PEP 517 backend interface should be excluded. Yes, I know this is probably never going to matter, but IMO correctness is important anyway…

I’ve no objections to adding a version constraint. It might not matter when building with isolation but e.g. distro packagers might appreciate the gesture or a frontend which is yet to be conceived might wish to verify that depedencies are met when building without isolation.

+1 for adding a version constraint to the setuptools package.

My only thought around removing wheel is: does it break any users of “setup.py + pyproject.toml” packages? One that I can think of is a package that imports wheel in it’s setup.py (eg: to override bdist_wheel). If there’s no workflows that we’d break with this, I’m on board.

Ah yes, if authors of ‘legacy’ packages were relying on wheel being provided by pip if they had a pyproject.toml without a build-system section to import wheel in setup.py unconditionally, that’s going to break. But considering that wheel is not installed in a fresh venv (or system-wide) by default, I would be very surprised if wheel imports weren’t guarded in this context.

If we are touching this, I think we should make the build backend explicit.

build-backend = 'setuptools.build_meta'

Especially considering this

For the vast majority of Python projects that rely upon setuptools, the pyproject.toml file will be:

The current build system table has no build backend, so it will fallback to setuptools.build_meta:__legacy__, which is actually not what most people want to be running.

The current default backend was specifically added to avoid creating the difference in behaviour between the build_meta vs how things used to work (I think it was current working directory on sys.path handling). Reverting that is a no-go, IMO.

1 Like

Yes but we are not changing the default backend, that is defined in PEP 517, not PEP 518. I read this in PEP 518 as a recommendation of what you should probably do if you are sticking with setuptools, which is very likely not use the legacy backend.

This is a bit of a jumble with part of the fallback (the requirements) being defined in PEP 518 and the other half (the backend) in PEP 517. This in fact makes it impossible to remove wheel from the snippet in PEP 518 since PEP 518 does not assume the existence of PEP 517, i.e. that there is another way to retrieve build requirements.

The recommendation for build tools in PEP 518 is actually not followed by pip - pip will not install setuptools and wheel if they’re missing from a non-isolated (non-PEP 517) build environment, which is to say that pip only opts into PEP 518 if it opts into PEP 517 as well.