Skip to content

Move Match and Pattern to re.pyi; move ContextManager protocols to contextlib.pyi #8447

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 1 commit into from
Jul 31, 2022
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
20 changes: 17 additions & 3 deletions stdlib/contextlib.pyi
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import sys
from _typeshed import Self, StrOrBytesPath
from abc import abstractmethod
from collections.abc import AsyncGenerator, AsyncIterator, Awaitable, Callable, Generator, Iterator
from types import TracebackType
from typing import IO, Any, AsyncContextManager, ContextManager, Generic, Protocol, TypeVar, overload # noqa: Y022,Y027
from typing import IO, Any, Generic, Protocol, TypeVar, overload, runtime_checkable
from typing_extensions import ParamSpec, TypeAlias

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

AbstractContextManager = ContextManager
AbstractAsyncContextManager = AsyncContextManager
@runtime_checkable
class AbstractContextManager(Protocol[_T_co]):
def __enter__(self) -> _T_co: ...
@abstractmethod
def __exit__(
self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
) -> bool | None: ...

@runtime_checkable
class AbstractAsyncContextManager(Protocol[_T_co]):
async def __aenter__(self) -> _T_co: ...
@abstractmethod
async def __aexit__(
self, __exc_type: type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
) -> bool | None: ...

class ContextDecorator:
def __call__(self, func: _F) -> _F: ...
Expand Down
124 changes: 121 additions & 3 deletions stdlib/re.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import enum
import sre_compile
import sys
from _typeshed import ReadableBuffer
from collections.abc import Callable, Iterator
from collections.abc import Callable, Iterator, Mapping
from sre_constants import error as error
from typing import Any, AnyStr, Match as Match, Pattern as Pattern, overload
from typing_extensions import TypeAlias
from typing import Any, AnyStr, Generic, TypeVar, overload
from typing_extensions import Literal, TypeAlias, final

if sys.version_info >= (3, 9):
from types import GenericAlias

