summaryrefslogtreecommitdiffstats
path: root/contrib/python/importlib-metadata
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2026-04-07 12:11:03 +0300
committerrobot-piglet <[email protected]>2026-04-07 12:45:12 +0300
commitcb7c61880689d4eac05f9bbd62f93e3415bcd3a8 (patch)
tree7434cb2c54d61c167e88404353b85b31ed32c89d /contrib/python/importlib-metadata
parent3061b022c1388744ef39a716bdc79353a302052a (diff)
Intermediate changes
commit_hash:6353c155f30593c41d7c32d53647f5e6ecfc845c
Diffstat (limited to 'contrib/python/importlib-metadata')
-rw-r--r--contrib/python/importlib-metadata/py3/.dist-info/METADATA2
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py36
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/_context.py118
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py15
-rw-r--r--contrib/python/importlib-metadata/py3/ya.make4
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