Skip to content

Commit bb9a11f

Browse files
authored
Make collections.abc.* generic (#5)
1 parent 9ed17ef commit bb9a11f

File tree

4 files changed

+58
-10
lines changed

4 files changed

+58
-10
lines changed

Lib/_collections_abc.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from abc import ABCMeta, abstractmethod
1010
import sys
11+
from types import GenericAlias
1112

1213
__all__ = ["Awaitable", "Coroutine",
1314
"AsyncIterable", "AsyncIterator", "AsyncGenerator",
@@ -110,6 +111,10 @@ def __subclasshook__(cls, C):
110111
return _check_methods(C, "__await__")
111112
return NotImplemented
112113

114+
def __class_getitem__(cls, item):
115+
"""Internal: PEP 585."""
116+
return GenericAlias(cls, item)
117+
113118

114119
class Coroutine(Awaitable):
115120

@@ -169,6 +174,10 @@ def __subclasshook__(cls, C):
169174
return _check_methods(C, "__aiter__")
170175
return NotImplemented
171176

177+
def __class_getitem__(cls, item):
178+
"""Internal: PEP 585."""
179+
return GenericAlias(cls, item)
180+
172181

173182
class AsyncIterator(AsyncIterable):
174183

@@ -255,6 +264,10 @@ def __subclasshook__(cls, C):
255264
return _check_methods(C, "__iter__")
256265
return NotImplemented
257266

267+
def __class_getitem__(cls, item):
268+
"""Internal: PEP 585."""
269+
return GenericAlias(cls, item)
270+
258271

259272
class Iterator(Iterable):
260273

@@ -274,6 +287,7 @@ def __subclasshook__(cls, C):
274287
return _check_methods(C, '__iter__', '__next__')
275288
return NotImplemented
276289

290+
277291
Iterator.register(bytes_iterator)
278292
Iterator.register(bytearray_iterator)
279293
#Iterator.register(callable_iterator)
@@ -353,6 +367,7 @@ def __subclasshook__(cls, C):
353367
'send', 'throw', 'close')
354368
return NotImplemented
355369

370+
356371
Generator.register(generator)
357372

358373

@@ -385,6 +400,11 @@ def __subclasshook__(cls, C):
385400
return _check_methods(C, "__contains__")
386401
return NotImplemented
387402

403+
def __class_getitem__(cls, item):
404+
"""Internal: PEP 585."""
405+
return GenericAlias(cls, item)
406+
407+
388408
class Collection(Sized, Iterable, Container):
389409

390410
__slots__ = ()
@@ -395,6 +415,7 @@ def __subclasshook__(cls, C):
395415
return _check_methods(C, "__len__", "__iter__", "__contains__")
396416
return NotImplemented
397417

418+
398419
class Callable(metaclass=ABCMeta):
399420

400421
__slots__ = ()
@@ -409,6 +430,10 @@ def __subclasshook__(cls, C):
409430
return _check_methods(C, "__call__")
410431
return NotImplemented
411432

433+
def __class_getitem__(cls, item):
434+
"""Internal: PEP 585."""
435+
return GenericAlias(cls, item)
436+
412437

413438
### SETS ###
414439

@@ -550,6 +575,7 @@ def _hash(self):
550575
h = 590923713
551576
return h
552577

578+
553579
Set.register(frozenset)
554580

555581

@@ -632,6 +658,7 @@ def __isub__(self, it):
632658
self.discard(value)
633659
return self
634660

661+
635662
MutableSet.register(set)
636663

637664

@@ -688,6 +715,7 @@ def __eq__(self, other):
688715

689716
__reversed__ = None
690717

718+
691719
Mapping.register(mappingproxy)
692720

693721

@@ -704,6 +732,10 @@ def __len__(self):
704732
def __repr__(self):
705733
return '{0.__class__.__name__}({0._mapping!r})'.format(self)
706734

735+
def __class_getitem__(cls, item):
736+
"""Internal: PEP 585."""
737+
return GenericAlias(cls, item)
738+
707739

708740
class KeysView(MappingView, Set):
709741

@@ -719,6 +751,7 @@ def __contains__(self, key):
719751
def __iter__(self):
720752
yield from self._mapping
721753

754+
722755
KeysView.register(dict_keys)
723756

724757

@@ -743,6 +776,7 @@ def __iter__(self):
743776
for key in self._mapping:
744777
yield (key, self._mapping[key])
745778

779+
746780
ItemsView.register(dict_items)
747781

748782

@@ -761,6 +795,7 @@ def __iter__(self):
761795
for key in self._mapping:
762796
yield self._mapping[key]
763797

798+
764799
ValuesView.register(dict_values)
765800

766801

@@ -847,6 +882,7 @@ def setdefault(self, key, default=None):
847882
self[key] = default
848883
return default
849884

885+
850886
MutableMapping.register(dict)
851887

852888

@@ -914,6 +950,7 @@ def count(self, value):
914950
'S.count(value) -> integer -- return number of occurrences of value'
915951
return sum(1 for v in self if v is value or v == value)
916952

953+
917954
Sequence.register(tuple)
918955
Sequence.register(str)
919956
Sequence.register(range)
@@ -1000,5 +1037,6 @@ def __iadd__(self, values):
10001037
self.extend(values)
10011038
return self
10021039

1040+
10031041
MutableSequence.register(list)
10041042
MutableSequence.register(bytearray) # Multiply inheriting, see ByteString

Lib/collections/__init__.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -962,10 +962,6 @@ def __init__(self, dict=None, /, **kwargs):
962962
if kwargs:
963963
self.update(kwargs)
964964

965-
# It's a generic class, just like dict.
966-
def __class_getitem__(cls, item):
967-
return _GenericAlias(cls, item)
968-
969965
def __len__(self): return len(self.data)
970966
def __getitem__(self, key):
971967
if key in self.data:
@@ -1029,8 +1025,6 @@ def __init__(self, initlist=None):
10291025
self.data[:] = initlist.data[:]
10301026
else:
10311027
self.data = list(initlist)
1032-
def __class_getitem__(cls, item):
1033-
return _GenericAlias(cls, item)
10341028
def __repr__(self): return repr(self.data)
10351029
def __lt__(self, other): return self.data < self.__cast(other)
10361030
def __le__(self, other): return self.data <= self.__cast(other)

Lib/test/test_genericalias.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,36 @@
11
"""Tests for C-implemented GenericAlias."""
22

33
import unittest
4-
from collections import defaultdict, deque
4+
from collections import (
5+
defaultdict, deque, OrderedDict, Counter, UserDict, UserList
6+
)
7+
from collections.abc import *
58
from contextlib import AbstractContextManager, AbstractAsyncContextManager
69
from io import IOBase
710
from re import Pattern, Match
811

12+
913
class BaseTest(unittest.TestCase):
1014
"""Test basics."""
1115

1216
def test_subscriptable(self):
1317
for t in (tuple, list, dict, set, frozenset,
14-
defaultdict, deque,
18+
defaultdict, deque,
19+
OrderedDict, Counter, UserDict, UserList,
1520
IOBase,
1621
Pattern, Match,
1722
AbstractContextManager, AbstractAsyncContextManager,
23+
Awaitable, Coroutine,
24+
AsyncIterable, AsyncIterator,
25+
AsyncGenerator, Generator,
26+
Iterable, Iterator,
27+
Reversible,
28+
Container, Collection,
29+
Callable,
30+
Set, MutableSet,
31+
Mapping, MutableMapping, MappingView,
32+
KeysView, ItemsView, ValuesView,
33+
Sequence, MutableSequence,
1834
):
1935
tname = t.__name__
2036
with self.subTest(f"Testing {tname}"):
@@ -24,7 +40,7 @@ def test_subscriptable(self):
2440
self.assertEqual(alias.__parameters__, ())
2541

2642
def test_unsubscriptable(self):
27-
for t in int, str, float:
43+
for t in int, str, float, Sized, Hashable:
2844
tname = t.__name__
2945
with self.subTest(f"Testing {tname}"):
3046
with self.assertRaises(TypeError):

Lib/typing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ class _TypingEllipsis:
946946

947947
_SPECIAL_NAMES = ['__abstractmethods__', '__annotations__', '__dict__', '__doc__',
948948
'__init__', '__module__', '__new__', '__slots__',
949-
'__subclasshook__', '__weakref__']
949+
'__subclasshook__', '__weakref__', '__class_getitem__']
950950

951951
# These special attributes will be not collected as protocol members.
952952
EXCLUDED_ATTRIBUTES = _TYPING_INTERNALS + _SPECIAL_NAMES + ['_MutableMapping__marker']

0 commit comments

Comments
 (0)