mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Merge pull request #6449 from cjerdonek/restore-pyproject-toml-19.0.3
Restore pyproject.toml handling to its version 19.0.3 state
This commit is contained in:
commit
f8732ac06d
|
@ -1,7 +1,2 @@
|
||||||
Allow ``--no-use-pep517`` to be used as a work-around when installing a
|
Restore ``pyproject.toml`` handling to how it was with pip 19.0.3 to prevent
|
||||||
project in editable mode, even when `PEP 517
|
the need to add ``--no-use-pep517`` when installing in editable mode.
|
||||||
<https://www.python.org/dev/peps/pep-0517/>`_ mandates
|
|
||||||
``pyproject.toml``-style processing (i.e. when the project has a
|
|
||||||
``pyproject.toml`` file as well as a ``"build-backend"`` key for the
|
|
||||||
``[build-system]`` table). Since this option conflicts with the PEP 517 spec,
|
|
||||||
this mode of operation is officially unsupported.
|
|
||||||
|
|
|
@ -136,11 +136,7 @@ class IsSDist(DistAbstraction):
|
||||||
# 2. Set up the build environment
|
# 2. Set up the build environment
|
||||||
|
|
||||||
self.req.load_pyproject_toml()
|
self.req.load_pyproject_toml()
|
||||||
|
should_isolate = self.req.use_pep517 and build_isolation
|
||||||
should_isolate = (
|
|
||||||
(self.req.use_pep517 or self.req.pyproject_requires) and
|
|
||||||
build_isolation
|
|
||||||
)
|
|
||||||
|
|
||||||
if should_isolate:
|
if should_isolate:
|
||||||
# Isolate in a BuildEnvironment and install the build-time
|
# Isolate in a BuildEnvironment and install the build-time
|
||||||
|
@ -167,12 +163,10 @@ class IsSDist(DistAbstraction):
|
||||||
" and ".join(map(repr, sorted(missing)))
|
" and ".join(map(repr, sorted(missing)))
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.req.use_pep517:
|
# Install any extra build dependencies that the backend requests.
|
||||||
# If we're using PEP 517, then install any extra build
|
# This must be done in a second pass, as the pyproject.toml
|
||||||
# dependencies that the backend requested. This must be
|
# dependencies must be installed before we can call the backend.
|
||||||
# done in a second pass, as the pyproject.toml dependencies
|
self.install_backend_dependencies(finder=finder)
|
||||||
# must be installed before we can call the backend.
|
|
||||||
self.install_backend_dependencies(finder=finder)
|
|
||||||
|
|
||||||
self.req.prepare_metadata()
|
self.req.prepare_metadata()
|
||||||
self.req.assert_source_matches_version()
|
self.req.assert_source_matches_version()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -11,12 +10,7 @@ from pip._internal.exceptions import InstallationError
|
||||||
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
|
||||||
|
|
||||||
if MYPY_CHECK_RUNNING:
|
if MYPY_CHECK_RUNNING:
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Tuple, Optional, List
|
||||||
|
|
||||||
Pep517Data = Tuple[str, List[str]]
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def _is_list_of_str(obj):
|
def _is_list_of_str(obj):
|
||||||
|
@ -38,42 +32,100 @@ def make_pyproject_path(setup_py_dir):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def read_pyproject_toml(path):
|
def load_pyproject_toml(
|
||||||
# type: (str) -> Optional[Dict[str, str]]
|
use_pep517, # type: Optional[bool]
|
||||||
|
pyproject_toml, # type: str
|
||||||
|
setup_py, # type: str
|
||||||
|
req_name # type: str
|
||||||
|
):
|
||||||
|
# type: (...) -> Optional[Tuple[List[str], str, List[str]]]
|
||||||
|
"""Load the pyproject.toml file.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
use_pep517 - Has the user requested PEP 517 processing? None
|
||||||
|
means the user hasn't explicitly specified.
|
||||||
|
pyproject_toml - Location of the project's pyproject.toml file
|
||||||
|
setup_py - Location of the project's setup.py file
|
||||||
|
req_name - The name of the requirement we're processing (for
|
||||||
|
error reporting)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None if we should use the legacy code path, otherwise a tuple
|
||||||
|
(
|
||||||
|
requirements from pyproject.toml,
|
||||||
|
name of PEP 517 backend,
|
||||||
|
requirements we should check are installed after setting
|
||||||
|
up the build environment
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
Read a project's pyproject.toml file.
|
has_pyproject = os.path.isfile(pyproject_toml)
|
||||||
|
has_setup = os.path.isfile(setup_py)
|
||||||
|
|
||||||
:param path: The path to the pyproject.toml file.
|
if has_pyproject:
|
||||||
|
with io.open(pyproject_toml, encoding="utf-8") as f:
|
||||||
|
pp_toml = pytoml.load(f)
|
||||||
|
build_system = pp_toml.get("build-system")
|
||||||
|
else:
|
||||||
|
build_system = None
|
||||||
|
|
||||||
:return: The "build_system" value specified in the project's
|
# The following cases must use PEP 517
|
||||||
pyproject.toml file.
|
# We check for use_pep517 being non-None and falsey because that means
|
||||||
"""
|
# the user explicitly requested --no-use-pep517. The value 0 as
|
||||||
with io.open(path, encoding="utf-8") as f:
|
# opposed to False can occur when the value is provided via an
|
||||||
pp_toml = pytoml.load(f)
|
# environment variable or config file option (due to the quirk of
|
||||||
build_system = pp_toml.get("build-system")
|
# strtobool() returning an integer in pip's configuration code).
|
||||||
|
if has_pyproject and not has_setup:
|
||||||
|
if use_pep517 is not None and not use_pep517:
|
||||||
|
raise InstallationError(
|
||||||
|
"Disabling PEP 517 processing is invalid: "
|
||||||
|
"project does not have a setup.py"
|
||||||
|
)
|
||||||
|
use_pep517 = True
|
||||||
|
elif build_system and "build-backend" in build_system:
|
||||||
|
if use_pep517 is not None and not use_pep517:
|
||||||
|
raise InstallationError(
|
||||||
|
"Disabling PEP 517 processing is invalid: "
|
||||||
|
"project specifies a build backend of {} "
|
||||||
|
"in pyproject.toml".format(
|
||||||
|
build_system["build-backend"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
use_pep517 = True
|
||||||
|
|
||||||
return build_system
|
# If we haven't worked out whether to use PEP 517 yet,
|
||||||
|
# and the user hasn't explicitly stated a preference,
|
||||||
|
# we do so if the project has a pyproject.toml file.
|
||||||
|
elif use_pep517 is None:
|
||||||
|
use_pep517 = has_pyproject
|
||||||
|
|
||||||
|
# At this point, we know whether we're going to use PEP 517.
|
||||||
|
assert use_pep517 is not None
|
||||||
|
|
||||||
def make_editable_error(req_name, reason):
|
# If we're using the legacy code path, there is nothing further
|
||||||
"""
|
# for us to do here.
|
||||||
:param req_name: the name of the requirement.
|
if not use_pep517:
|
||||||
:param reason: the reason the requirement is being processed as
|
|
||||||
pyproject.toml-style.
|
|
||||||
"""
|
|
||||||
message = (
|
|
||||||
'Error installing {!r}: editable mode is not supported for '
|
|
||||||
'pyproject.toml-style projects. This project is being processed '
|
|
||||||
'as pyproject.toml-style because {}. '
|
|
||||||
'See PEP 517 for the relevant specification.'
|
|
||||||
).format(req_name, reason)
|
|
||||||
return InstallationError(message)
|
|
||||||
|
|
||||||
|
|
||||||
def get_build_system_requires(build_system, req_name):
|
|
||||||
if build_system is None:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if build_system is None:
|
||||||
|
# Either the user has a pyproject.toml with no build-system
|
||||||
|
# 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 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.8.0", "wheel"],
|
||||||
|
"build-backend": "setuptools.build_meta:__legacy__",
|
||||||
|
}
|
||||||
|
|
||||||
|
# If we're using PEP 517, we have build system information (either
|
||||||
|
# from pyproject.toml, or defaulted by the code above).
|
||||||
|
# Note that at this point, we do not know if the user has actually
|
||||||
|
# specified a backend, though.
|
||||||
|
assert build_system is not None
|
||||||
|
|
||||||
# Ensure that the build-system section in pyproject.toml conforms
|
# Ensure that the build-system section in pyproject.toml conforms
|
||||||
# to PEP 518.
|
# to PEP 518.
|
||||||
error_template = (
|
error_template = (
|
||||||
|
@ -98,150 +150,6 @@ def get_build_system_requires(build_system, req_name):
|
||||||
reason="'build-system.requires' is not a list of strings.",
|
reason="'build-system.requires' is not a list of strings.",
|
||||||
))
|
))
|
||||||
|
|
||||||
return requires
|
|
||||||
|
|
||||||
|
|
||||||
def resolve_pyproject_toml(
|
|
||||||
build_system, # type: Optional[Dict[str, Any]]
|
|
||||||
has_pyproject, # type: bool
|
|
||||||
has_setup, # type: bool
|
|
||||||
use_pep517, # type: Optional[bool]
|
|
||||||
editable, # type: bool
|
|
||||||
req_name, # type: str
|
|
||||||
):
|
|
||||||
# type: (...) -> Tuple[Optional[List[str]], Optional[Pep517Data]]
|
|
||||||
"""
|
|
||||||
Return how a pyproject.toml file's contents should be interpreted.
|
|
||||||
|
|
||||||
:param build_system: the "build_system" value specified in a project's
|
|
||||||
pyproject.toml file, or None if the project either doesn't have the
|
|
||||||
file or does but the file doesn't have a [build-system] table.
|
|
||||||
:param has_pyproject: whether the project has a pyproject.toml file.
|
|
||||||
:param has_setup: whether the project has a setup.py file.
|
|
||||||
:param use_pep517: whether the user requested PEP 517 processing. None
|
|
||||||
means the user didn't explicitly specify.
|
|
||||||
:param editable: whether editable mode was requested for the requirement.
|
|
||||||
:param req_name: the name of the requirement we're processing (for
|
|
||||||
error reporting).
|
|
||||||
|
|
||||||
:return: a tuple (requires, pep517_data), where `requires` is the list
|
|
||||||
of build requirements from pyproject.toml (or else None). The value
|
|
||||||
`pep517_data` is None if `use_pep517` is False. Otherwise, it is the
|
|
||||||
tuple (backend, check), where `backend` is the name of the PEP 517
|
|
||||||
backend and `check` is the list of requirements we should check are
|
|
||||||
installed after setting up the build environment.
|
|
||||||
"""
|
|
||||||
# The following cases must use PEP 517
|
|
||||||
# We check for use_pep517 being non-None and falsey because that means
|
|
||||||
# the user explicitly requested --no-use-pep517. The value 0 as
|
|
||||||
# opposed to False can occur when the value is provided via an
|
|
||||||
# environment variable or config file option (due to the quirk of
|
|
||||||
# strtobool() returning an integer in pip's configuration code).
|
|
||||||
if editable and use_pep517:
|
|
||||||
raise make_editable_error(
|
|
||||||
req_name, 'PEP 517 processing was explicitly requested'
|
|
||||||
)
|
|
||||||
elif has_pyproject and not has_setup:
|
|
||||||
if use_pep517 is not None and not use_pep517:
|
|
||||||
raise InstallationError(
|
|
||||||
"Disabling PEP 517 processing is invalid: "
|
|
||||||
"project does not have a setup.py"
|
|
||||||
)
|
|
||||||
if editable:
|
|
||||||
raise make_editable_error(
|
|
||||||
req_name, 'it has a pyproject.toml file and no setup.py'
|
|
||||||
)
|
|
||||||
use_pep517 = True
|
|
||||||
elif build_system and "build-backend" in build_system:
|
|
||||||
if editable:
|
|
||||||
if use_pep517 is None:
|
|
||||||
message = (
|
|
||||||
'Error installing {!r}: editable mode is not supported '
|
|
||||||
'for pyproject.toml-style projects. '
|
|
||||||
'This project is pyproject.toml-style because it has a '
|
|
||||||
'pyproject.toml file and a "build-backend" key for the '
|
|
||||||
'[build-system] table, but editable mode is undefined '
|
|
||||||
'for pyproject.toml-style projects. '
|
|
||||||
'Since the project has a setup.py, you may pass '
|
|
||||||
'--no-use-pep517 to opt out of pyproject.toml-style '
|
|
||||||
'processing. However, this is an unsupported combination. '
|
|
||||||
'See PEP 517 for details on pyproject.toml-style projects.'
|
|
||||||
).format(req_name)
|
|
||||||
raise InstallationError(message)
|
|
||||||
|
|
||||||
# The case of `editable and use_pep517` being true was already
|
|
||||||
# handled above.
|
|
||||||
assert not use_pep517
|
|
||||||
message = (
|
|
||||||
'Installing {!r} in editable mode, which is not supported '
|
|
||||||
'for pyproject.toml-style projects: '
|
|
||||||
'this project is pyproject.toml-style because it has a '
|
|
||||||
'pyproject.toml file and a "build-backend" key for the '
|
|
||||||
'[build-system] table, but editable mode is undefined '
|
|
||||||
'for pyproject.toml-style projects. '
|
|
||||||
'See PEP 517 for details on pyproject.toml-style projects.'
|
|
||||||
).format(req_name)
|
|
||||||
logger.warning(message)
|
|
||||||
elif use_pep517 is not None and not use_pep517:
|
|
||||||
raise InstallationError(
|
|
||||||
"Disabling PEP 517 processing is invalid: "
|
|
||||||
"project specifies a build backend of {} "
|
|
||||||
"in pyproject.toml".format(
|
|
||||||
build_system["build-backend"]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
use_pep517 = True
|
|
||||||
|
|
||||||
# If we haven't worked out whether to use PEP 517 yet, and the user
|
|
||||||
# hasn't explicitly stated a preference, we do so if the project has
|
|
||||||
# a pyproject.toml file (provided editable mode wasn't requested).
|
|
||||||
elif use_pep517 is None:
|
|
||||||
if has_pyproject and editable:
|
|
||||||
message = (
|
|
||||||
'Error installing {!r}: editable mode is not supported for '
|
|
||||||
'pyproject.toml-style projects. pip is processing this '
|
|
||||||
'project as pyproject.toml-style because it has a '
|
|
||||||
'pyproject.toml file. Since the project has a setup.py and '
|
|
||||||
'the pyproject.toml has no "build-backend" key for the '
|
|
||||||
'[build-system] table, you may pass --no-use-pep517 to opt '
|
|
||||||
'out of pyproject.toml-style processing. '
|
|
||||||
'See PEP 517 for details on pyproject.toml-style projects.'
|
|
||||||
).format(req_name)
|
|
||||||
raise InstallationError(message)
|
|
||||||
|
|
||||||
use_pep517 = has_pyproject
|
|
||||||
|
|
||||||
# At this point, we know whether we're going to use PEP 517.
|
|
||||||
assert use_pep517 is not None
|
|
||||||
|
|
||||||
requires = get_build_system_requires(build_system, req_name=req_name)
|
|
||||||
|
|
||||||
# If we're using the legacy code path, there is nothing further
|
|
||||||
# for us to do here.
|
|
||||||
if not use_pep517:
|
|
||||||
return (requires, None)
|
|
||||||
|
|
||||||
if build_system is None:
|
|
||||||
# Either the user has a pyproject.toml with no build-system
|
|
||||||
# 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 that most closely emulates the
|
|
||||||
# traditional direct setup.py execution, and require wheel and
|
|
||||||
# a version of setuptools that supports that backend.
|
|
||||||
|
|
||||||
requires = ["setuptools>=40.8.0", "wheel"]
|
|
||||||
build_system = {
|
|
||||||
"build-backend": "setuptools.build_meta:__legacy__",
|
|
||||||
}
|
|
||||||
|
|
||||||
# If we're using PEP 517, we have build system information (either
|
|
||||||
# from pyproject.toml, or defaulted by the code above).
|
|
||||||
# Note that at this point, we do not know if the user has actually
|
|
||||||
# specified a backend, though.
|
|
||||||
assert build_system is not None
|
|
||||||
|
|
||||||
backend = build_system.get("build-backend")
|
backend = build_system.get("build-backend")
|
||||||
check = [] # type: List[str]
|
check = [] # type: List[str]
|
||||||
if backend is None:
|
if backend is None:
|
||||||
|
@ -260,50 +168,4 @@ def resolve_pyproject_toml(
|
||||||
backend = "setuptools.build_meta:__legacy__"
|
backend = "setuptools.build_meta:__legacy__"
|
||||||
check = ["setuptools>=40.8.0", "wheel"]
|
check = ["setuptools>=40.8.0", "wheel"]
|
||||||
|
|
||||||
return (requires, (backend, check))
|
return (requires, backend, check)
|
||||||
|
|
||||||
|
|
||||||
def load_pyproject_toml(
|
|
||||||
use_pep517, # type: Optional[bool]
|
|
||||||
editable, # type: bool
|
|
||||||
pyproject_toml, # type: str
|
|
||||||
setup_py, # type: str
|
|
||||||
req_name # type: str
|
|
||||||
):
|
|
||||||
# type: (...) -> Tuple[Optional[List[str]], Optional[Pep517Data]]
|
|
||||||
"""Load the pyproject.toml file.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
use_pep517 - Has the user requested PEP 517 processing? None
|
|
||||||
means the user hasn't explicitly specified.
|
|
||||||
editable - Whether editable mode was requested for the requirement.
|
|
||||||
pyproject_toml - Location of the project's pyproject.toml file
|
|
||||||
setup_py - Location of the project's setup.py file
|
|
||||||
req_name - The name of the requirement we're processing (for
|
|
||||||
error reporting)
|
|
||||||
|
|
||||||
Returns: (requires, pep_517_data)
|
|
||||||
requires: requirements from pyproject.toml (can be None).
|
|
||||||
pep_517_data: None if we should use the legacy code path, otherwise:
|
|
||||||
(
|
|
||||||
name of PEP 517 backend,
|
|
||||||
requirements we should check are installed after setting up
|
|
||||||
the build environment
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
has_pyproject = os.path.isfile(pyproject_toml)
|
|
||||||
has_setup = os.path.isfile(setup_py)
|
|
||||||
|
|
||||||
if has_pyproject:
|
|
||||||
build_system = read_pyproject_toml(pyproject_toml)
|
|
||||||
else:
|
|
||||||
build_system = None
|
|
||||||
|
|
||||||
return resolve_pyproject_toml(
|
|
||||||
build_system=build_system,
|
|
||||||
has_pyproject=has_pyproject,
|
|
||||||
has_setup=has_setup,
|
|
||||||
use_pep517=use_pep517,
|
|
||||||
editable=editable,
|
|
||||||
req_name=req_name,
|
|
||||||
)
|
|
||||||
|
|
|
@ -485,22 +485,20 @@ class InstallRequirement(object):
|
||||||
use_pep517 attribute can be used to determine whether we should
|
use_pep517 attribute can be used to determine whether we should
|
||||||
follow the PEP 517 or legacy (setup.py) code path.
|
follow the PEP 517 or legacy (setup.py) code path.
|
||||||
"""
|
"""
|
||||||
requires, pep517_data = load_pyproject_toml(
|
pep517_data = load_pyproject_toml(
|
||||||
self.use_pep517,
|
self.use_pep517,
|
||||||
self.editable,
|
|
||||||
self.pyproject_toml,
|
self.pyproject_toml,
|
||||||
self.setup_py,
|
self.setup_py,
|
||||||
str(self)
|
str(self)
|
||||||
)
|
)
|
||||||
|
|
||||||
use_pep517 = bool(pep517_data)
|
if pep517_data is None:
|
||||||
|
self.use_pep517 = False
|
||||||
self.use_pep517 = use_pep517
|
else:
|
||||||
self.pyproject_requires = requires
|
self.use_pep517 = True
|
||||||
|
requires, backend, check = pep517_data
|
||||||
if use_pep517:
|
|
||||||
backend, check = pep517_data
|
|
||||||
self.requirements_to_check = check
|
self.requirements_to_check = check
|
||||||
|
self.pyproject_requires = requires
|
||||||
self.pep517_backend = Pep517HookCaller(self.setup_py_dir, backend)
|
self.pep517_backend = Pep517HookCaller(self.setup_py_dir, backend)
|
||||||
|
|
||||||
# Use a custom function to call subprocesses
|
# Use a custom function to call subprocesses
|
||||||
|
|
|
@ -302,12 +302,8 @@ def test_constraints_local_editable_install_pep518(script, data):
|
||||||
to_install = data.src.join("pep518-3.0")
|
to_install = data.src.join("pep518-3.0")
|
||||||
|
|
||||||
script.pip('download', 'setuptools', 'wheel', '-d', data.packages)
|
script.pip('download', 'setuptools', 'wheel', '-d', data.packages)
|
||||||
# --no-use-pep517 has to be passed since a pyproject.toml file is
|
|
||||||
# present but PEP 517 doesn't support editable mode.
|
|
||||||
script.pip(
|
script.pip(
|
||||||
'install', '--no-use-pep517', '--no-index', '-f', data.find_links,
|
'install', '--no-index', '-f', data.find_links, '-e', to_install)
|
||||||
'-e', to_install,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_constraints_local_install_causes_error(script, data):
|
def test_constraints_local_install_causes_error(script, data):
|
||||||
|
|
|
@ -1,210 +1,9 @@
|
||||||
from contextlib import contextmanager
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pip._internal.exceptions import InstallationError
|
from pip._internal.exceptions import InstallationError
|
||||||
from pip._internal.pyproject import resolve_pyproject_toml
|
|
||||||
from pip._internal.req import InstallRequirement
|
from pip._internal.req import InstallRequirement
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def assert_error_startswith(exc_type, expected_start, expected_substr):
|
|
||||||
with pytest.raises(InstallationError) as excinfo:
|
|
||||||
yield
|
|
||||||
|
|
||||||
err_args = excinfo.value.args
|
|
||||||
assert len(err_args) == 1
|
|
||||||
msg = err_args[0]
|
|
||||||
assert msg.startswith(expected_start), 'full message: {}'.format(msg)
|
|
||||||
assert expected_substr in msg, 'full message: {}'.format(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_pyproject_toml__pep_517_optional():
|
|
||||||
"""
|
|
||||||
Test resolve_pyproject_toml() when has_pyproject=True but the source
|
|
||||||
tree isn't pyproject.toml-style per PEP 517.
|
|
||||||
"""
|
|
||||||
actual = resolve_pyproject_toml(
|
|
||||||
build_system=None,
|
|
||||||
has_pyproject=True,
|
|
||||||
has_setup=True,
|
|
||||||
use_pep517=None,
|
|
||||||
editable=False,
|
|
||||||
req_name='my-package',
|
|
||||||
)
|
|
||||||
expected = (
|
|
||||||
['setuptools>=40.8.0', 'wheel'],
|
|
||||||
('setuptools.build_meta:__legacy__', []),
|
|
||||||
)
|
|
||||||
assert actual == expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_pyproject_toml__editable_with_build_system_requires():
|
|
||||||
"""
|
|
||||||
Test a case of editable=True when build-system.requires are returned.
|
|
||||||
"""
|
|
||||||
actual = resolve_pyproject_toml(
|
|
||||||
build_system={'requires': ['package-a', 'package=b']},
|
|
||||||
has_pyproject=True,
|
|
||||||
has_setup=True,
|
|
||||||
use_pep517=False,
|
|
||||||
editable=True,
|
|
||||||
req_name='my-package',
|
|
||||||
)
|
|
||||||
expected = (['package-a', 'package=b'], None)
|
|
||||||
assert actual == expected
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_pyproject_toml__editable_without_use_pep517_false():
|
|
||||||
"""
|
|
||||||
Test passing editable=True when PEP 517 processing is optional, but
|
|
||||||
use_pep517=False hasn't been passed.
|
|
||||||
"""
|
|
||||||
expected_start = (
|
|
||||||
"Error installing 'my-package': editable mode is not supported"
|
|
||||||
)
|
|
||||||
expected_substr = (
|
|
||||||
'you may pass --no-use-pep517 to opt out of pyproject.toml-style '
|
|
||||||
'processing'
|
|
||||||
)
|
|
||||||
with assert_error_startswith(
|
|
||||||
InstallationError, expected_start, expected_substr=expected_substr,
|
|
||||||
):
|
|
||||||
resolve_pyproject_toml(
|
|
||||||
build_system=None,
|
|
||||||
has_pyproject=True,
|
|
||||||
has_setup=True,
|
|
||||||
use_pep517=None,
|
|
||||||
editable=True,
|
|
||||||
req_name='my-package',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
'has_pyproject, has_setup, use_pep517, build_system, expected_err', [
|
|
||||||
# Test pyproject.toml with no setup.py.
|
|
||||||
(True, False, None, None, 'has a pyproject.toml file and no setup.py'),
|
|
||||||
# Test explicitly requesting PEP 517 processing.
|
|
||||||
(True, True, True, None,
|
|
||||||
'PEP 517 processing was explicitly requested'),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
def test_resolve_pyproject_toml__editable_and_pep_517_required(
|
|
||||||
has_pyproject, has_setup, use_pep517, build_system, expected_err,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test that passing editable=True raises an error if PEP 517 processing
|
|
||||||
is required.
|
|
||||||
"""
|
|
||||||
expected_start = (
|
|
||||||
"Error installing 'my-package': editable mode is not supported"
|
|
||||||
)
|
|
||||||
with assert_error_startswith(
|
|
||||||
InstallationError, expected_start, expected_substr=expected_err,
|
|
||||||
):
|
|
||||||
resolve_pyproject_toml(
|
|
||||||
build_system=build_system,
|
|
||||||
has_pyproject=has_pyproject,
|
|
||||||
has_setup=has_setup,
|
|
||||||
use_pep517=use_pep517,
|
|
||||||
editable=True,
|
|
||||||
req_name='my-package',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_pyproject_toml__editable_build_backend_use_pep517_none():
|
|
||||||
"""
|
|
||||||
Test editable=True with "build-backend" and use_pep517=None.
|
|
||||||
"""
|
|
||||||
expected_start = (
|
|
||||||
"Error installing 'my-package': editable mode is not supported "
|
|
||||||
)
|
|
||||||
expected_substr = 'you may pass --no-use-pep517 to opt out'
|
|
||||||
|
|
||||||
with assert_error_startswith(
|
|
||||||
InstallationError, expected_start, expected_substr=expected_substr,
|
|
||||||
):
|
|
||||||
resolve_pyproject_toml(
|
|
||||||
build_system={'requires': ['my-package'], 'build-backend': 'foo'},
|
|
||||||
has_pyproject=True,
|
|
||||||
has_setup=True,
|
|
||||||
use_pep517=None,
|
|
||||||
editable=True,
|
|
||||||
req_name='my-package',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_pyproject_toml__editable_build_backend_use_pep517_false(
|
|
||||||
caplog
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test editable=True with "build-backend" and use_pep517=False.
|
|
||||||
"""
|
|
||||||
resolve_pyproject_toml(
|
|
||||||
build_system={'requires': ['my-package'], 'build-backend': 'foo'},
|
|
||||||
has_pyproject=True,
|
|
||||||
has_setup=True,
|
|
||||||
use_pep517=False,
|
|
||||||
editable=True,
|
|
||||||
req_name='my-package',
|
|
||||||
)
|
|
||||||
|
|
||||||
records = caplog.records
|
|
||||||
assert len(records) == 1
|
|
||||||
record = records[0]
|
|
||||||
assert record.levelname == 'WARNING'
|
|
||||||
expected_start = (
|
|
||||||
"Installing 'my-package' in editable mode, which is not supported "
|
|
||||||
)
|
|
||||||
assert record.message.startswith(expected_start), (
|
|
||||||
'full message: {}'.format(record.message)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
'has_pyproject, has_setup, use_pep517, editable, build_system, '
|
|
||||||
'expected_err', [
|
|
||||||
# Test editable=False with no build-system.requires.
|
|
||||||
(True, False, None, False, {},
|
|
||||||
"it has a 'build-system' table but not 'build-system.requires'"),
|
|
||||||
# Test editable=True with no build-system.requires (we also
|
|
||||||
# need to pass use_pep517=False).
|
|
||||||
(True, True, False, True, {},
|
|
||||||
"it has a 'build-system' table but not 'build-system.requires'"),
|
|
||||||
# Test editable=False with a bad build-system.requires value.
|
|
||||||
(True, False, None, False, {'requires': 'foo'},
|
|
||||||
"'build-system.requires' is not a list of strings"),
|
|
||||||
# Test editable=True with a bad build-system.requires value (we also
|
|
||||||
# need to pass use_pep517=False).
|
|
||||||
(True, True, False, True, {'requires': 'foo'},
|
|
||||||
"'build-system.requires' is not a list of strings"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
def test_resolve_pyproject_toml__bad_build_system_section(
|
|
||||||
has_pyproject, has_setup, use_pep517, editable, build_system,
|
|
||||||
expected_err,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Test a pyproject.toml build-system section that doesn't conform to
|
|
||||||
PEP 518.
|
|
||||||
"""
|
|
||||||
expected_start = (
|
|
||||||
'my-package has a pyproject.toml file that does not comply with '
|
|
||||||
'PEP 518:'
|
|
||||||
)
|
|
||||||
with assert_error_startswith(
|
|
||||||
InstallationError, expected_start, expected_substr=expected_err,
|
|
||||||
):
|
|
||||||
resolve_pyproject_toml(
|
|
||||||
build_system=build_system,
|
|
||||||
has_pyproject=has_pyproject,
|
|
||||||
has_setup=has_setup,
|
|
||||||
use_pep517=use_pep517,
|
|
||||||
editable=editable,
|
|
||||||
req_name='my-package',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(('source', 'expected'), [
|
@pytest.mark.parametrize(('source', 'expected'), [
|
||||||
("pep517_setup_and_pyproject", True),
|
("pep517_setup_and_pyproject", True),
|
||||||
("pep517_setup_only", False),
|
("pep517_setup_only", False),
|
||||||
|
|
Loading…
Reference in a new issue