__all__ = [
"match",
Expand Down Expand Up @@ -42,6 +45,121 @@ __all__ = [
if sys.version_info >= (3, 11):
__all__ += ["NOFLAG", "RegexFlag"]

_T = TypeVar("_T")

@final
class Match(Generic[AnyStr]):
@property
def pos(self) -> int: ...
@property
def endpos(self) -> int: ...
@property
def lastindex(self) -> int | None: ...
@property
def lastgroup(self) -> str | None: ...
@property
def string(self) -> AnyStr: ...

# The regular expression object whose match() or search() method produced
# this match instance.
@property
def re(self) -> Pattern[AnyStr]: ...
@overload
def expand(self: Match[str], template: str) -> str: ...
@overload
def expand(self: Match[bytes], template: ReadableBuffer) -> bytes: ...
# group() returns "AnyStr" or "AnyStr | None", depending on the pattern.
@overload
def group(self, __group: Literal[0] = ...) -> AnyStr: ...
@overload
def group(self, __group: str | int) -> AnyStr | Any: ...
@overload
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.
@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.
@overload
def groupdict(self) -> dict[str, AnyStr | Any]: ...
@overload
def groupdict(self, default: _T) -> dict[str, AnyStr | _T]: ...
def start(self, __group: int | str = ...) -> int: ...
def end(self, __group: int | str = ...) -> int: ...
def span(self, __group: int | str = ...) -> tuple[int, int]: ...
@property
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: ...
@overload
def __getitem__(self, __key: int | str) -> AnyStr | Any: ...
def __copy__(self) -> Match[AnyStr]: ...
def __deepcopy__(self, __memo: Any) -> Match[AnyStr]: ...
if sys.version_info >= (3, 9):
def __class_getitem__(cls, item: Any) -> GenericAlias: ...

@final
class Pattern(Generic[AnyStr]):
@property
def flags(self) -> int: ...
@property
def groupindex(self) -> Mapping[str, int]: ...
@property
def groups(self) -> int: ...
@property
def pattern(self) -> AnyStr: ...
@overload
def search(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
@overload
def search(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
@overload
def match(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
@overload
def match(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
@overload
def fullmatch(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
@overload
def fullmatch(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
@overload
def split(self: Pattern[str], string: str, maxsplit: int = ...) -> list[str | Any]: ...
@overload
def split(self: Pattern[bytes], string: ReadableBuffer, maxsplit: int = ...) -> list[bytes | Any]: ...
# return type depends on the number of groups in the pattern
@overload
def findall(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> list[Any]: ...
@overload
def findall(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> list[Any]: ...
@overload
def finditer(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Iterator[Match[str]]: ...
@overload
def finditer(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Iterator[Match[bytes]]: ...
@overload
def sub(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> str: ...
@overload
def sub(
self: Pattern[bytes],
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
string: ReadableBuffer,
count: int = ...,
) -> bytes: ...
@overload
def subn(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> tuple[str, int]: ...
@overload
def subn(
self: Pattern[bytes],
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
string: ReadableBuffer,
count: int = ...,
) -> tuple[bytes, int]: ...
def __copy__(self) -> Pattern[AnyStr]: ...
def __deepcopy__(self, __memo: Any) -> Pattern[AnyStr]: ...
if sys.version_info >= (3, 9):
def __class_getitem__(cls, item: Any) -> GenericAlias: ...

# ----- re variables and constants -----

class RegexFlag(enum.IntFlag):
Expand Down
141 changes: 7 additions & 134 deletions stdlib/typing.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import collections # Needed by aliases like DefaultDict, see mypy issue 2986
import sys
from _typeshed import IdentityFunction, Incomplete, ReadableBuffer, Self as TypeshedSelf, SupportsKeysAndGetItem
from _typeshed import IdentityFunction, Incomplete, Self as TypeshedSelf, SupportsKeysAndGetItem
from abc import ABCMeta, abstractmethod
from contextlib import AbstractAsyncContextManager, AbstractContextManager
from re import Match as Match, Pattern as Pattern
from types import (
BuiltinFunctionType,
CodeType,
Expand All @@ -14,10 +16,7 @@ from types import (
TracebackType,
WrapperDescriptorType,
)
from typing_extensions import Literal as _Literal, ParamSpec as _ParamSpec, final as _final

if sys.version_info >= (3, 9):
from types import GenericAlias
from typing_extensions import ParamSpec as _ParamSpec, final as _final

__all__ = [
"AbstractSet",
Expand Down Expand Up @@ -120,6 +119,9 @@ if sys.version_info >= (3, 11):
"reveal_type",
]

ContextManager = AbstractContextManager
AsyncContextManager = AbstractAsyncContextManager

# This itself is only available during type checking
def type_check_only(func_or_cls: _F) -> _F: ...

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

@runtime_checkable
class ContextManager(Protocol[_T_co]):
def __enter__(self) -> _T_co: ...
@abstractmethod
def __exit__(
self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
) -> bool | None: ...

@runtime_checkable
class AsyncContextManager(Protocol[_T_co]):
async def __aenter__(self) -> _T_co: ...
@abstractmethod
async def __aexit__(
self, __exc_type: Type[BaseException] | None, __exc_value: BaseException | None, __traceback: TracebackType | None
) -> bool | None: ...

class Mapping(Collection[_KT], Generic[_KT, _VT_co]):
# TODO: We wish the key type could also be covariant, but that doesn't work,
# see discussion in https://github.com/python/typing/pull/273.
Expand Down Expand Up @@ -718,119 +704,6 @@ class TextIO(IO[str]):

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

@_final
class Match(Generic[AnyStr]):
@property
def pos(self) -> int: ...
@property
def endpos(self) -> int: ...
@property
def lastindex(self) -> int | None: ...
@property
def lastgroup(self) -> str | None: ...
@property
def string(self) -> AnyStr: ...

# The regular expression object whose match() or search() method produced
# this match instance.
@property
def re(self) -> Pattern[AnyStr]: ...
@overload
def expand(self: Match[str], template: str) -> str: ...
@overload
def expand(self: Match[bytes], template: ReadableBuffer) -> bytes: ...
# group() returns "AnyStr" or "AnyStr | None", depending on the pattern.
@overload
def group(self, __group: _Literal[0] = ...) -> AnyStr: ...
@overload
def group(self, __group: str | int) -> AnyStr | Any: ...
@overload
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.
@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.
@overload
def groupdict(self) -> dict[str, AnyStr | Any]: ...
@overload
def groupdict(self, default: _T) -> dict[str, AnyStr | _T]: ...
def start(self, __group: int | str = ...) -> int: ...
def end(self, __group: int | str = ...) -> int: ...
def span(self, __group: int | str = ...) -> tuple[int, int]: ...
@property
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: ...
@overload
def __getitem__(self, __key: int | str) -> AnyStr | Any: ...
def __copy__(self) -> Match[AnyStr]: ...
def __deepcopy__(self, __memo: Any) -> Match[AnyStr]: ...
if sys.version_info >= (3, 9):
def __class_getitem__(cls, item: Any) -> GenericAlias: ...

@_final
class Pattern(Generic[AnyStr]):
@property
def flags(self) -> int: ...
@property
def groupindex(self) -> Mapping[str, int]: ...
@property
def groups(self) -> int: ...
@property
def pattern(self) -> AnyStr: ...
@overload
def search(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
@overload
def search(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
@overload
def match(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
@overload
def match(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
@overload
def fullmatch(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Match[str] | None: ...
@overload
def fullmatch(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Match[bytes] | None: ...
@overload
def split(self: Pattern[str], string: str, maxsplit: int = ...) -> list[str | Any]: ...
@overload
def split(self: Pattern[bytes], string: ReadableBuffer, maxsplit: int = ...) -> list[bytes | Any]: ...
# return type depends on the number of groups in the pattern
@overload
def findall(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> list[Any]: ...
@overload
def findall(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> list[Any]: ...
@overload
def finditer(self: Pattern[str], string: str, pos: int = ..., endpos: int = ...) -> Iterator[Match[str]]: ...
@overload
def finditer(self: Pattern[bytes], string: ReadableBuffer, pos: int = ..., endpos: int = ...) -> Iterator[Match[bytes]]: ...
@overload
def sub(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> str: ...
@overload
def sub(
self: Pattern[bytes],
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
string: ReadableBuffer,
count: int = ...,
) -> bytes: ...
@overload
def subn(self: Pattern[str], repl: str | Callable[[Match[str]], str], string: str, count: int = ...) -> tuple[str, int]: ...
@overload
def subn(
self: Pattern[bytes],
repl: ReadableBuffer | Callable[[Match[bytes]], ReadableBuffer],
string: ReadableBuffer,
count: int = ...,
) -> tuple[bytes, int]: ...
def __copy__(self) -> Pattern[AnyStr]: ...
def __deepcopy__(self, __memo: Any) -> Pattern[AnyStr]: ...
if sys.version_info >= (3, 9):
def __class_getitem__(cls, item: Any) -> GenericAlias: ...

# Functions

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