Fix #6163: Default to setuptools.build_meta:__legacy__

The main setuptools PEP 517 backend is intended for
explicit usage in `pyproject.toml`, when the project
authors can ensure that their `setup.py` runs without
that directory being implicitly on `sys.path`.

For implicit usage, setuptools now offers a separate
legacy backend that more closely mimics direct
execution of the `setup.py` script.
This commit is contained in:
Nick Coghlan 2019-01-28 20:16:20 +10:00
parent 5a61475f95
commit 682cff7230
7 changed files with 114 additions and 22 deletions

1
.gitignore vendored
View File

@ -27,6 +27,7 @@ nosetests.xml
coverage.xml
*.cover
tests/data/common_wheels/
pip-wheel-metadata
# Misc
*~

View File

@ -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

5
news/6163.bugfix Normal file
View File

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

View File

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

View File

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

View File

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

View File

@ -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