diff options
| author | robot-piglet <[email protected]> | 2026-04-07 12:11:03 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2026-04-07 12:45:12 +0300 |
| commit | cb7c61880689d4eac05f9bbd62f93e3415bcd3a8 (patch) | |
| tree | 7434cb2c54d61c167e88404353b85b31ed32c89d /contrib/python/importlib-metadata | |
| parent | 3061b022c1388744ef39a716bdc79353a302052a (diff) | |
Intermediate changes
commit_hash:6353c155f30593c41d7c32d53647f5e6ecfc845c
Diffstat (limited to 'contrib/python/importlib-metadata')
5 files changed, 148 insertions, 27 deletions
diff --git a/contrib/python/importlib-metadata/py3/.dist-info/METADATA b/contrib/python/importlib-metadata/py3/.dist-info/METADATA index 98dfda37bc4..bfffd7236c6 100644 --- a/contrib/python/importlib-metadata/py3/.dist-info/METADATA +++ b/contrib/python/importlib-metadata/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: importlib_metadata -Version: 8.8.0 +Version: 9.0.0 Summary: Read metadata from Python packages Author-email: "Jason R. Coombs" <[email protected]> License-Expression: Apache-2.0 diff --git a/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py b/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py index 46d8b7c5ac2..59736c07abf 100644 --- a/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py +++ b/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py @@ -35,10 +35,10 @@ from ._compat import ( NullFinder, install, ) +from ._context import ExceptionTrap from ._functools import method_cache, noop, pass_none, passthrough from ._itertools import always_iterable, bucket, unique_everseen from ._meta import PackageMetadata, SimplePath -from ._typing import md_none from .compat import py311 __all__ = [ @@ -46,6 +46,7 @@ __all__ = [ 'DistributionFinder', 'PackageMetadata', 'PackageNotFoundError', + 'MetadataNotFound', 'SimplePath', 'distribution', 'distributions', @@ -76,6 +77,10 @@ class PackageNotFoundError(ModuleNotFoundError): return name +class MetadataNotFound(FileNotFoundError): + """No metadata file is present in the distribution.""" + + class Sectioned: """ A simple entry point config parser for performance @@ -497,7 +502,12 @@ class Distribution(metaclass=abc.ABCMeta): Ref python/importlib_resources#489. """ - buckets = bucket(dists, lambda dist: bool(dist.metadata)) + + has_metadata = ExceptionTrap(MetadataNotFound).passes( + operator.attrgetter('metadata') + ) + + buckets = bucket(dists, has_metadata) return itertools.chain(buckets[True], buckets[False]) @staticmethod @@ -518,7 +528,7 @@ class Distribution(metaclass=abc.ABCMeta): return filter(None, declared) @property - def metadata(self) -> _meta.PackageMetadata | None: + def metadata(self) -> _meta.PackageMetadata: """Return the parsed metadata for this Distribution. The returned object will have keys that name the various bits of @@ -527,6 +537,8 @@ class Distribution(metaclass=abc.ABCMeta): Custom providers may provide the METADATA file or override this property. + + :raises MetadataNotFound: If no metadata file is present. """ text = ( @@ -537,20 +549,25 @@ class Distribution(metaclass=abc.ABCMeta): # (which points to the egg-info file) attribute unchanged. or self.read_text('') ) - return self._assemble_message(text) + return self._assemble_message(self._ensure_metadata_present(text)) @staticmethod - @pass_none def _assemble_message(text: str) -> _meta.PackageMetadata: # deferred for performance (python/cpython#109829) from . import _adapters return _adapters.Message(email.message_from_string(text)) + def _ensure_metadata_present(self, text: str | None) -> str: + if text is not None: + return text + + raise MetadataNotFound('No package metadata was found.') + @property def name(self) -> str: """Return the 'Name' metadata for the distribution package.""" - return md_none(self.metadata)['Name'] + return self.metadata['Name'] @property def _normalized_name(self): @@ -560,7 +577,7 @@ class Distribution(metaclass=abc.ABCMeta): @property def version(self) -> str: """Return the 'Version' metadata for the distribution package.""" - return md_none(self.metadata)['Version'] + return self.metadata['Version'] @property def entry_points(self) -> EntryPoints: @@ -1126,11 +1143,12 @@ def distributions(**kwargs) -> Iterable[Distribution]: return Distribution.discover(**kwargs) -def metadata(distribution_name: str) -> _meta.PackageMetadata | None: +def metadata(distribution_name: str) -> _meta.PackageMetadata: """Get the metadata for the named package. :param distribution_name: The name of the distribution package to query. :return: A PackageMetadata containing the parsed metadata. + :raises MetadataNotFound: If no metadata file is present in the distribution. """ return Distribution.from_name(distribution_name).metadata @@ -1201,7 +1219,7 @@ def packages_distributions() -> Mapping[str, list[str]]: pkg_to_dist = collections.defaultdict(list) for dist in distributions(): for pkg in _top_level_declared(dist) or _top_level_inferred(dist): - pkg_to_dist[pkg].append(md_none(dist.metadata)['Name']) + pkg_to_dist[pkg].append(dist.metadata['Name']) return dict(pkg_to_dist) diff --git a/contrib/python/importlib-metadata/py3/importlib_metadata/_context.py b/contrib/python/importlib-metadata/py3/importlib_metadata/_context.py new file mode 100644 index 00000000000..2635b164ce8 --- /dev/null +++ b/contrib/python/importlib-metadata/py3/importlib_metadata/_context.py @@ -0,0 +1,118 @@ +from __future__ import annotations + +import functools +import operator + + +# from jaraco.context 6.1 +class ExceptionTrap: + """ + A context manager that will catch certain exceptions and provide an + indication they occurred. + + >>> with ExceptionTrap() as trap: + ... raise Exception() + >>> bool(trap) + True + + >>> with ExceptionTrap() as trap: + ... pass + >>> bool(trap) + False + + >>> with ExceptionTrap(ValueError) as trap: + ... raise ValueError("1 + 1 is not 3") + >>> bool(trap) + True + >>> trap.value + ValueError('1 + 1 is not 3') + >>> trap.tb + <traceback object at ...> + + >>> with ExceptionTrap(ValueError) as trap: + ... raise Exception() + Traceback (most recent call last): + ... + Exception + + >>> bool(trap) + False + """ + + exc_info = None, None, None + + def __init__(self, exceptions=(Exception,)): + self.exceptions = exceptions + + def __enter__(self): + return self + + @property + def type(self): + return self.exc_info[0] + + @property + def value(self): + return self.exc_info[1] + + @property + def tb(self): + return self.exc_info[2] + + def __exit__(self, *exc_info): + type = exc_info[0] + matches = type and issubclass(type, self.exceptions) + if matches: + self.exc_info = exc_info + return matches + + def __bool__(self): + return bool(self.type) + + def raises(self, func, *, _test=bool): + """ + Wrap func and replace the result with the truth + value of the trap (True if an exception occurred). + + First, give the decorator an alias to support Python 3.8 + Syntax. + + >>> raises = ExceptionTrap(ValueError).raises + + Now decorate a function that always fails. + + >>> @raises + ... def fail(): + ... raise ValueError('failed') + >>> fail() + True + """ + + @functools.wraps(func) + def wrapper(*args, **kwargs): + with ExceptionTrap(self.exceptions) as trap: + func(*args, **kwargs) + return _test(trap) + + return wrapper + + def passes(self, func): + """ + Wrap func and replace the result with the truth + value of the trap (True if no exception). + + First, give the decorator an alias to support Python 3.8 + Syntax. + + >>> passes = ExceptionTrap(ValueError).passes + + Now decorate a function that always fails. + + >>> @passes + ... def fail(): + ... raise ValueError('failed') + + >>> fail() + False + """ + return self.raises(func, _test=operator.not_) diff --git a/contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py b/contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py deleted file mode 100644 index 32b1d2b98ac..00000000000 --- a/contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py +++ /dev/null @@ -1,15 +0,0 @@ -import functools -import typing - -from ._meta import PackageMetadata - -md_none = functools.partial(typing.cast, PackageMetadata) -""" -Suppress type errors for optional metadata. - -Although Distribution.metadata can return None when metadata is corrupt -and thus None, allow callers to assume it's not None and crash if -that's the case. - -# python/importlib_metadata#493 -""" diff --git a/contrib/python/importlib-metadata/py3/ya.make b/contrib/python/importlib-metadata/py3/ya.make index 2f053d3c048..4822537e63a 100644 --- a/contrib/python/importlib-metadata/py3/ya.make +++ b/contrib/python/importlib-metadata/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(8.8.0) +VERSION(9.0.0) LICENSE(Apache-2.0) @@ -14,11 +14,11 @@ PY_SRCS( importlib_metadata/_adapters.py importlib_metadata/_collections.py importlib_metadata/_compat.py + importlib_metadata/_context.py importlib_metadata/_functools.py importlib_metadata/_itertools.py importlib_metadata/_meta.py importlib_metadata/_text.py - importlib_metadata/_typing.py importlib_metadata/compat/__init__.py importlib_metadata/compat/py311.py importlib_metadata/diagnose.py |
