Expand protocol allowlist to match CPythons (#676)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77b27dd..fcd2db5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@
[#149172](https://github.com/python/cpython/pull/149172).
- Fix setting of `__required_keys__` and `__optional_keys__` when inheriting
keys with the same name.
+- Add support for `AsyncIterator`, `io.Reader`, `io.Writer` and `os.PathLike` protocols
+ as bases for other protocls.
- Fix incorrect behaviour on Python 3.9 and Python 3.10 that meant that
calling `isinstance` with `typing_extensions.Concatenate[...]` or
`typing_extensions.Unpack[...]` as the first argument could have a different
diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py
index c3aede8..54b65f4 100644
--- a/src/test_typing_extensions.py
+++ b/src/test_typing_extensions.py
@@ -10,6 +10,7 @@
import inspect
import io
import itertools
+import os
import pickle
import re
import subprocess
@@ -3870,9 +3871,15 @@
class CustomProtocol(TestCase, Protocol):
pass
+ class CustomPathLikeProtocol(os.PathLike, Protocol):
+ pass
+
class CustomContextManager(typing.ContextManager, Protocol):
pass
+ class CustomAsyncIterator(typing.AsyncIterator, Protocol):
+ pass
+
@skip_if_py312b1
def test_typing_extensions_protocol_allowlist(self):
@runtime_checkable
@@ -7110,13 +7117,13 @@
}
if sys.version_info < (3, 13):
exclude |= {
- 'NamedTuple', 'Protocol', 'runtime_checkable', 'Generator',
+ 'NamedTuple', 'runtime_checkable', 'Generator',
'AsyncGenerator', 'ContextManager', 'AsyncContextManager',
'ParamSpec', 'TypeVar', 'TypeVarTuple', 'get_type_hints',
}
if sys.version_info < (3, 15):
exclude |= {
- 'TypeAliasType'
+ 'TypeAliasType', 'Protocol'
}
if not typing_extensions._PEP_728_IMPLEMENTED:
exclude |= {'TypedDict', 'is_typeddict'}
diff --git a/src/typing_extensions.py b/src/typing_extensions.py
index e370475..712a6ea 100644
--- a/src/typing_extensions.py
+++ b/src/typing_extensions.py
@@ -677,10 +677,13 @@
_PROTO_ALLOWLIST = {
'collections.abc': [
'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable',
- 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', 'Buffer',
+ 'AsyncIterator', 'Hashable', 'Sized', 'Container', 'Collection',
+ 'Reversible', 'Buffer',
],
'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'],
+ 'io': ['Reader', 'Writer'],
'typing_extensions': ['Buffer'],
+ 'os': ['PathLike'],
}
@@ -704,8 +707,10 @@
# `__match_args__` attribute was removed from protocol members in 3.13,
# we want to backport this change to older Python versions.
-# Breakpoint: https://github.com/python/cpython/pull/110683
-if sys.version_info >= (3, 13):
+# 3.14 additionally added `io.Reader`, `io.Writer` and `os.PathLike` to
+# the list of allowed protocol allowlist.
+# https://github.com/python/cpython/issues/127647
+if sys.version_info >= (3, 14):
Protocol = typing.Protocol
else:
def _allow_reckless_class_checks(depth=2):