Skip to content

Commit ea7bbbd

Browse files
authored
Move Match and Pattern to re.pyi; move ContextManager protocols to contextlib.pyi (#8447)
1 parent 36a5bb0 commit ea7bbbd

File tree

3 files changed

+145
-140
lines changed

3 files changed

+145
-140
lines changed

stdlib/contextlib.pyi

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import sys
22
from _typeshed import Self, StrOrBytesPath
3+
from abc import abstractmethod
34
from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Callable, Generator, Iterator
45
from types import TracebackType
5-
from typing import IO, Any, AsyncContextManager, ContextManager, Generic, Protocol, TypeVar, overload # noqa: Y022,Y027
6+
from typing import IO, Any, Generic, Protocol, TypeVar, overload, runtime_checkable
67
from typing_extensions import ParamSpec, TypeAlias
78

89
__all__ = [
@@ -35,8 +36,21 @@ _P = ParamSpec("_P")
3536
_ExitFunc: TypeAlias = Callable[[type[BaseException] | None, BaseException | None, TracebackType | None], bool | None]
3637
_CM_EF = TypeVar("_CM_EF", bound=AbstractContextManager[Any] | _ExitFunc)
3738

38-
AbstractContextManager = ContextManager
39-
AbstractAsyncContextManager = AsyncContextManager
39+
@runtime_checkable
40+
class AbstractContextManager(Protocol[_T_co]):
41+
def __enter__(self) -> _T_co: ...
42+
@abstractmethod
43+
def __exit__(
44+
self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
45+
) -> bool | None: ...
46+
47+
@runtime_checkable
48+
class AbstractAsyncContextManager(Protocol[_T_co]):
49+
async def __aenter__(self) -> _T_co: ...
50+
@abstractmethod
51+
async def __aexit__(
52+
self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
53+
) -> bool | None: ...
4054

4155
class ContextDecorator:
4256
def __call__(self, func: _F) -> _F: ...

stdlib/re.pyi

Lines changed: 121 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ import enum
22
import sre_compile
33
import sys
44
from _typeshed import ReadableBuffer
5-
from collections.abc import Callable, Iterator
5+
from collections.abc import Callable, Iterator, Mapping
66
from sre_constants import error as error
7-
from typing import Any, AnyStr, Match as Match, Pattern as Pattern, overload
8-
from typing_extensions import TypeAlias
7+
from typing import Any, AnyStr, Generic, TypeVar, overload
8+
from typing_extensions import Literal, TypeAlias, final
9+
10+
if sys.version_info >= (3, 9):
11+
from types import GenericAlias
912

1013
__all__ = [
1114
"match",
@@ -42,6 +45,121 @@ __all__ = [
4245
if sys.version_info >= (3, 11):
4346
__all__ += ["NOFLAG", "RegexFlag"]
4447

48+
_T = TypeVar("_T")
49+
50+
@final
51+
class Match(Generic[AnyStr]):
52+
@property
53+
def pos(self) -> int: ...
54+
@property
55+
def endpos(self) -> int: ...
56+
@property
57+
def lastindex(self) -> int | None: ...
58+
@property
59+
def lastgroup(self) -> str | None: ...
60+
@property
61+
def string(self) -> AnyStr: ...
62+
63+
# The regular expression object whose match() or search() method produced
64+
# this match instance.
65+
@property
66+
def re(self) -> Pattern[AnyStr]: ...
67+
@overload
68+
def expand(self: Match[str], template: str) -> str: ...
69+
@overload
70+
def expand(self: Match[bytes], template: ReadableBuffer) -> bytes: ...
71+
# group() returns "AnyStr" or "AnyStr | None", depending on the pattern.
72+
@overload
73+
def group(self, __group: Literal[0] = ...) -> AnyStr: ...
74+
@overload
75+
def group(self, __group: str | int) -> AnyStr | Any: ...
76+
@overload
77+
def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> tuple[AnyStr | Any, ...]: ...
78+
# Each item of groups()'s return tuple is either "AnyStr" or
79+
# "AnyStr | None", depending on the pattern.
80+
@overload
81+
def groups(self) -> tuple[AnyStr | Any, ...]: ...
82+
@overload
83+
def groups(self, default: _T) -> tuple[AnyStr | _T, ...]: ...
84+
# Each value in groupdict()'s return dict is either "AnyStr" or
85+
# "AnyStr | None", depending on the pattern.
86+
@overload
87+
def groupdict(self) -> dict[str, AnyStr | Any]: ...
88+
@overload
89+
def groupdict(self, default: _T) -> dict[str, AnyStr | _T]: ...
90+
def start(self, __group: int | str = ...) -> int: ...
91+
def end(self, __group: int | str = ...) -> int: ...
92+
def span(self, __group: int | str = ...) -> tuple[int, int]: ...
93+
@property
94+
def regs(self) -> tuple[tuple[int, int], ...]: ... # undocumented
95+
# __getitem__() returns "AnyStr" or "AnyStr | None", depending on the pattern.
96+
@overload
97+
def __getitem__(self, __key: Literal[0]) -> AnyStr: ...
98+
@overload
99+
def __getitem__(self, __key: int | str) -> AnyStr | Any: ...
100+
def __copy__(self) -> Match[AnyStr]: ...
101+
def __deepcopy__(self, __memo: Any) -> Match[AnyStr]: ...
102+
if sys.version_info >= (3, 9):
103+
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
104+
105+
@final
106+
class Pattern(Generic[AnyStr]):
107+
@property
108+
def flags(self) -> int: ...
109+
@property
110+
def groupindex(self) -> Mapping[str, int]: ...
111+
@property
112+
def groups(self) -> int: ...
113+
@property
114+
def pattern(self) -> AnyStr: ...
115+
@overload
116+
def search(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
117+
@overload
118+
def search(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
119+
@overload
120+
def match(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
121+
@overload
122+
def match(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
123+
@overload
124+
def fullmatch(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
125+
@overload
126+
def fullmatch(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
127+
@overload
128+
def split(self: Pattern[str], string: str, maxsplit: int = ...) -> list[str | Any]: ...
129+
@overload
130+
def split(self: Pattern[bytes], string: ReadableBuffer, maxsplit: int = ...) -> list[bytes | Any]: ...
131+
# return type depends on the number of groups in the pattern
132+
@overload
133+
def findall(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> list[Any]: ...
134+
@overload
135+
def findall(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> list[Any]: ...
136+
@overload
137+
def finditer(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Iterator[Match[str]]: ...
138+
@overload
139+
def finditer(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Iterator[Match[bytes]]: ...
140+
@overload
141+
def sub(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> str: ...
142+
@overload
143+
def sub(
144+
self: Pattern[bytes],
145+
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
146+
string: ReadableBuffer,
147+
count: int = ...,
148+
) -> bytes: ...
149+
@overload
150+
def subn(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> tuple[str, int]: ...
151+
@overload
152+
def subn(
153+
self: Pattern[bytes],
154+
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
155+
string: ReadableBuffer,
156+
count: int = ...,
157+
) -> tuple[bytes, int]: ...
158+
def __copy__(self) -> Pattern[AnyStr]: ...
159+
def __deepcopy__(self, __memo: Any) -> Pattern[AnyStr]: ...
160+
if sys.version_info >= (3, 9):
161+
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
162+
45163
# ----- re variables and constants -----
46164

47165
class RegexFlag(enum.IntFlag):

stdlib/typing.pyi

Lines changed: 7 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import collections # Needed by aliases like DefaultDict, see mypy issue 2986
22
import sys
3-
from _typeshed import IdentityFunction, Incomplete, ReadableBuffer, Self as TypeshedSelf, SupportsKeysAndGetItem
3+
from _typeshed import IdentityFunction, Incomplete, Self as TypeshedSelf, SupportsKeysAndGetItem
44
from abc import ABCMeta, abstractmethod
5+
from contextlib import AbstractAsyncContextManager, AbstractContextManager
6+
from re import Match as Match, Pattern as Pattern
57
from types import (
68
BuiltinFunctionType,
79
CodeType,
@@ -14,10 +16,7 @@ from types import (
1416
TracebackType,
1517
WrapperDescriptorType,
1618
)
17-
from typing_extensions import Literal as _Literal, ParamSpec as _ParamSpec, final as _final
18-
19-
if sys.version_info >= (3, 9):
20-
from types import GenericAlias
19+
from typing_extensions import ParamSpec as _ParamSpec, final as _final
2120

2221
__all__ = [
2322
"AbstractSet",
@@ -120,6 +119,9 @@ if sys.version_info >= (3, 11):
120119
"reveal_type",
121120
]
122121

122+
ContextManager = AbstractContextManager
123+
AsyncContextManager = AbstractAsyncContextManager
124+
123125
# This itself is only available during type checking
124126
def type_check_only(func_or_cls: _F) -> _F: ...
125127

@@ -568,22 +570,6 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]):
568570
if sys.version_info >= (3, 8):
569571
def __reversed__(self) -> Iterator[_VT_co]: ...
570572

571-
@runtime_checkable
572-
class ContextManager(Protocol[_T_co]):
573-
def __enter__(self) -> _T_co: ...
574-
@abstractmethod
575-
def __exit__(
576-
self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
577-
) -> bool | None: ...
578-
579-
@runtime_checkable
580-
class AsyncContextManager(Protocol[_T_co]):
581-
async def __aenter__(self) -> _T_co: ...
582-
@abstractmethod
583-
async def __aexit__(
584-
self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
585-
) -> bool | None: ...
586-
587573
class Mapping(Collection[_KT], Generic[_KT, _VT_co]):
588574
# TODO: We wish the key type could also be covariant, but that doesn't work,
589575
# see discussion in https://github.com/python/typing/pull/273.
@@ -718,119 +704,6 @@ class TextIO(IO[str]):
718704

719705
class ByteString(Sequence[int], metaclass=ABCMeta): ...
720706

721-
@_final
722-
class Match(Generic[AnyStr]):
723-
@property
724-
def pos(self) -> int: ...
725-
@property
726-
def endpos(self) -> int: ...
727-
@property
728-
def lastindex(self) -> int | None: ...
729-
@property
730-
def lastgroup(self) -> str | None: ...
731-
@property
732-
def string(self) -> AnyStr: ...
733-
734-
# The regular expression object whose match() or search() method produced
735-
# this match instance.
736-
@property
737-
def re(self) -> Pattern[AnyStr]: ...
738-
@overload
739-
def expand(self: Match[str], template: str) -> str: ...
740-
@overload
741-
def expand(self: Match[bytes], template: ReadableBuffer) -> bytes: ...
742-
# group() returns "AnyStr" or "AnyStr | None", depending on the pattern.
743-
@overload
744-
def group(self, __group: _Literal[0] = ...) -> AnyStr: ...
745-
@overload
746-
def group(self, __group: str | int) -> AnyStr | Any: ...
747-
@overload
748-
def group(self, __group1: str | int, __group2: str | int, *groups: str | int) -> tuple[AnyStr | Any, ...]: ...
749-
# Each item of groups()'s return tuple is either "AnyStr" or
750-
# "AnyStr | None", depending on the pattern.
751-
@overload
752-
def groups(self) -> tuple[AnyStr | Any, ...]: ...
753-
@overload
754-
def groups(self, default: _T) -> tuple[AnyStr | _T, ...]: ...
755-
# Each value in groupdict()'s return dict is either "AnyStr" or
756-
# "AnyStr | None", depending on the pattern.
757-
@overload
758-
def groupdict(self) -> dict[str, AnyStr | Any]: ...
759-
@overload
760-
def groupdict(self, default: _T) -> dict[str, AnyStr | _T]: ...
761-
def start(self, __group: int | str = ...) -> int: ...
762-
def end(self, __group: int | str = ...) -> int: ...
763-
def span(self, __group: int | str = ...) -> tuple[int, int]: ...
764-
@property
765-
def regs(self) -> tuple[tuple[int, int], ...]: ... # undocumented
766-
# __getitem__() returns "AnyStr" or "AnyStr | None", depending on the pattern.
767-
@overload
768-
def __getitem__(self, __key: _Literal[0]) -> AnyStr: ...
769-
@overload
770-
def __getitem__(self, __key: int | str) -> AnyStr | Any: ...
771-
def __copy__(self) -> Match[AnyStr]: ...
772-
def __deepcopy__(self, __memo: Any) -> Match[AnyStr]: ...
773-
if sys.version_info >= (3, 9):
774-
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
775-
776-
@_final
777-
class Pattern(Generic[AnyStr]):
778-
@property
779-
def flags(self) -> int: ...
780-
@property
781-
def groupindex(self) -> Mapping[str, int]: ...
782-
@property
783-
def groups(self) -> int: ...
784-
@property
785-
def pattern(self) -> AnyStr: ...
786-
@overload
787-
def search(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
788-
@overload
789-
def search(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
790-
@overload
791-
def match(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
792-
@overload
793-
def match(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
794-
@overload
795-
def fullmatch(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
796-
@overload
797-
def fullmatch(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
798-
@overload
799-
def split(self: Pattern[str], string: str, maxsplit: int = ...) -> list[str | Any]: ...
800-
@overload
801-
def split(self: Pattern[bytes], string: ReadableBuffer, maxsplit: int = ...) -> list[bytes | Any]: ...
802-
# return type depends on the number of groups in the pattern
803-
@overload
804-
def findall(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> list[Any]: ...
805-
@overload
806-
def findall(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> list[Any]: ...
807-
@overload
808-
def finditer(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Iterator[Match[str]]: ...
809-
@overload
810-
def finditer(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Iterator[Match[bytes]]: ...
811-
@overload
812-
def sub(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> str: ...
813-
@overload
814-
def sub(
815-
self: Pattern[bytes],
816-
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
817-
string: ReadableBuffer,
818-
count: int = ...,
819-
) -> bytes: ...
820-
@overload
821-
def subn(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> tuple[str, int]: ...
822-
@overload
823-
def subn(
824-
self: Pattern[bytes],
825-
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
826-
string: ReadableBuffer,
827-
count: int = ...,
828-
) -> tuple[bytes, int]: ...
829-
def __copy__(self) -> Pattern[AnyStr]: ...
830-
def __deepcopy__(self, __memo: Any) -> Pattern[AnyStr]: ...
831-
if sys.version_info >= (3, 9):
832-
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
833-
834707
# Functions
835708

836709
_get_type_hints_obj_allowed_types = ( # noqa: Y026 # TODO: Use TypeAlias once mypy bugs are fixed

0 commit comments

Comments
 (0)