Skip to content

Fix #6163: Default to setuptools.build_meta:__legacy__ #6212

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ nosetests.xml
coverage.xml
*.cover
tests/data/common_wheels/
pip-wheel-metadata

# Misc
*~
Expand Down
28 changes: 15 additions & 13 deletions docs/html/reference/pip.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,26 +145,28 @@ explicitly manage the build environment. For such workflows, build isolation
can be problematic. If this is the case, pip provides a
``--no-build-isolation`` flag to disable build isolation. Users supplying this
flag are responsible for ensuring the build environment is managed
appropriately.
appropriately (including ensuring that all required build dependencies are
installed).

By default, pip will continue to use the legacy (``setuptools`` based) build
processing for projects that do not have a ``pyproject.toml`` file. Projects
with a ``pyproject.toml`` file will use a :pep:`517` backend. Projects with
a ``pyproject.toml`` file, but which don't have a ``build-system`` section,
By default, pip will continue to use the legacy (direct ``setup.py`` execution
based) build processing for projects that do not have a ``pyproject.toml`` file.
Projects with a ``pyproject.toml`` file will use a :pep:`517` backend. Projects
with a ``pyproject.toml`` file, but which don't have a ``build-system`` section,
will be assumed to have the following backend settings::

[build-system]
requires = ["setuptools>=40.2.0", "wheel"]
build-backend = "setuptools.build_meta"
requires = ["setuptools>=40.8.0", "wheel"]
build-backend = "setuptools.build_meta:__legacy__"

.. note::

``setuptools`` 40.2.0 is the first version of setuptools with full
:pep:`517` support.

If a project has ``[build-system]``, but no ``build-backend``, pip will use
``setuptools.build_meta``, but will assume the project requirements include
``setuptools>=40.2.0`` and ``wheel`` (and will report an error if not).
``setuptools`` 40.8.0 is the first version of setuptools that offers a
:pep:`517` backend that closely mimics directly executing ``setup.py``.

If a project has ``[build-system]``, but no ``build-backend``, pip will also use
``setuptools.build_meta:__legacy__``, but will expect the project requirements
to include ``setuptools`` and ``wheel`` (and will report an error if the
installed version of ``setuptools`` is not recent enough).

If a user wants to explicitly request :pep:`517` handling even though a project
doesn't have a ``pyproject.toml`` file, this can be done using the
Expand Down
5 changes: 5 additions & 0 deletions news/6163.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The implicit default backend used for projects that provide a ``pyproject.toml``
file without explicitly specifying ``build-backend`` now behaves more like direct
execution of ``setup.py``, and hence should restore compatibility with projects
that were unable to be installed with ``pip`` 19.0. This raised the minimum
required version of ``setuptools`` for such builds to 40.8.0.
16 changes: 9 additions & 7 deletions src/pip/_internal/pyproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,13 @@ def load_pyproject_toml(
# section, or the user has no pyproject.toml, but has opted in
# explicitly via --use-pep517.
# In the absence of any explicit backend specification, we
# assume the setuptools backend, and require wheel and a version
# of setuptools that supports that backend.
# assume the setuptools backend that most closely emulates the
# traditional direct setup.py execution, and require wheel and
# a version of setuptools that supports that backend.

build_system = {
"requires": ["setuptools>=40.2.0", "wheel"],
"build-backend": "setuptools.build_meta",
"requires": ["setuptools>=40.8.0", "wheel"],
"build-backend": "setuptools.build_meta:__legacy__",
}

# If we're using PEP 517, we have build system information (either
Expand Down Expand Up @@ -154,7 +156,7 @@ def load_pyproject_toml(
# If the user didn't specify a backend, we assume they want to use
# the setuptools backend. But we can't be sure they have included
# a version of setuptools which supplies the backend, or wheel
# (which is neede by the backend) in their requirements. So we
# (which is needed by the backend) in their requirements. So we
# make a note to check that those requirements are present once
# we have set up the environment.
# This is quite a lot of work to check for a very specific case. But
Expand All @@ -163,7 +165,7 @@ def load_pyproject_toml(
# execute setup.py, but never considered needing to mention the build
# tools themselves. The original PEP 518 code had a similar check (but
# implemented in a different way).
backend = "setuptools.build_meta"
check = ["setuptools>=40.2.0", "wheel"]
backend = "setuptools.build_meta:__legacy__"
check = ["setuptools>=40.8.0", "wheel"]

return (requires, backend, check)
2 changes: 1 addition & 1 deletion tests/functional/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def test_pep518_refuses_conflicting_requires(script, data):
result.returncode != 0 and
('Some build dependencies for %s conflict with PEP 517/518 supported '
'requirements: setuptools==1.0 is incompatible with '
'setuptools>=40.2.0.' % path_to_url(project_dir)) in result.stderr
'setuptools>=40.8.0.' % path_to_url(project_dir)) in result.stderr
), str(result)


Expand Down
75 changes: 75 additions & 0 deletions tests/functional/test_pep517.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,78 @@ def test_pep517_install_with_no_cache_dir(script, tmpdir, data):
project_dir,
)
result.assert_installed('project', editable=False)


