Skip to content

Commit 9861dc7

Browse files
authored
Merge pull request #6442 from cjerdonek/issue-6434-pyproject-editable
Permit --no-use-pep517 with editable mode in more cases.
2 parents 9816d17 + f069769 commit 9861dc7

File tree

3 files changed

+97
-17
lines changed

3 files changed

+97
-17
lines changed

news/6434.feature

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Allow ``--no-use-pep517`` to be used as a work-around when installing a
2+
project in editable mode, even when `PEP 517
3+
<https://www.python.org/dev/peps/pep-0517/>`_ mandates
4+
``pyproject.toml``-style processing (i.e. when the project has a
5+
``pyproject.toml`` file as well as a ``"build-backend"`` key for the
6+
``"build_system"`` value). Since this option conflicts with the PEP 517 spec,
7+
this mode of operation is officially unsupported.

src/pip/_internal/pyproject.py

+41-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import absolute_import
22

33
import io
4+
import logging
45
import os
56
import sys
67

@@ -15,6 +16,9 @@
1516
Pep517Data = Tuple[str, List[str]]
1617

1718

19+
logger = logging.getLogger(__name__)
20+
21+
1822
def _is_list_of_str(obj):
1923
# type: (Any) -> bool
2024
return (
@@ -133,7 +137,11 @@ def resolve_pyproject_toml(
133137
# opposed to False can occur when the value is provided via an
134138
# environment variable or config file option (due to the quirk of
135139
# strtobool() returning an integer in pip's configuration code).
136-
if has_pyproject and not has_setup:
140+
if editable and use_pep517:
141+
raise make_editable_error(
142+
req_name, 'PEP 517 processing was explicitly requested'
143+
)
144+
elif has_pyproject and not has_setup:
137145
if use_pep517 is not None and not use_pep517:
138146
raise InstallationError(
139147
"Disabling PEP 517 processing is invalid: "
@@ -145,26 +153,45 @@ def resolve_pyproject_toml(
145153
)
146154
use_pep517 = True
147155
elif build_system and "build-backend" in build_system:
148-
if use_pep517 is not None and not use_pep517:
156+
if editable:
157+
if use_pep517 is None:
158+
message = (
159+
'Error installing {!r}: editable mode is not supported '
160+
'for pyproject.toml-style projects. '
161+
'This project is pyproject.toml-style because it has a '
162+
'pyproject.toml file and a "build-backend" key for the '
163+
'"build_system" value, but editable mode is undefined '
164+
'for pyproject.toml-style projects. '
165+
'Since the project has a setup.py, you may pass '
166+
'--no-use-pep517 to opt out of pyproject.toml-style '
167+
'processing. However, this is an unsupported combination. '
168+
'See PEP 517 for details on pyproject.toml-style projects.'
169+
).format(req_name)
170+
raise InstallationError(message)
171+
172+
# The case of `editable and use_pep517` being true was already
173+
# handled above.
174+
assert not use_pep517
175+
message = (
176+
'Installing {!r} in editable mode, which is not supported '
177+
'for pyproject.toml-style projects: '
178+
'this project is pyproject.toml-style because it has a '
179+
'pyproject.toml file and a "build-backend" key for the '
180+
'"build_system" value, but editable mode is undefined '
181+
'for pyproject.toml-style projects. '
182+
'See PEP 517 for details on pyproject.toml-style projects.'
183+
).format(req_name)
184+
logger.warning(message)
185+
elif use_pep517 is not None and not use_pep517:
149186
raise InstallationError(
150187
"Disabling PEP 517 processing is invalid: "
151188
"project specifies a build backend of {} "
152189
"in pyproject.toml".format(
153190
build_system["build-backend"]
154191
)
155192
)
156-
if editable:
157-
reason = (
158-
'it has a pyproject.toml file with a "build-backend" key '
159-
'in the "build_system" value'
160-
)
161-
raise make_editable_error(req_name, reason)
162-
use_pep517 = True
163-
elif use_pep517:
164-
if editable:
165-
raise make_editable_error(
166-
req_name, 'PEP 517 processing was explicitly requested'
167-
)
193+
else:
194+
use_pep517 = True
168195

169196
# If we haven't worked out whether to use PEP 517 yet, and the user
170197
# hasn't explicitly stated a preference, we do so if the project has

tests/unit/test_pep517.py

+49-3
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ def test_resolve_pyproject_toml__editable_without_use_pep517_false():
8484
'has_pyproject, has_setup, use_pep517, build_system, expected_err', [
8585
# Test pyproject.toml with no setup.py.
8686
(True, False, None, None, 'has a pyproject.toml file and no setup.py'),
87-
# Test "build-backend" present.
88-
(True, True, None, {'build-backend': 'foo'},
89-
'has a pyproject.toml file with a "build-backend" key'),
9087
# Test explicitly requesting PEP 517 processing.
9188
(True, True, True, None,
9289
'PEP 517 processing was explicitly requested'),
@@ -115,6 +112,55 @@ def test_resolve_pyproject_toml__editable_and_pep_517_required(
115112
)
116113

117114

115+
def test_resolve_pyproject_toml__editable_build_backend_use_pep517_none():
116+
"""
117+
Test editable=True with "build-backend" and use_pep517=None.
118+
"""
119+
expected_start = (
120+
"Error installing 'my-package': editable mode is not supported "
121+
)
122+
expected_substr = 'you may pass --no-use-pep517 to opt out'
123+
124+
with assert_error_startswith(
125+
InstallationError, expected_start, expected_substr=expected_substr,
126+
):
127+
resolve_pyproject_toml(
128+
build_system={'requires': ['my-package'], 'build-backend': 'foo'},
129+
has_pyproject=True,
130+
has_setup=True,
131+
use_pep517=None,
132+
editable=True,
133+
req_name='my-package',
134+
)
135+
136+
137+
def test_resolve_pyproject_toml__editable_build_backend_use_pep517_false(
138+
caplog
139+
):
140+
"""
141+
Test editable=True with "build-backend" and use_pep517=False.
142+
"""
143+
resolve_pyproject_toml(
144+
build_system={'requires': ['my-package'], 'build-backend': 'foo'},
145+
has_pyproject=True,
146+
has_setup=True,
147+
use_pep517=False,
148+
editable=True,
149+
req_name='my-package',
150+
)
151+
152+
records = caplog.records
153+
assert len(records) == 1
154+
record = records[0]
155+
assert record.levelname == 'WARNING'
156+
expected_start = (
157+
"Installing 'my-package' in editable mode, which is not supported "
158+
)
159+
assert record.message.startswith(expected_start), (
160+
'full message: {}'.format(record.message)
161+
)
162+
163+
118164
@pytest.mark.parametrize(
119165
'has_pyproject, has_setup, use_pep517, editable, build_system, '
120166
'expected_err', [

0 commit comments

Comments
 (0)