From e599e261e4daab81a8aee519ef770c36e4af5196 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 30 May 2021 14:48:48 +0200 Subject: [PATCH 1/4] Rework Match.group handling Standardize group(), groups(), groupdict(), and __getattr__() to return Any instead of AnyStr. Also special case group(0) and __getattr__(0) to always return AnyStr. Use PEP 604 for unions in changed lines. --- stdlib/typing.pyi | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index aafb1fbdf1b3..2bb453aa3c8a 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -2,6 +2,7 @@ import collections # Needed by aliases like DefaultDict, see mypy issue 2986 import sys from abc import ABCMeta, abstractmethod from types import BuiltinFunctionType, CodeType, FrameType, FunctionType, MethodType, ModuleType, TracebackType +from typing_extensions import Literal as _Literal if sys.version_info >= (3, 7): from types import MethodDescriptorType, MethodWrapperType, WrapperDescriptorType @@ -563,19 +564,29 @@ class Match(Generic[AnyStr]): # this match instance. re: Pattern[AnyStr] def expand(self, template: AnyStr) -> AnyStr: ... - # TODO: The return for a group may be None, except if __group is 0 or not given. + # group() returns "AnyStr" or "AnyStr | None", depending on the pattern. @overload - def group(self, __group: Union[str, int] = ...) -> AnyStr: ... + def group(self, __group: _Literal[0] = ...) -> AnyStr: ... @overload - def group(self, __group1: Union[str, int], __group2: Union[str, int], *groups: Union[str, int]) -> Tuple[AnyStr, ...]: ... - def groups(self, default: AnyStr = ...) -> Sequence[AnyStr]: ... - def groupdict(self, default: AnyStr = ...) -> dict[str, AnyStr]: ... + def group(self, __group: str | int) -> Any: ... + @overload + def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> Tuple[Any, ...]: ... + # Each item of groups()'s return tuple is either "AnyStr" or + # "AnyStr | None", depending on the pattern. + def groups(self, default: AnyStr = ...) -> Tuple[Any, ...]: ... + # Each value in groupdict()'s return dict is either "AnyStr" or + # "AnyStr | None", depending on the pattern. + def groupdict(self, default: AnyStr = ...) -> dict[str, Any]: ... def start(self, __group: Union[int, str] = ...) -> int: ... def end(self, __group: Union[int, str] = ...) -> int: ... def span(self, __group: Union[int, str] = ...) -> Tuple[int, int]: ... @property def regs(self) -> Tuple[Tuple[int, int], ...]: ... # undocumented - def __getitem__(self, g: Union[int, str]) -> AnyStr: ... + # __getitem__() returns "AnyStr" or "AnyStr | None", depending on the pattern. + @overload + def __getitem__(self, __key: Literal[0]) -> AnyStr: ... + @overload + def __getitem__(self, __key: int | str) -> Any: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... From dae70753d8af03cdf93df4331fb06c3cf9cd1544 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 30 May 2021 14:56:27 +0200 Subject: [PATCH 2/4] Literal -> _Literal --- stdlib/typing.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index 2bb453aa3c8a..2e64f52218d6 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -584,7 +584,7 @@ class Match(Generic[AnyStr]): def regs(self) -> Tuple[Tuple[int, int], ...]: ... # undocumented # __getitem__() returns "AnyStr" or "AnyStr | None", depending on the pattern. @overload - def __getitem__(self, __key: Literal[0]) -> AnyStr: ... + def __getitem__(self, __key: _Literal[0]) -> AnyStr: ... @overload def __getitem__(self, __key: int | str) -> Any: ... if sys.version_info >= (3, 9): From 4576665565e70736bb4124db92e7bd34c067f3ea Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 30 May 2021 15:16:29 +0200 Subject: [PATCH 3/4] Use AnyStr | Any instead of just Any --- stdlib/typing.pyi | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index 2e64f52218d6..c36bf6daa835 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -568,15 +568,15 @@ class Match(Generic[AnyStr]): @overload def group(self, __group: _Literal[0] = ...) -> AnyStr: ... @overload - def group(self, __group: str | int) -> Any: ... + def group(self, __group: str | int) -> AnyStr | Any: ... @overload - def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> Tuple[Any, ...]: ... + def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> Tuple[AnyStr | Any, ...]: ... # Each item of groups()'s return tuple is either "AnyStr" or # "AnyStr | None", depending on the pattern. - def groups(self, default: AnyStr = ...) -> Tuple[Any, ...]: ... + def groups(self, default: AnyStr = ...) -> Tuple[AnyStr | Any, ...]: ... # Each value in groupdict()'s return dict is either "AnyStr" or # "AnyStr | None", depending on the pattern. - def groupdict(self, default: AnyStr = ...) -> dict[str, Any]: ... + def groupdict(self, default: AnyStr = ...) -> dict[str, AnyStr | Any]: ... def start(self, __group: Union[int, str] = ...) -> int: ... def end(self, __group: Union[int, str] = ...) -> int: ... def span(self, __group: Union[int, str] = ...) -> Tuple[int, int]: ... @@ -586,7 +586,7 @@ class Match(Generic[AnyStr]): @overload def __getitem__(self, __key: _Literal[0]) -> AnyStr: ... @overload - def __getitem__(self, __key: int | str) -> Any: ... + def __getitem__(self, __key: int | str) -> AnyStr | Any: ... if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any) -> GenericAlias: ... @@ -597,7 +597,6 @@ class Pattern(Generic[AnyStr]): pattern: AnyStr def search(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Optional[Match[AnyStr]]: ... def match(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Optional[Match[AnyStr]]: ... - # New in Python 3.4 def fullmatch(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> Optional[Match[AnyStr]]: ... def split(self, string: AnyStr, maxsplit: int = ...) -> list[AnyStr]: ... def findall(self, string: AnyStr, pos: int = ..., endpos: int = ...) -> list[Any]: ... From bd2c288ce24feecc5adf967f71122916212e42c1 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 30 May 2021 15:31:37 +0200 Subject: [PATCH 4/4] Handle defaults --- stdlib/typing.pyi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index c36bf6daa835..359a7d4f9e92 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -573,10 +573,16 @@ class Match(Generic[AnyStr]): def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> Tuple[AnyStr | Any, ...]: ... # Each item of groups()'s return tuple is either "AnyStr" or # "AnyStr | None", depending on the pattern. - def groups(self, default: AnyStr = ...) -> Tuple[AnyStr | Any, ...]: ... + @overload + def groups(self) -> Tuple[AnyStr | Any, ...]: ... + @overload + def groups(self, default: _T) -> Tuple[AnyStr | _T, ...]: ... # Each value in groupdict()'s return dict is either "AnyStr" or # "AnyStr | None", depending on the pattern. - def groupdict(self, default: AnyStr = ...) -> dict[str, AnyStr | Any]: ... + @overload + def groupdict(self) -> dict[str, AnyStr | Any]: ... + @overload + def groupdict(self, default: _T) -> dict[str, AnyStr | _T]: ... def start(self, __group: Union[int, str] = ...) -> int: ... def end(self, __group: Union[int, str] = ...) -> int: ... def span(self, __group: Union[int, str] = ...) -> Tuple[int, int]: ...