3131
3232from . import _meta
3333from ._collections import FreezableDefaultDict , Pair
34+ from ._context import ExceptionTrap
3435from ._functools import method_cache , noop , pass_none , passthrough
3536from ._itertools import always_iterable , bucket , unique_everseen
3637from ._meta import PackageMetadata , SimplePath
4243 'PackageMetadata' ,
4344 'PackageNotFoundError' ,
4445 'PackagePath' ,
46+ 'MetadataNotFound' ,
4547 'SimplePath' ,
4648 'distribution' ,
4749 'distributions' ,
@@ -66,6 +68,10 @@ def name(self) -> str: # type: ignore[override] # make readonly
6668 return name
6769
6870
71+ class MetadataNotFound (FileNotFoundError ):
72+ """No metadata file is present in the distribution."""
73+
74+
6975class Sectioned :
7076 """
7177 A simple entry point config parser for performance
@@ -487,7 +493,12 @@ def _prefer_valid(dists: Iterable[Distribution]) -> Iterable[Distribution]:
487493
488494 Ref python/importlib_resources#489.
489495 """
490- buckets = bucket (dists , lambda dist : bool (dist .metadata ))
496+
497+ has_metadata = ExceptionTrap (MetadataNotFound ).passes (
498+ operator .attrgetter ('metadata' )
499+ )
500+
501+ buckets = bucket (dists , has_metadata )
491502 return itertools .chain (buckets [True ], buckets [False ])
492503
493504 @staticmethod
@@ -508,7 +519,7 @@ def _discover_resolvers():
508519 return filter (None , declared )
509520
510521 @property
511- def metadata (self ) -> _meta .PackageMetadata | None :
522+ def metadata (self ) -> _meta .PackageMetadata :
512523 """Return the parsed metadata for this Distribution.
513524
514525 The returned object will have keys that name the various bits of
@@ -517,6 +528,8 @@ def metadata(self) -> _meta.PackageMetadata | None:
517528
518529 Custom providers may provide the METADATA file or override this
519530 property.
531+
532+ :raises MetadataNotFound: If no metadata file is present.
520533 """
521534
522535 text = (
@@ -527,20 +540,25 @@ def metadata(self) -> _meta.PackageMetadata | None:
527540 # (which points to the egg-info file) attribute unchanged.
528541 or self .read_text ('' )
529542 )
530- return self ._assemble_message (text )
543+ return self ._assemble_message (self . _ensure_metadata_present ( text ) )
531544
532545 @staticmethod
533- @pass_none
534546 def _assemble_message (text : str ) -> _meta .PackageMetadata :
535547 # deferred for performance (python/cpython#109829)
536548 from . import _adapters
537549
538550 return _adapters .Message (email .message_from_string (text ))
539551
552+ def _ensure_metadata_present (self , text : str | None ) -> str :
553+ if text is not None :
554+ return text
555+
556+ raise MetadataNotFound ('No package metadata was found.' )
557+
540558 @property
541559 def name (self ) -> str :
542560 """Return the 'Name' metadata for the distribution package."""
543- return md_none ( self .metadata ) ['Name' ]
561+ return self .metadata ['Name' ]
544562
545563 @property
546564 def _normalized_name (self ):
@@ -550,7 +568,7 @@ def _normalized_name(self):
550568 @property
551569 def version (self ) -> str :
552570 """Return the 'Version' metadata for the distribution package."""
553- return md_none ( self .metadata ) ['Version' ]
571+ return self .metadata ['Version' ]
554572
555573 @property
556574 def entry_points (self ) -> EntryPoints :
@@ -1063,11 +1081,12 @@ def distributions(**kwargs) -> Iterable[Distribution]:
10631081 return Distribution .discover (** kwargs )
10641082
10651083
1066- def metadata (distribution_name : str ) -> _meta .PackageMetadata | None :
1084+ def metadata (distribution_name : str ) -> _meta .PackageMetadata :
10671085 """Get the metadata for the named package.
10681086
10691087 :param distribution_name: The name of the distribution package to query.
10701088 :return: A PackageMetadata containing the parsed metadata.
1089+ :raises MetadataNotFound: If no metadata file is present in the distribution.
10711090 """
10721091 return Distribution .from_name (distribution_name ).metadata
10731092
@@ -1138,7 +1157,7 @@ def packages_distributions() -> Mapping[str, list[str]]:
11381157 pkg_to_dist = collections .defaultdict (list )
11391158 for dist in distributions ():
11401159 for pkg in _top_level_declared (dist ) or _top_level_inferred (dist ):
1141- pkg_to_dist [pkg ].append (md_none ( dist .metadata ) ['Name' ])
1160+ pkg_to_dist [pkg ].append (dist .metadata ['Name' ])
11421161 return dict (pkg_to_dist )
11431162
11441163
0 commit comments