mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Error out if installing a pyproject.toml-style (PEP 517) project in editable mode.
This commit is contained in:
parent
f66c1f7639
commit
cc2d299f76
4 changed files with 99 additions and 1 deletions
2
news/6314.feature
Normal file
2
news/6314.feature
Normal file
|
@ -0,0 +1,2 @@
|
|||
Error out with an informative message if one tries to install a
|
||||
``pyproject.toml``-style (PEP 517) source tree using ``--editable`` mode.
|
|
@ -49,11 +49,27 @@ def read_pyproject_toml(path):
|
|||
return build_system
|
||||
|
||||
|
||||
def make_editable_error(req_name, reason):
|
||||
"""
|
||||
:param req_name: the name of the requirement.
|
||||
: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 resolve_pyproject_toml(
|
||||
build_system, # type: Optional[Dict[str, str]]
|
||||
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: (...) -> Optional[Tuple[List[str], str, List[str]]]
|
||||
|
@ -67,6 +83,7 @@ def resolve_pyproject_toml(
|
|||
: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).
|
||||
"""
|
||||
|
@ -82,6 +99,10 @@ def resolve_pyproject_toml(
|
|||
"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 use_pep517 is not None and not use_pep517:
|
||||
|
@ -92,7 +113,18 @@ def resolve_pyproject_toml(
|
|||
build_system["build-backend"]
|
||||
)
|
||||
)
|
||||
if editable:
|
||||
reason = (
|
||||
'it has a pyproject.toml file with a "build-backend" key '
|
||||
'in the "build_system" value'
|
||||
)
|
||||
raise make_editable_error(req_name, reason)
|
||||
use_pep517 = True
|
||||
elif use_pep517:
|
||||
if editable:
|
||||
raise make_editable_error(
|
||||
req_name, 'PEP 517 processing was explicitly requested'
|
||||
)
|
||||
|
||||
# If we haven't worked out whether to use PEP 517 yet,
|
||||
# and the user hasn't explicitly stated a preference,
|
||||
|
@ -175,6 +207,7 @@ def resolve_pyproject_toml(
|
|||
|
||||
def load_pyproject_toml(
|
||||
use_pep517, # type: Optional[bool]
|
||||
editable, # type: bool
|
||||
pyproject_toml, # type: str
|
||||
setup_py, # type: str
|
||||
req_name # type: str
|
||||
|
@ -185,6 +218,7 @@ def load_pyproject_toml(
|
|||
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
|
||||
|
@ -212,5 +246,6 @@ def load_pyproject_toml(
|
|||
has_pyproject=has_pyproject,
|
||||
has_setup=has_setup,
|
||||
use_pep517=use_pep517,
|
||||
editable=editable,
|
||||
req_name=req_name,
|
||||
)
|
||||
|
|
|
@ -484,6 +484,7 @@ class InstallRequirement(object):
|
|||
"""
|
||||
pep517_data = load_pyproject_toml(
|
||||
self.use_pep517,
|
||||
self.editable,
|
||||
self.pyproject_toml,
|
||||
self.setup_py,
|
||||
str(self)
|
||||
|
|
|
@ -1,9 +1,69 @@
|
|||
import pytest
|
||||
|
||||
from pip._internal.exceptions import InstallationError
|
||||
from pip._internal.pyproject import resolve_pyproject_toml
|
||||
from pip._internal.req import InstallRequirement
|
||||
|
||||
|
||||
@pytest.mark.parametrize('editable', [False, True])
|
||||
def test_resolve_pyproject_toml__pep_517_optional(editable):
|
||||
"""
|
||||
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=editable,
|
||||
req_name='my-package',
|
||||
)
|
||||
expected = (
|
||||
['setuptools>=40.8.0', 'wheel'],
|
||||
'setuptools.build_meta:__legacy__',
|
||||
[],
|
||||
)
|
||||
assert actual == expected
|
||||
|
||||
|
||||
@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 "build-backend" present.
|
||||
(True, True, None, {'build-backend': 'foo'},
|
||||
'has a pyproject.toml file with a "build-backend" key'),
|
||||
# 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.
|
||||
"""
|
||||
with pytest.raises(InstallationError) as excinfo:
|
||||
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',
|
||||
)
|
||||
err_args = excinfo.value.args
|
||||
assert len(err_args) == 1
|
||||
msg = err_args[0]
|
||||
assert msg.startswith(
|
||||
"Error installing 'my-package': editable mode is not supported"
|
||||
)
|
||||
assert expected_err in msg, 'full message: {}'.format(msg)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(('source', 'expected'), [
|
||||
("pep517_setup_and_pyproject", True),
|
||||
("pep517_setup_only", False),
|
||||
|
|
Loading…
Reference in a new issue