@@ -59,6 +59,17 @@ class RequiresBuildWheelResult(NamedTuple):
59
59
err : str
60
60
61
61
62
+ class RequiresBuildEditableResult (NamedTuple ):
63
+ """Information collected while acquiring the wheel build dependencies"""
64
+
65
+ #: editable wheel build dependencies
66
+ requires : tuple [Requirement , ...]
67
+ #: backend standard output while acquiring the editable wheel build dependencies
68
+ out : str
69
+ #: backend standard error while acquiring the editable wheel build dependencies
70
+ err : str
71
+
72
+
62
73
class MetadataForBuildWheelResult (NamedTuple ):
63
74
"""Information collected while acquiring the wheel metadata"""
64
75
@@ -70,6 +81,17 @@ class MetadataForBuildWheelResult(NamedTuple):
70
81
err : str
71
82
72
83
84
+ class MetadataForBuildEditableResult (NamedTuple ):
85
+ """Information collected while acquiring the editable metadata"""
86
+
87
+ #: path to the wheel metadata
88
+ metadata : Path
89
+ #: backend standard output while generating the editable wheel metadata
90
+ out : str
91
+ #: backend standard output while generating the editable wheel metadata
92
+ err : str
93
+
94
+
73
95
class SdistResult (NamedTuple ):
74
96
"""Information collected while building a source distribution"""
75
97
@@ -92,6 +114,17 @@ class WheelResult(NamedTuple):
92
114
err : str
93
115
94
116
117
+ class EditableResult (NamedTuple ):
118
+ """Information collected while building an editable wheel"""
119
+
120
+ #: path to the built wheel artifact
121
+ wheel : Path
122
+ #: backend standard output while building the wheel
123
+ out : str
124
+ #: backend standard error while building the wheel
125
+ err : str
126
+
127
+
95
128
class BackendFailed (RuntimeError ):
96
129
"""An error of the build backend."""
97
130
@@ -240,6 +273,23 @@ def get_requires_for_build_wheel(self, config_settings: ConfigSettings | None =
240
273
self ._unexpected_response ("get_requires_for_build_wheel" , result , "list of string" , out , err )
241
274
return RequiresBuildWheelResult (tuple (Requirement (r ) for r in cast (List [str ], result )), out , err )
242
275
276
+ def get_requires_for_build_editable (
277
+ self , config_settings : ConfigSettings | None = None
278
+ ) -> RequiresBuildEditableResult :
279
+ """
280
+ Get build requirements for an editable wheel build (per PEP-660).
281
+
282
+ :param config_settings: run arguments
283
+ :return: outcome
284
+ """
285
+ try :
286
+ result , out , err = self ._send (cmd = "get_requires_for_build_editable" , config_settings = config_settings )
287
+ except BackendFailed as exc :
288
+ result , out , err = [], exc .out , exc .err
289
+ if not isinstance (result , list ) or not all (isinstance (i , str ) for i in result ):
290
+ self ._unexpected_response ("get_requires_for_build_editable" , result , "list of string" , out , err )
291
+ return RequiresBuildEditableResult (tuple (Requirement (r ) for r in cast (List [str ], result )), out , err )
292
+
243
293
def prepare_metadata_for_build_wheel (
244
294
self , metadata_directory : Path , config_settings : ConfigSettings | None = None
245
295
) -> MetadataForBuildWheelResult :
@@ -250,24 +300,52 @@ def prepare_metadata_for_build_wheel(
250
300
:param config_settings: build arguments
251
301
:return: metadata generation result
252
302
"""
303
+ self ._check_metadata_dir (metadata_directory )
304
+ try :
305
+ basename , out , err = self ._send (
306
+ cmd = "prepare_metadata_for_build_wheel" ,
307
+ metadata_directory = metadata_directory ,
308
+ config_settings = config_settings ,
309
+ )
310
+ except BackendFailed :
311
+ # if backend does not provide it acquire it from the wheel
312
+ basename , err , out = self ._metadata_from_built_wheel (config_settings , metadata_directory , "build_wheel" )
313
+ if not isinstance (basename , str ):
314
+ self ._unexpected_response ("prepare_metadata_for_build_wheel" , basename , str , out , err )
315
+ result = metadata_directory / basename
316
+ return MetadataForBuildWheelResult (result , out , err )
317
+
318
+ def _check_metadata_dir (self , metadata_directory : Path ) -> None :
253
319
if metadata_directory == self ._root :
254
320
raise RuntimeError (f"the project root and the metadata directory can't be the same { self ._root } " )
255
321
if metadata_directory .exists (): # start with fresh
256
322
ensure_empty_dir (metadata_directory )
257
323
metadata_directory .mkdir (parents = True , exist_ok = True )
324
+
325
+ def prepare_metadata_for_build_editable (
326
+ self , metadata_directory : Path , config_settings : ConfigSettings | None = None
327
+ ) -> MetadataForBuildEditableResult :
328
+ """
329
+ Build editable wheel metadata (per PEP-660).
330
+
331
+ :param metadata_directory: where to generate the metadata
332
+ :param config_settings: build arguments
333
+ :return: metadata generation result
334
+ """
335
+ self ._check_metadata_dir (metadata_directory )
258
336
try :
259
337
basename , out , err = self ._send (
260
- cmd = "prepare_metadata_for_build_wheel " ,
338
+ cmd = "prepare_metadata_for_build_editable " ,
261
339
metadata_directory = metadata_directory ,
262
340
config_settings = config_settings ,
263
341
)
264
342
except BackendFailed :
265
343
# if backend does not provide it acquire it from the wheel
266
- basename , err , out = self ._metadata_from_built_wheel (config_settings , metadata_directory )
344
+ basename , err , out = self ._metadata_from_built_wheel (config_settings , metadata_directory , "build_editable" )
267
345
if not isinstance (basename , str ):
268
346
self ._unexpected_response ("prepare_metadata_for_build_wheel" , basename , str , out , err )
269
347
result = metadata_directory / basename
270
- return MetadataForBuildWheelResult (result , out , err )
348
+ return MetadataForBuildEditableResult (result , out , err )
271
349
272
350
def build_sdist (self , sdist_directory : Path , config_settings : ConfigSettings | None = None ) -> SdistResult :
273
351
"""
@@ -294,7 +372,7 @@ def build_wheel(
294
372
metadata_directory : Path | None = None ,
295
373
) -> WheelResult :
296
374
"""
297
- Build a source distribution (per PEP-517).
375
+ Build a wheel file (per PEP-517).
298
376
299
377
:param wheel_directory: the folder where to build the wheel
300
378
:param config_settings: build arguments
@@ -312,15 +390,40 @@ def build_wheel(
312
390
self ._unexpected_response ("build_wheel" , basename , str , out , err )
313
391
return WheelResult (wheel_directory / basename , out , err )
314
392
393
+ def build_editable (
394
+ self ,
395
+ wheel_directory : Path ,
396
+ config_settings : ConfigSettings | None = None ,
397
+ metadata_directory : Path | None = None ,
398
+ ) -> EditableResult :
399
+ """
400
+ Build an editable wheel file (per PEP-660).
401
+
402
+ :param wheel_directory: the folder where to build the editable wheel
403
+ :param config_settings: build arguments
404
+ :param metadata_directory: wheel metadata folder
405
+ :return: wheel build result
406
+ """
407
+ wheel_directory .mkdir (parents = True , exist_ok = True )
408
+ basename , out , err = self ._send (
409
+ cmd = "build_editable" ,
410
+ wheel_directory = wheel_directory ,
411
+ config_settings = config_settings ,
412
+ metadata_directory = metadata_directory ,
413
+ )
414
+ if not isinstance (basename , str ):
415
+ self ._unexpected_response ("build_editable" , basename , str , out , err )
416
+ return EditableResult (wheel_directory / basename , out , err )
417
+
315
418
def _unexpected_response (self , cmd : str , got : Any , expected_type : Any , out : str , err : str ) -> NoReturn :
316
419
msg = f"{ cmd !r} on { self .backend !r} returned { got !r} but expected type { expected_type !r} "
317
420
raise BackendFailed ({"code" : None , "exc_type" : TypeError .__name__ , "exc_msg" : msg }, out , err )
318
421
319
422
def _metadata_from_built_wheel (
320
- self , config_settings : ConfigSettings | None , metadata_directory : Path | None
423
+ self , config_settings : ConfigSettings | None , metadata_directory : Path | None , cmd : str
321
424
) -> tuple [str , str , str ]:
322
425
with self ._wheel_directory () as wheel_directory :
323
- wheel_result = self . build_wheel (
426
+ wheel_result = getattr ( self , cmd ) (
324
427
wheel_directory = wheel_directory ,
325
428
config_settings = config_settings ,
326
429
metadata_directory = metadata_directory ,
0 commit comments