summaryrefslogtreecommitdiffstats
path: root/contrib/python
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2025-05-12 10:40:00 +0300
committerrobot-piglet <[email protected]>2025-05-12 10:50:44 +0300
commit3828d7ccd94bdcdb1515d956d96f5050b158f3f4 (patch)
tree7090aafadb84c91a6bef3213bf562efe1256401b /contrib/python
parentc9bc4600b34d872d3c33a9a6b4164b1fbd0cca88 (diff)
Intermediate changes
commit_hash:c5767cc2625ee5d7a34bd8cade5a63abc114ae18
Diffstat (limited to 'contrib/python')
-rw-r--r--contrib/python/importlib-metadata/py3/.dist-info/METADATA7
-rw-r--r--contrib/python/importlib-metadata/py3/README.rst2
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py117
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/_collections.py6
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/_meta.py20
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py15
-rw-r--r--contrib/python/importlib-metadata/py3/importlib_metadata/compat/py39.py12
-rw-r--r--contrib/python/importlib-metadata/py3/ya.make3
8 files changed, 124 insertions, 58 deletions
diff --git a/contrib/python/importlib-metadata/py3/.dist-info/METADATA b/contrib/python/importlib-metadata/py3/.dist-info/METADATA
index b5a602cbff7..3df5c095d7b 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.2
+Metadata-Version: 2.4
Name: importlib_metadata
-Version: 8.6.1
+Version: 8.7.0
Summary: Read metadata from Python packages
Author-email: "Jason R. Coombs" <[email protected]>
Project-URL: Source, https://github.com/python/importlib_metadata
@@ -39,6 +39,7 @@ Provides-Extra: enabler
Requires-Dist: pytest-enabler>=2.2; extra == "enabler"
Provides-Extra: type
Requires-Dist: pytest-mypy; extra == "type"
+Dynamic: license-file
.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg
:target: https://pypi.org/project/importlib_metadata
@@ -56,7 +57,7 @@ Requires-Dist: pytest-mypy; extra == "type"
.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest
:target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest
-.. image:: https://img.shields.io/badge/skeleton-2024-informational
+.. image:: https://img.shields.io/badge/skeleton-2025-informational
:target: https://blog.jaraco.com/skeleton
.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata
diff --git a/contrib/python/importlib-metadata/py3/README.rst b/contrib/python/importlib-metadata/py3/README.rst
index ffb63387999..a9e634f2247 100644
--- a/contrib/python/importlib-metadata/py3/README.rst
+++ b/contrib/python/importlib-metadata/py3/README.rst
@@ -14,7 +14,7 @@
.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest
:target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest
-.. image:: https://img.shields.io/badge/skeleton-2024-informational
+.. image:: https://img.shields.io/badge/skeleton-2025-informational
:target: https://blog.jaraco.com/skeleton
.. image:: https://tidelift.com/badges/package/pypi/importlib-metadata
diff --git a/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py b/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py
index 0d20b12eae0..deb057b5d50 100644
--- a/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py
+++ b/contrib/python/importlib-metadata/py3/importlib_metadata/__init__.py
@@ -22,11 +22,12 @@ import re
import sys
import textwrap
import types
+from collections.abc import Iterable, Mapping
from contextlib import suppress
from importlib import import_module
from importlib.abc import MetaPathFinder
from itertools import starmap
-from typing import Any, Iterable, List, Mapping, Match, Optional, Set, cast
+from typing import Any
from . import _meta
from ._collections import FreezableDefaultDict, Pair
@@ -37,6 +38,7 @@ from ._compat import (
from ._functools import method_cache, pass_none
from ._itertools import always_iterable, bucket, unique_everseen
from ._meta import PackageMetadata, SimplePath
+from ._typing import md_none
from .compat import py39, py311
__all__ = [
@@ -139,6 +141,12 @@ class Sectioned:
return line and not line.startswith('#')
+class _EntryPointMatch(types.SimpleNamespace):
+ module: str
+ attr: str
+ extras: str
+
+
class EntryPoint:
"""An entry point as defined by Python packaging conventions.
@@ -154,6 +162,30 @@ class EntryPoint:
'attr'
>>> ep.extras
['extra1', 'extra2']
+
+ If the value package or module are not valid identifiers, a
+ ValueError is raised on access.
+
+ >>> EntryPoint(name=None, group=None, value='invalid-name').module
+ Traceback (most recent call last):
+ ...
+ ValueError: ('Invalid object reference...invalid-name...
+ >>> EntryPoint(name=None, group=None, value='invalid-name').attr
+ Traceback (most recent call last):
+ ...
+ ValueError: ('Invalid object reference...invalid-name...
+ >>> EntryPoint(name=None, group=None, value='invalid-name').extras
+ Traceback (most recent call last):
+ ...
+ ValueError: ('Invalid object reference...invalid-name...
+
+ The same thing happens on construction.
+
+ >>> EntryPoint(name=None, group=None, value='invalid-name')
+ Traceback (most recent call last):
+ ...
+ ValueError: ('Invalid object reference...invalid-name...
+
"""
pattern = re.compile(
@@ -181,38 +213,44 @@ class EntryPoint:
value: str
group: str
- dist: Optional[Distribution] = None
+ dist: Distribution | None = None
def __init__(self, name: str, value: str, group: str) -> None:
vars(self).update(name=name, value=value, group=group)
+ self.module
def load(self) -> Any:
"""Load the entry point from its definition. If only a module
is indicated by the value, return that module. Otherwise,
return the named object.
"""
- match = cast(Match, self.pattern.match(self.value))
- module = import_module(match.group('module'))
- attrs = filter(None, (match.group('attr') or '').split('.'))
+ module = import_module(self.module)
+ attrs = filter(None, (self.attr or '').split('.'))
return functools.reduce(getattr, attrs, module)
@property
def module(self) -> str:
- match = self.pattern.match(self.value)
- assert match is not None
- return match.group('module')
+ return self._match.module
@property
def attr(self) -> str:
- match = self.pattern.match(self.value)
- assert match is not None
- return match.group('attr')
+ return self._match.attr
@property
- def extras(self) -> List[str]:
+ def extras(self) -> list[str]:
+ return re.findall(r'\w+', self._match.extras or '')
+
+ @functools.cached_property
+ def _match(self) -> _EntryPointMatch:
match = self.pattern.match(self.value)
- assert match is not None
- return re.findall(r'\w+', match.group('extras') or '')
+ if not match:
+ raise ValueError(
+ 'Invalid object reference. '
+ 'See https://packaging.python.org'
+ '/en/latest/specifications/entry-points/#data-model',
+ self.value,
+ )
+ return _EntryPointMatch(**match.groupdict())
def _for(self, dist):
vars(self).update(dist=dist)
@@ -311,14 +349,14 @@ class EntryPoints(tuple):
return EntryPoints(ep for ep in self if py39.ep_matches(ep, **params))
@property
- def names(self) -> Set[str]:
+ def names(self) -> set[str]:
"""
Return the set of all names of all entry points.
"""
return {ep.name for ep in self}
@property
- def groups(self) -> Set[str]:
+ def groups(self) -> set[str]:
"""
Return the set of all groups of all entry points.
"""
@@ -339,7 +377,7 @@ class EntryPoints(tuple):
class PackagePath(pathlib.PurePosixPath):
"""A reference to a path in a package"""
- hash: Optional[FileHash]
+ hash: FileHash | None
size: int
dist: Distribution
@@ -374,7 +412,7 @@ class Distribution(metaclass=abc.ABCMeta):
"""
@abc.abstractmethod
- def read_text(self, filename) -> Optional[str]:
+ def read_text(self, filename) -> str | None:
"""Attempt to load metadata file given by the name.
Python distribution metadata is organized by blobs of text
@@ -434,7 +472,7 @@ class Distribution(metaclass=abc.ABCMeta):
@classmethod
def discover(
- cls, *, context: Optional[DistributionFinder.Context] = None, **kwargs
+ cls, *, context: DistributionFinder.Context | None = None, **kwargs
) -> Iterable[Distribution]:
"""Return an iterable of Distribution objects for all packages.
@@ -480,7 +518,7 @@ class Distribution(metaclass=abc.ABCMeta):
return filter(None, declared)
@property
- def metadata(self) -> _meta.PackageMetadata:
+ def metadata(self) -> _meta.PackageMetadata | None:
"""Return the parsed metadata for this Distribution.
The returned object will have keys that name the various bits of
@@ -490,10 +528,8 @@ class Distribution(metaclass=abc.ABCMeta):
Custom providers may provide the METADATA file or override this
property.
"""
- # deferred for performance (python/cpython#109829)
- from . import _adapters
- opt_text = (
+ text = (
self.read_text('METADATA')
or self.read_text('PKG-INFO')
# This last clause is here to support old egg-info files. Its
@@ -501,13 +537,20 @@ class Distribution(metaclass=abc.ABCMeta):
# (which points to the egg-info file) attribute unchanged.
or self.read_text('')
)
- text = cast(str, opt_text)
+ return self._assemble_message(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))
@property
def name(self) -> str:
"""Return the 'Name' metadata for the distribution package."""
- return self.metadata['Name']
+ return md_none(self.metadata)['Name']
@property
def _normalized_name(self):
@@ -517,7 +560,7 @@ class Distribution(metaclass=abc.ABCMeta):
@property
def version(self) -> str:
"""Return the 'Version' metadata for the distribution package."""
- return self.metadata['Version']
+ return md_none(self.metadata)['Version']
@property
def entry_points(self) -> EntryPoints:
@@ -530,7 +573,7 @@ class Distribution(metaclass=abc.ABCMeta):
return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self)
@property
- def files(self) -> Optional[List[PackagePath]]:
+ def files(self) -> list[PackagePath] | None:
"""Files in this distribution.
:return: List of PackagePath for this distribution or None
@@ -622,7 +665,7 @@ class Distribution(metaclass=abc.ABCMeta):
return text and map('"{}"'.format, text.splitlines())
@property
- def requires(self) -> Optional[List[str]]:
+ def requires(self) -> list[str] | None:
"""Generated requirements specified for this Distribution"""
reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
return reqs and list(reqs)
@@ -728,7 +771,7 @@ class DistributionFinder(MetaPathFinder):
vars(self).update(kwargs)
@property
- def path(self) -> List[str]:
+ def path(self) -> list[str]:
"""
The sequence of directory path that a distribution finder
should search.
@@ -880,7 +923,7 @@ class Prepared:
normalized = None
legacy_normalized = None
- def __init__(self, name: Optional[str]):
+ def __init__(self, name: str | None):
self.name = name
if name is None:
return
@@ -950,7 +993,7 @@ class PathDistribution(Distribution):
"""
self._path = path
- def read_text(self, filename: str | os.PathLike[str]) -> Optional[str]:
+ def read_text(self, filename: str | os.PathLike[str]) -> str | None:
with suppress(
FileNotFoundError,
IsADirectoryError,
@@ -1067,7 +1110,7 @@ def distributions(**kwargs) -> Iterable[Distribution]:
return Distribution.discover(**kwargs)
-def metadata(distribution_name: str) -> _meta.PackageMetadata:
+def metadata(distribution_name: str) -> _meta.PackageMetadata | None:
"""Get the metadata for the named package.
:param distribution_name: The name of the distribution package to query.
@@ -1110,7 +1153,7 @@ def entry_points(**params) -> EntryPoints:
return EntryPoints(eps).select(**params)
-def files(distribution_name: str) -> Optional[List[PackagePath]]:
+def files(distribution_name: str) -> list[PackagePath] | None:
"""Return a list of files for the named package.
:param distribution_name: The name of the distribution package to query.
@@ -1119,7 +1162,7 @@ def files(distribution_name: str) -> Optional[List[PackagePath]]:
return distribution(distribution_name).files
-def requires(distribution_name: str) -> Optional[List[str]]:
+def requires(distribution_name: str) -> list[str] | None:
"""
Return a list of requirements for the named package.
@@ -1129,7 +1172,7 @@ def requires(distribution_name: str) -> Optional[List[str]]:
return distribution(distribution_name).requires
-def packages_distributions() -> Mapping[str, List[str]]:
+def packages_distributions() -> Mapping[str, list[str]]:
"""
Return a mapping of top-level packages to their
distributions.
@@ -1142,7 +1185,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(dist.metadata['Name'])
+ pkg_to_dist[pkg].append(md_none(dist.metadata)['Name'])
return dict(pkg_to_dist)
@@ -1150,7 +1193,7 @@ def _top_level_declared(dist):
return (dist.read_text('top_level.txt') or '').split()
-def _topmost(name: PackagePath) -> Optional[str]:
+def _topmost(name: PackagePath) -> str | None:
"""
Return the top-most parent as long as there is a parent.
"""
diff --git a/contrib/python/importlib-metadata/py3/importlib_metadata/_collections.py b/contrib/python/importlib-metadata/py3/importlib_metadata/_collections.py
index cf0954e1a30..fc5045d36be 100644
--- a/contrib/python/importlib-metadata/py3/importlib_metadata/_collections.py
+++ b/contrib/python/importlib-metadata/py3/importlib_metadata/_collections.py
@@ -1,4 +1,5 @@
import collections
+import typing
# from jaraco.collections 3.3
@@ -24,7 +25,10 @@ class FreezableDefaultDict(collections.defaultdict):
self._frozen = lambda key: self.default_factory()
-class Pair(collections.namedtuple('Pair', 'name value')):
+class Pair(typing.NamedTuple):
+ name: str
+ value: str
+
@classmethod
def parse(cls, text):
return cls(*map(str.strip, text.split("=", 1)))
diff --git a/contrib/python/importlib-metadata/py3/importlib_metadata/_meta.py b/contrib/python/importlib-metadata/py3/importlib_metadata/_meta.py
index 0942bbd963a..0c20eff3da7 100644
--- a/contrib/python/importlib-metadata/py3/importlib_metadata/_meta.py
+++ b/contrib/python/importlib-metadata/py3/importlib_metadata/_meta.py
@@ -1,15 +1,11 @@
from __future__ import annotations
import os
+from collections.abc import Iterator
from typing import (
Any,
- Dict,
- Iterator,
- List,
- Optional,
Protocol,
TypeVar,
- Union,
overload,
)
@@ -28,25 +24,25 @@ class PackageMetadata(Protocol):
@overload
def get(
self, name: str, failobj: None = None
- ) -> Optional[str]: ... # pragma: no cover
+ ) -> str | None: ... # pragma: no cover
@overload
- def get(self, name: str, failobj: _T) -> Union[str, _T]: ... # pragma: no cover
+ def get(self, name: str, failobj: _T) -> str | _T: ... # pragma: no cover
# overload per python/importlib_metadata#435
@overload
def get_all(
self, name: str, failobj: None = None
- ) -> Optional[List[Any]]: ... # pragma: no cover
+ ) -> list[Any] | None: ... # pragma: no cover
@overload
- def get_all(self, name: str, failobj: _T) -> Union[List[Any], _T]:
+ def get_all(self, name: str, failobj: _T) -> list[Any] | _T:
"""
Return all values associated with a possibly multi-valued key.
"""
@property
- def json(self) -> Dict[str, Union[str, List[str]]]:
+ def json(self) -> dict[str, str | list[str]]:
"""
A JSON-compatible form of the metadata.
"""
@@ -58,11 +54,11 @@ class SimplePath(Protocol):
"""
def joinpath(
- self, other: Union[str, os.PathLike[str]]
+ self, other: str | os.PathLike[str]
) -> SimplePath: ... # pragma: no cover
def __truediv__(
- self, other: Union[str, os.PathLike[str]]
+ self, other: str | os.PathLike[str]
) -> SimplePath: ... # pragma: no cover
@property
diff --git a/contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py b/contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py
new file mode 100644
index 00000000000..32b1d2b98ac
--- /dev/null
+++ b/contrib/python/importlib-metadata/py3/importlib_metadata/_typing.py
@@ -0,0 +1,15 @@
+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/importlib_metadata/compat/py39.py b/contrib/python/importlib-metadata/py3/importlib_metadata/compat/py39.py
index 1f15bd97e6a..3eb9c01ecbb 100644
--- a/contrib/python/importlib-metadata/py3/importlib_metadata/compat/py39.py
+++ b/contrib/python/importlib-metadata/py3/importlib_metadata/compat/py39.py
@@ -2,7 +2,9 @@
Compatibility layer with Python 3.8/3.9
"""
-from typing import TYPE_CHECKING, Any, Optional
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any
if TYPE_CHECKING: # pragma: no cover
# Prevent circular imports on runtime.
@@ -10,8 +12,10 @@ if TYPE_CHECKING: # pragma: no cover
else:
Distribution = EntryPoint = Any
+from .._typing import md_none
+
-def normalized_name(dist: Distribution) -> Optional[str]:
+def normalized_name(dist: Distribution) -> str | None:
"""
Honor name normalization for distributions that don't provide ``_normalized_name``.
"""
@@ -20,7 +24,9 @@ def normalized_name(dist: Distribution) -> Optional[str]:
except AttributeError:
from .. import Prepared # -> delay to prevent circular imports.
- return Prepared.normalize(getattr(dist, "name", None) or dist.metadata['Name'])
+ return Prepared.normalize(
+ getattr(dist, "name", None) or md_none(dist.metadata)['Name']
+ )
def ep_matches(ep: EntryPoint, **params) -> bool:
diff --git a/contrib/python/importlib-metadata/py3/ya.make b/contrib/python/importlib-metadata/py3/ya.make
index bd8f1d06d9a..9544a14830f 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.6.1)
+VERSION(8.7.0)
LICENSE(Apache-2.0)
@@ -18,6 +18,7 @@ PY_SRCS(
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/compat/py39.py