88from pathlib import Path
99from tempfile import NamedTemporaryFile , TemporaryDirectory
1010from time import sleep
11- from typing import Any , Dict , Iterator , List , NamedTuple , NoReturn , Optional , TypedDict , cast
11+ from typing import Any , Dict , Iterator , List , Literal , NamedTuple , NoReturn , Optional , TypedDict , cast
1212from zipfile import ZipFile
1313
1414from packaging .requirements import Requirement
@@ -314,7 +314,7 @@ def prepare_metadata_for_build_wheel(
314314 self ,
315315 metadata_directory : Path ,
316316 config_settings : ConfigSettings | None = None ,
317- ) -> MetadataForBuildWheelResult :
317+ ) -> MetadataForBuildWheelResult | None :
318318 """
319319 Build wheel metadata (per PEP-517).
320320
@@ -331,12 +331,10 @@ def prepare_metadata_for_build_wheel(
331331 config_settings = config_settings ,
332332 )
333333 if basename is None :
334- # if backend does not provide it acquire it from the wheel
335- basename , err , out = self ._metadata_from_built_wheel (config_settings , metadata_directory , "build_wheel" )
334+ return None
336335 if not isinstance (basename , str ):
337336 self ._unexpected_response ("prepare_metadata_for_build_wheel" , basename , str , out , err )
338- result = metadata_directory / basename
339- return MetadataForBuildWheelResult (result , out , err )
337+ return MetadataForBuildWheelResult (metadata_directory / basename , out , err )
340338
341339 def _check_metadata_dir (self , metadata_directory : Path ) -> None :
342340 if metadata_directory == self ._root :
@@ -350,7 +348,7 @@ def prepare_metadata_for_build_editable(
350348 self ,
351349 metadata_directory : Path ,
352350 config_settings : ConfigSettings | None = None ,
353- ) -> MetadataForBuildEditableResult :
351+ ) -> MetadataForBuildEditableResult | None :
354352 """
355353 Build editable wheel metadata (per PEP-660).
356354
@@ -359,16 +357,15 @@ def prepare_metadata_for_build_editable(
359357 :return: metadata generation result
360358 """
361359 self ._check_metadata_dir (metadata_directory )
362- basename = None
360+ basename : str | None = None
363361 if self .optional_hooks ["prepare_metadata_for_build_editable" ]:
364362 basename , out , err = self ._send (
365363 cmd = "prepare_metadata_for_build_editable" ,
366364 metadata_directory = metadata_directory ,
367365 config_settings = config_settings ,
368366 )
369367 if basename is None :
370- # if backend does not provide it acquire it from the wheel
371- basename , err , out = self ._metadata_from_built_wheel (config_settings , metadata_directory , "build_editable" )
368+ return None
372369 if not isinstance (basename , str ):
373370 self ._unexpected_response ("prepare_metadata_for_build_wheel" , basename , str , out , err )
374371 result = metadata_directory / basename
@@ -453,35 +450,41 @@ def _unexpected_response( # noqa: PLR0913
453450 msg = f"{ cmd !r} on { self .backend !r} returned { got !r} but expected type { expected_type !r} "
454451 raise BackendFailed ({"code" : None , "exc_type" : TypeError .__name__ , "exc_msg" : msg }, out , err )
455452
456- def _metadata_from_built_wheel (
453+ def metadata_from_built (
457454 self ,
458- config_settings : ConfigSettings | None ,
459- metadata_directory : Path | None ,
460- cmd : str ,
461- ) -> tuple [str , str , str ]:
455+ metadata_directory : Path ,
456+ target : Literal ["wheel" , "editable" ],
457+ config_settings : ConfigSettings | None = None ,
458+ ) -> tuple [Path , str , str ]:
459+ """
460+ Create metadata from building the wheel (use when the prepare endpoints are not present or don't work).
461+
462+ :param metadata_directory: directory where to put the metadata
463+ :param target: the type of wheel metadata to build
464+ :param config_settings: config settings to pass in to the build endpoint
465+ :return:
466+ """
467+ hook = getattr (self , f"build_{ target } " )
462468 with self ._wheel_directory () as wheel_directory :
463- wheel_result = getattr (self , cmd )(
464- wheel_directory = wheel_directory ,
465- config_settings = config_settings ,
466- metadata_directory = None , # let the backend populate the metadata
467- )
468- wheel = wheel_result .wheel
469+ result : EditableResult | WheelResult = hook (wheel_directory , config_settings )
470+ wheel = result .wheel
469471 if not wheel .exists ():
470472 msg = f"missing wheel file return by backed { wheel !r} "
471473 raise RuntimeError (msg )
472- out , err = wheel_result .out , wheel_result .err
474+ out , err = result .out , result .err
473475 extract_to = str (metadata_directory )
474476 basename = None
475477 with ZipFile (str (wheel ), "r" ) as zip_file :
476478 for name in zip_file .namelist (): # pragma: no branch
477- path = Path (name )
478- if path . parts [ 0 ] .endswith (".dist-info" ):
479- basename = path . parts [ 0 ]
479+ root = Path (name ). parts [ 0 ]
480+ if root .endswith (".dist-info" ):
481+ basename = root
480482 zip_file .extract (name , extract_to )
481- if basename is None : # pragma: no branch
482- msg = f"no .dist-info found inside generated wheel { wheel } "
483- raise RuntimeError (msg )
484- return basename , err , out
483+ break
484+ if basename is None : # pragma: no branch
485+ msg = f"no .dist-info found inside generated wheel { wheel } "
486+ raise RuntimeError (msg )
487+ return metadata_directory / basename , out , err
485488
486489 @contextmanager
487490 def _wheel_directory (self ) -> Iterator [Path ]:
0 commit comments