Skip to content

Add deprecation classes in importlib.metadata #11118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 65 additions & 10 deletions stdlib/importlib/metadata/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import abc
import pathlib
import sys
from _collections_abc import dict_keys, dict_values
from _typeshed import StrPath
from collections.abc import Iterable, Mapping
from collections.abc import Iterable, Iterator, Mapping
from email.message import Message
from importlib.abc import MetaPathFinder
from os import PathLike
from pathlib import Path
from re import Pattern
from typing import Any, ClassVar, NamedTuple, overload
from typing import Any, ClassVar, Generic, NamedTuple, TypeVar, overload
from typing_extensions import Self

_T = TypeVar("_T")
_KT = TypeVar("_KT")
_VT = TypeVar("_VT")

__all__ = [
"Distribution",
"DistributionFinder",
Expand All @@ -35,14 +40,23 @@ class PackageNotFoundError(ModuleNotFoundError):
@property
def name(self) -> str: ... # type: ignore[override]

class _EntryPointBase(NamedTuple):
name: str
value: str
group: str
if sys.version_info >= (3, 11):
class DeprecatedTuple:
def __getitem__(self, item: int) -> str: ...
_EntryPointBase = DeprecatedTuple
else:
class _EntryPointBase(NamedTuple):
name: str
value: str
group: str

class EntryPoint(_EntryPointBase):
pattern: ClassVar[Pattern[str]]
if sys.version_info >= (3, 11):
name: str
value: str
group: str

def __init__(self, name: str, value: str, group: str) -> None: ...

def load(self) -> Any: ... # Callable[[], Any] or an importable module
Expand All @@ -68,9 +82,33 @@ class EntryPoint(_EntryPointBase):

def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
if sys.version_info >= (3, 11):
def __lt__(self, other: object) -> bool: ...
if sys.version_info < (3, 12):
def __iter__(self) -> Iterator[Any]: ... # result of iter((str, Self)), really
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So why not use Iterator[tuple[str, Self]]?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an iterator that returns tuple[str, Self]. This is an iterator that will always return two items, the first of which is str and the second of which is Self. As far as I know, there's no way to express that in the current system. We could do Iterator[str | Self], but my understanding is that it's better to avoid union return types.

The implementation here is return iter((self.name, self)); I meant "iter()` as the runtime function, not a misspelling of the type, but that's a bit confusing because then I switched to the types of the values. Maybe the comment could be better worded, but I'm not sure how without getting too wordy. Might be better to just leave off the comment if it's too confusing. The function was removed in 3.12, so this is going away (eventually) anyway.


if sys.version_info >= (3, 10):
class EntryPoints(list[EntryPoint]): # use as list is deprecated since 3.10
if sys.version_info >= (3, 12):
class EntryPoints(tuple[EntryPoint, ...]):
def __getitem__(self, name: str) -> EntryPoint: ... # type: ignore[override]
def select(
self,
*,
name: str = ...,
value: str = ...,
group: str = ...,
module: str = ...,
attr: str = ...,
extras: list[str] = ...,
) -> EntryPoints: ...
@property
def names(self) -> set[str]: ...
@property
def groups(self) -> set[str]: ...

elif sys.version_info >= (3, 10):
class DeprecatedList(list[_T]): ...

class EntryPoints(DeprecatedList[EntryPoint]): # use as list is deprecated since 3.10
# int argument is deprecated since 3.10
def __getitem__(self, name: int | str) -> EntryPoint: ... # type: ignore[override]
def select(
Expand All @@ -89,7 +127,18 @@ if sys.version_info >= (3, 10):
def groups(self) -> set[str]: ...

if sys.version_info >= (3, 10) and sys.version_info < (3, 12):
class SelectableGroups(dict[str, EntryPoints]): # use as dict is deprecated since 3.10
class Deprecated(Generic[_KT, _VT]):
def __getitem__(self, name: _KT) -> _VT: ...
@overload
def get(self, name: _KT) -> _VT | None: ...
@overload
def get(self, name: _KT, default: _T) -> _VT | _T: ...
def __iter__(self) -> Iterator[_KT]: ...
def __contains__(self, *args: object) -> bool: ...
def keys(self) -> dict_keys[_KT, _VT]: ...
def values(self) -> dict_values[_KT, _VT]: ...

class SelectableGroups(Deprecated[str, EntryPoints], dict[str, EntryPoints]): # use as dict is deprecated since 3.10
@classmethod
def load(cls, eps: Iterable[EntryPoint]) -> Self: ...
@property
Expand Down Expand Up @@ -124,7 +173,13 @@ class FileHash:
value: str
def __init__(self, spec: str) -> None: ...

class Distribution:
if sys.version_info >= (3, 12):
class DeprecatedNonAbstract: ...
_distribution_parent = DeprecatedNonAbstract
else:
_distribution_parent = object

class Distribution(_distribution_parent):
@abc.abstractmethod
def read_text(self, filename: str) -> str | None: ...
@abc.abstractmethod
Expand Down
4 changes: 4 additions & 0 deletions tests/stubtest_allowlists/py310.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ typing.ParamSpec(Args|Kwargs).__origin__
importlib.abc.Traversable.joinpath
importlib.abc.Traversable.open

# Deprecation wrapper classes; their methods are just pass-through, so we can ignore them.
importlib.metadata.DeprecatedList.reverse
importlib.metadata.DeprecatedList.sort

# Super-special typing primitives
typing\.NamedTuple
typing\.Annotated
Expand Down
4 changes: 4 additions & 0 deletions tests/stubtest_allowlists/py311.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ unittest.case.TestCase.__init_subclass__
importlib.abc.Traversable.open
importlib.resources.abc.Traversable.open

# Deprecation wrapper classes; their methods are just pass-through, so we can ignore them.
importlib.metadata.DeprecatedList.reverse
importlib.metadata.DeprecatedList.sort

# Super-special typing primitives
typing\._SpecialForm.*
typing\.NamedTuple
Expand Down
3 changes: 3 additions & 0 deletions tests/stubtest_allowlists/py312.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ unittest.case.TestCase.__init_subclass__
importlib.abc.Traversable.open
importlib.resources.abc.Traversable.open

# Deprecation wrapper classes; their methods are just pass-through, so we can ignore them.
importlib.metadata.DeprecatedNonAbstract.__new__

# Super-special typing primitives
typing\._SpecialForm.*
typing\.NamedTuple
Expand Down