def make_pyproject_with_setup(tmpdir, build_system=True, set_backend=True):
project_dir = (tmpdir / 'project').mkdir()
setup_script = (
'from setuptools import setup\n'
)
expect_script_dir_on_path = True
if build_system:
buildsys = {
'requires': ['setuptools', 'wheel'],
}
if set_backend:
buildsys['build-backend'] = 'setuptools.build_meta'
expect_script_dir_on_path = False
project_data = pytoml.dumps({'build-system': buildsys})
else:
project_data = ''

if expect_script_dir_on_path:
setup_script += (
'from pep517_test import __version__\n'
)
else:
setup_script += (
'try:\n'
' import pep517_test\n'
'except ImportError:\n'
' pass\n'
'else:\n'
' raise RuntimeError("Source dir incorrectly on sys.path")\n'
)

setup_script += (
'setup(name="pep517_test", version="0.1", packages=["pep517_test"])'
)

project_dir.join('pyproject.toml').write(project_data)
project_dir.join('setup.py').write(setup_script)
package_dir = (project_dir / "pep517_test").mkdir()
package_dir.join('__init__.py').write('__version__ = "0.1"')
return project_dir, "pep517_test"


def test_no_build_system_section(script, tmpdir, data, common_wheels):
"""Check builds with setup.py, pyproject.toml, but no build-system section.
"""
project_dir, name = make_pyproject_with_setup(tmpdir, build_system=False)
result = script.pip(
'install', '--no-cache-dir', '--no-index', '-f', common_wheels,
project_dir,
)
result.assert_installed(name, editable=False)


def test_no_build_backend_entry(script, tmpdir, data, common_wheels):
"""Check builds with setup.py, pyproject.toml, but no build-backend entry.
"""
project_dir, name = make_pyproject_with_setup(tmpdir, set_backend=False)
result = script.pip(
'install', '--no-cache-dir', '--no-index', '-f', common_wheels,
project_dir,
)
result.assert_installed(name, editable=False)


def test_explicit_setuptools_backend(script, tmpdir, data, common_wheels):
"""Check builds with setup.py, pyproject.toml, and a build-backend entry.
"""
project_dir, name = make_pyproject_with_setup(tmpdir)
result = script.pip(
'install', '--no-cache-dir', '--no-index', '-f', common_wheels,
project_dir,
)
result.assert_installed(name, editable=False)
9 changes: 8 additions & 1 deletion tools/tests-common_wheels-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
setuptools
# Create local setuptools wheel files for testing by:
# 1. Cloning setuptools and checking out the branch of interest
# 2. Running `python3 bootstrap.py` in that directory
# 3. Running `python3 -m pip wheel --no-cache -w /tmp/setuptools_build_meta_legacy/ .`
# 4. Replacing the `setuptools` entry below with a `file:///...` URL
# (Adjust artifact directory used based on preference and operating system)

setuptools >= 40.8.0
wheel