2727from importlib import import_module
2828from importlib .abc import MetaPathFinder
2929from itertools import starmap
30- from typing import Any , cast
30+ from typing import Any
3131
3232from . import _meta
3333from ._collections import FreezableDefaultDict , Pair
3838from ._functools import method_cache , pass_none
3939from ._itertools import always_iterable , bucket , unique_everseen
4040from ._meta import PackageMetadata , SimplePath
41+ from ._typing import md_none
4142from .compat import py39 , py311
4243
4344__all__ = [
@@ -511,7 +512,7 @@ def _discover_resolvers():
511512 return filter (None , declared )
512513
513514 @property
514- def metadata (self ) -> _meta .PackageMetadata :
515+ def metadata (self ) -> _meta .PackageMetadata | None :
515516 """Return the parsed metadata for this Distribution.
516517
517518 The returned object will have keys that name the various bits of
@@ -521,24 +522,29 @@ def metadata(self) -> _meta.PackageMetadata:
521522 Custom providers may provide the METADATA file or override this
522523 property.
523524 """
524- # deferred for performance (python/cpython#109829)
525- from . import _adapters
526525
527- opt_text = (
526+ text = (
528527 self .read_text ('METADATA' )
529528 or self .read_text ('PKG-INFO' )
530529 # This last clause is here to support old egg-info files. Its
531530 # effect is to just end up using the PathDistribution's self._path
532531 # (which points to the egg-info file) attribute unchanged.
533532 or self .read_text ('' )
534533 )
535- text = cast (str , opt_text )
534+ return self ._assemble_message (text )
535+
536+ @staticmethod
537+ @pass_none
538+ def _assemble_message (text : str ) -> _meta .PackageMetadata :
539+ # deferred for performance (python/cpython#109829)
540+ from . import _adapters
541+
536542 return _adapters .Message (email .message_from_string (text ))
537543
538544 @property
539545 def name (self ) -> str :
540546 """Return the 'Name' metadata for the distribution package."""
541- return self .metadata ['Name' ]
547+ return md_none ( self .metadata ) ['Name' ]
542548
543549 @property
544550 def _normalized_name (self ):
@@ -548,7 +554,7 @@ def _normalized_name(self):
548554 @property
549555 def version (self ) -> str :
550556 """Return the 'Version' metadata for the distribution package."""
551- return self .metadata ['Version' ]
557+ return md_none ( self .metadata ) ['Version' ]
552558
553559 @property
554560 def entry_points (self ) -> EntryPoints :
@@ -1045,7 +1051,7 @@ def distributions(**kwargs) -> Iterable[Distribution]:
10451051 return Distribution .discover (** kwargs )
10461052
10471053
1048- def metadata (distribution_name : str ) -> _meta .PackageMetadata :
1054+ def metadata (distribution_name : str ) -> _meta .PackageMetadata | None :
10491055 """Get the metadata for the named package.
10501056
10511057 :param distribution_name: The name of the distribution package to query.
@@ -1120,7 +1126,7 @@ def packages_distributions() -> Mapping[str, list[str]]:
11201126 pkg_to_dist = collections .defaultdict (list )
11211127 for dist in distributions ():
11221128 for pkg in _top_level_declared (dist ) or _top_level_inferred (dist ):
1123- pkg_to_dist [pkg ].append (dist .metadata ['Name' ])
1129+ pkg_to_dist [pkg ].append (md_none ( dist .metadata ) ['Name' ])
11241130 return dict (pkg_to_dist )
11251131
11261132
0 commit comments