12
12
if MYPY_CHECK_RUNNING :
13
13
from typing import Any , Dict , List , Optional , Tuple
14
14
15
+ Pep517Data = Tuple [str , List [str ]]
16
+
15
17
16
18
def _is_list_of_str (obj ):
17
19
# type: (Any) -> bool
@@ -64,6 +66,37 @@ def make_editable_error(req_name, reason):
64
66
return InstallationError (message )
65
67
66
68
69
+ def get_build_system_requires (build_system , req_name ):
70
+ if build_system is None :
71
+ return None
72
+
73
+ # Ensure that the build-system section in pyproject.toml conforms
74
+ # to PEP 518.
75
+ error_template = (
76
+ "{package} has a pyproject.toml file that does not comply "
77
+ "with PEP 518: {reason}"
78
+ )
79
+
80
+ # Specifying the build-system table but not the requires key is invalid
81
+ if "requires" not in build_system :
82
+ raise InstallationError (
83
+ error_template .format (package = req_name , reason = (
84
+ "it has a 'build-system' table but not "
85
+ "'build-system.requires' which is mandatory in the table"
86
+ ))
87
+ )
88
+
89
+ # Error out if requires is not a list of strings
90
+ requires = build_system ["requires" ]
91
+ if not _is_list_of_str (requires ):
92
+ raise InstallationError (error_template .format (
93
+ package = req_name ,
94
+ reason = "'build-system.requires' is not a list of strings." ,
95
+ ))
96
+
97
+ return requires
98
+
99
+
67
100
def resolve_pyproject_toml (
68
101
build_system , # type: Optional[Dict[str, Any]]
69
102
has_pyproject , # type: bool
@@ -72,7 +105,7 @@ def resolve_pyproject_toml(
72
105
editable , # type: bool
73
106
req_name , # type: str
74
107
):
75
- # type: (...) -> Optional[ Tuple[List[str], str, List[str] ]]
108
+ # type: (...) -> Tuple[Optional[ List[str]], Optional[Pep517Data ]]
76
109
"""
77
110
Return how a pyproject.toml file's contents should be interpreted.
78
111
@@ -86,6 +119,13 @@ def resolve_pyproject_toml(
86
119
:param editable: whether editable mode was requested for the requirement.
87
120
:param req_name: the name of the requirement we're processing (for
88
121
error reporting).
122
+
123
+ :return: a tuple (requires, pep517_data), where `requires` is the list
124
+ of build requirements from pyproject.toml (or else None). The value
125
+ `pep517_data` is None if `use_pep517` is False. Otherwise, it is the
126
+ tuple (backend, check), where `backend` is the name of the PEP 517
127
+ backend and `check` is the list of requirements we should check are
128
+ installed after setting up the build environment.
89
129
"""
90
130
# The following cases must use PEP 517
91
131
# We check for use_pep517 being non-None and falsey because that means
@@ -126,19 +166,34 @@ def resolve_pyproject_toml(
126
166
req_name , 'PEP 517 processing was explicitly requested'
127
167
)
128
168
129
- # If we haven't worked out whether to use PEP 517 yet,
130
- # and the user hasn't explicitly stated a preference,
131
- # we do so if the project has a pyproject.toml file.
169
+ # If we haven't worked out whether to use PEP 517 yet, and the user
170
+ # hasn't explicitly stated a preference, we do so if the project has
171
+ # a pyproject.toml file (provided editable mode wasn't requested) .
132
172
elif use_pep517 is None :
173
+ if has_pyproject and editable :
174
+ message = (
175
+ 'Error installing {!r}: editable mode is not supported for '
176
+ 'pyproject.toml-style projects. pip is processing this '
177
+ 'project as pyproject.toml-style because it has a '
178
+ 'pyproject.toml file. Since the project has a setup.py and '
179
+ 'the pyproject.toml has no "build-backend" key for the '
180
+ '"build_system" value, you may pass --no-use-pep517 to opt '
181
+ 'out of pyproject.toml-style processing. '
182
+ 'See PEP 517 for details on pyproject.toml-style projects.'
183
+ ).format (req_name )
184
+ raise InstallationError (message )
185
+
133
186
use_pep517 = has_pyproject
134
187
135
188
# At this point, we know whether we're going to use PEP 517.
136
189
assert use_pep517 is not None
137
190
191
+ requires = get_build_system_requires (build_system , req_name = req_name )
192
+
138
193
# If we're using the legacy code path, there is nothing further
139
194
# for us to do here.
140
195
if not use_pep517 :
141
- return None
196
+ return ( requires , None )
142
197
143
198
if build_system is None :
144
199
# Either the user has a pyproject.toml with no build-system
@@ -149,8 +204,8 @@ def resolve_pyproject_toml(
149
204
# traditional direct setup.py execution, and require wheel and
150
205
# a version of setuptools that supports that backend.
151
206
207
+ requires = ["setuptools>=40.8.0" , "wheel" ]
152
208
build_system = {
153
- "requires" : ["setuptools>=40.8.0" , "wheel" ],
154
209
"build-backend" : "setuptools.build_meta:__legacy__" ,
155
210
}
156
211
@@ -160,30 +215,6 @@ def resolve_pyproject_toml(
160
215
# specified a backend, though.
161
216
assert build_system is not None
162
217
163
- # Ensure that the build-system section in pyproject.toml conforms
164
- # to PEP 518.
165
- error_template = (
166
- "{package} has a pyproject.toml file that does not comply "
167
- "with PEP 518: {reason}"
168
- )
169
-
170
- # Specifying the build-system table but not the requires key is invalid
171
- if "requires" not in build_system :
172
- raise InstallationError (
173
- error_template .format (package = req_name , reason = (
174
- "it has a 'build-system' table but not "
175
- "'build-system.requires' which is mandatory in the table"
176
- ))
177
- )
178
-
179
- # Error out if requires is not a list of strings
180
- requires = build_system ["requires" ]
181
- if not _is_list_of_str (requires ):
182
- raise InstallationError (error_template .format (
183
- package = req_name ,
184
- reason = "'build-system.requires' is not a list of strings." ,
185
- ))
186
-
187
218
backend = build_system .get ("build-backend" )
188
219
check = [] # type: List[str]
189
220
if backend is None :
@@ -202,7 +233,7 @@ def resolve_pyproject_toml(
202
233
backend = "setuptools.build_meta:__legacy__"
203
234
check = ["setuptools>=40.8.0" , "wheel" ]
204
235
205
- return (requires , backend , check )
236
+ return (requires , ( backend , check ) )
206
237
207
238
208
239
def load_pyproject_toml (
@@ -212,7 +243,7 @@ def load_pyproject_toml(
212
243
setup_py , # type: str
213
244
req_name # type: str
214
245
):
215
- # type: (...) -> Optional[ Tuple[List[str], str, List[str] ]]
246
+ # type: (...) -> Tuple[Optional[ List[str]], Optional[Pep517Data ]]
216
247
"""Load the pyproject.toml file.
217
248
218
249
Parameters:
@@ -224,13 +255,13 @@ def load_pyproject_toml(
224
255
req_name - The name of the requirement we're processing (for
225
256
error reporting)
226
257
227
- Returns:
228
- None if we should use the legacy code path, otherwise a tuple
258
+ Returns: (requires, pep_517_data)
259
+ requires: requirements from pyproject.toml (can be None).
260
+ pep_517_data: None if we should use the legacy code path, otherwise:
229
261
(
230
- requirements from pyproject.toml,
231
262
name of PEP 517 backend,
232
- requirements we should check are installed after setting
233
- up the build environment
263
+ requirements we should check are installed after setting up
264
+ the build environment
234
265
)
235
266
"""
236
267
has_pyproject = os .path .isfile (pyproject_toml )
0 commit comments