3535 NullFinder ,
3636 install ,
3737)
38+ from ._context import ExceptionTrap
3839from ._functools import method_cache , noop , pass_none , passthrough
3940from ._itertools import always_iterable , bucket , unique_everseen
4041from ._meta import PackageMetadata , SimplePath
41- from ._typing import md_none
4242from .compat import py311
4343
4444__all__ = [
4545 'Distribution' ,
4646 'DistributionFinder' ,
4747 'PackageMetadata' ,
4848 'PackageNotFoundError' ,
49+ 'MetadataNotFound' ,
4950 'SimplePath' ,
5051 'distribution' ,
5152 'distributions' ,
@@ -70,6 +71,10 @@ def name(self) -> str: # type: ignore[override] # make readonly
7071 return name
7172
7273
74+ class MetadataNotFound (FileNotFoundError ):
75+ """No metadata file is present in the distribution."""
76+
77+
7378class Sectioned :
7479 """
7580 A simple entry point config parser for performance
@@ -491,7 +496,12 @@ def _prefer_valid(dists: Iterable[Distribution]) -> Iterable[Distribution]:
491496
492497 Ref python/importlib_resources#489.
493498 """
494- buckets = bucket (dists , lambda dist : bool (dist .metadata ))
499+
500+ has_metadata = ExceptionTrap (MetadataNotFound ).passes (
501+ operator .attrgetter ('metadata' )
502+ )
503+
504+ buckets = bucket (dists , has_metadata )
495505 return itertools .chain (buckets [True ], buckets [False ])
496506
497507 @staticmethod
@@ -512,7 +522,7 @@ def _discover_resolvers():
512522 return filter (None , declared )
513523
514524 @property
515- def metadata (self ) -> _meta .PackageMetadata | None :
525+ def metadata (self ) -> _meta .PackageMetadata :
516526 """Return the parsed metadata for this Distribution.
517527
518528 The returned object will have keys that name the various bits of
@@ -521,6 +531,8 @@ def metadata(self) -> _meta.PackageMetadata | None:
521531
522532 Custom providers may provide the METADATA file or override this
523533 property.
534+
535+ :raises MetadataNotFound: If no metadata file is present.
524536 """
525537
526538 text = (
@@ -531,20 +543,25 @@ def metadata(self) -> _meta.PackageMetadata | None:
531543 # (which points to the egg-info file) attribute unchanged.
532544 or self .read_text ('' )
533545 )
534- return self ._assemble_message (text )
546+ return self ._assemble_message (self . _ensure_metadata_present ( text ) )
535547
536548 @staticmethod
537- @pass_none
538549 def _assemble_message (text : str ) -> _meta .PackageMetadata :
539550 # deferred for performance (python/cpython#109829)
540551 from . import _adapters
541552
542553 return _adapters .Message (email .message_from_string (text ))
543554
555+ def _ensure_metadata_present (self , text : str | None ) -> str :
556+ if text is not None :
557+ return text
558+
559+ raise MetadataNotFound ('No package metadata was found.' )
560+
544561 @property
545562 def name (self ) -> str :
546563 """Return the 'Name' metadata for the distribution package."""
547- return md_none ( self .metadata ) ['Name' ]
564+ return self .metadata ['Name' ]
548565
549566 @property
550567 def _normalized_name (self ):
@@ -554,7 +571,7 @@ def _normalized_name(self):
554571 @property
555572 def version (self ) -> str :
556573 """Return the 'Version' metadata for the distribution package."""
557- return md_none ( self .metadata ) ['Version' ]
574+ return self .metadata ['Version' ]
558575
559576 @property
560577 def entry_points (self ) -> EntryPoints :
@@ -1067,11 +1084,12 @@ def distributions(**kwargs) -> Iterable[Distribution]:
10671084 return Distribution .discover (** kwargs )
10681085
10691086
1070- def metadata (distribution_name : str ) -> _meta .PackageMetadata | None :
1087+ def metadata (distribution_name : str ) -> _meta .PackageMetadata :
10711088 """Get the metadata for the named package.
10721089
10731090 :param distribution_name: The name of the distribution package to query.
10741091 :return: A PackageMetadata containing the parsed metadata.
1092+ :raises MetadataNotFound: If no metadata file is present in the distribution.
10751093 """
10761094 return Distribution .from_name (distribution_name ).metadata
10771095
@@ -1142,7 +1160,7 @@ def packages_distributions() -> Mapping[str, list[str]]:
11421160 pkg_to_dist = collections .defaultdict (list )
11431161 for dist in distributions ():
11441162 for pkg in _top_level_declared (dist ) or _top_level_inferred (dist ):
1145- pkg_to_dist [pkg ].append (md_none ( dist .metadata ) ['Name' ])
1163+ pkg_to_dist [pkg ].append (dist .metadata ['Name' ])
11461164 return dict (pkg_to_dist )
11471165
11481166
0 commit comments