Skip to content

Commit 7b79d4a

Browse files
Expand protocol allowlist to match CPythons (#676)
1 parent 9e90532 commit 7b79d4a

3 files changed

Lines changed: 19 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
[#149172](https://github.com/python/cpython/pull/149172).
66
- Fix setting of `__required_keys__` and `__optional_keys__` when inheriting
77
keys with the same name.
8+
- Add support for `AsyncIterator`, `io.Reader`, `io.Writer` and `os.PathLike` protocols
9+
as bases for other protocls.
810
- Fix incorrect behaviour on Python 3.9 and Python 3.10 that meant that
911
calling `isinstance` with `typing_extensions.Concatenate[...]` or
1012
`typing_extensions.Unpack[...]` as the first argument could have a different

src/test_typing_extensions.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import inspect
1111
import io
1212
import itertools
13+
import os
1314
import pickle
1415
import re
1516
import subprocess
@@ -3870,9 +3871,15 @@ def test_builtin_protocol_allowlist(self):
38703871
class CustomProtocol(TestCase, Protocol):
38713872
pass
38723873

3874+
class CustomPathLikeProtocol(os.PathLike, Protocol):
3875+
pass
3876+
38733877
class CustomContextManager(typing.ContextManager, Protocol):
38743878
pass
38753879

3880+
class CustomAsyncIterator(typing.AsyncIterator, Protocol):
3881+
pass
3882+
38763883
@skip_if_py312b1
38773884
def test_typing_extensions_protocol_allowlist(self):
38783885
@runtime_checkable
@@ -7110,13 +7117,13 @@ def test_typing_extensions_defers_when_possible(self):
71107117
}
71117118
if sys.version_info < (3, 13):
71127119
exclude |= {
7113-
'NamedTuple', 'Protocol', 'runtime_checkable', 'Generator',
7120+
'NamedTuple', 'runtime_checkable', 'Generator',
71147121
'AsyncGenerator', 'ContextManager', 'AsyncContextManager',
71157122
'ParamSpec', 'TypeVar', 'TypeVarTuple', 'get_type_hints',
71167123
}
71177124
if sys.version_info < (3, 15):
71187125
exclude |= {
7119-
'TypeAliasType'
7126+
'TypeAliasType', 'Protocol'
71207127
}
71217128
if not typing_extensions._PEP_728_IMPLEMENTED:
71227129
exclude |= {'TypedDict', 'is_typeddict'}

src/typing_extensions.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -677,10 +677,13 @@ def __getitem__(self, params):
677677
_PROTO_ALLOWLIST = {
678678
'collections.abc': [
679679
'Callable', 'Awaitable', 'Iterable', 'Iterator', 'AsyncIterable',
680-
'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', 'Buffer',
680+
'AsyncIterator', 'Hashable', 'Sized', 'Container', 'Collection',
681+
'Reversible', 'Buffer',
681682
],
682683
'contextlib': ['AbstractContextManager', 'AbstractAsyncContextManager'],
684+
'io': ['Reader', 'Writer'],
683685
'typing_extensions': ['Buffer'],
686+
'os': ['PathLike'],
684687
}
685688

686689

@@ -704,8 +707,10 @@ def _get_protocol_attrs(cls):
704707

705708
# `__match_args__` attribute was removed from protocol members in 3.13,
706709
# we want to backport this change to older Python versions.
707-
# Breakpoint: https://github.com/python/cpython/pull/110683
708-
if sys.version_info >= (3, 13):
710+
# 3.14 additionally added `io.Reader`, `io.Writer` and `os.PathLike` to
711+
# the list of allowed protocol allowlist.
712+
# https://github.com/python/cpython/issues/127647
713+
if sys.version_info >= (3, 14):
709714
Protocol = typing.Protocol
710715
else:
711716
def _allow_reckless_class_checks(depth=2):

0 commit comments

Comments
 (0)