bpo-39481: Implementation for PEP 585 (#18239)

This implements things like `list[int]`,
which returns an object of type `types.GenericAlias`.
This object mostly acts as a proxy for `list`,
but has attributes `__origin__` and `__args__`
that allow recovering the parts (with values `list` and `(int,)`.

There is also an approximate notion of type variables;
e.g. `list[T]` has a `__parameters__` attribute equal to `(T,)`.
Type variables are objects of type `typing.TypeVar`.
This commit is contained in:
Guido van Rossum 2020-04-07 09:50:06 -07:00 committed by GitHub
parent 9cc3ebd7e0
commit 48b069a003
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 830 additions and 53 deletions

View file

@ -9,6 +9,8 @@ Unit tests are in test_collections.
from abc import ABCMeta, abstractmethod
import sys
GenericAlias = type(list[int])
__all__ = ["Awaitable", "Coroutine",
"AsyncIterable", "AsyncIterator", "AsyncGenerator",
"Hashable", "Iterable", "Iterator", "Generator", "Reversible",
@ -110,6 +112,8 @@ class Awaitable(metaclass=ABCMeta):
return _check_methods(C, "__await__")
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
class Coroutine(Awaitable):
@ -169,6 +173,8 @@ class AsyncIterable(metaclass=ABCMeta):
return _check_methods(C, "__aiter__")
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
class AsyncIterator(AsyncIterable):
@ -255,6 +261,8 @@ class Iterable(metaclass=ABCMeta):
return _check_methods(C, "__iter__")
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
class Iterator(Iterable):
@ -274,6 +282,7 @@ class Iterator(Iterable):
return _check_methods(C, '__iter__', '__next__')
return NotImplemented
Iterator.register(bytes_iterator)
Iterator.register(bytearray_iterator)
#Iterator.register(callable_iterator)
@ -353,6 +362,7 @@ class Generator(Iterator):
'send', 'throw', 'close')
return NotImplemented
Generator.register(generator)
@ -385,6 +395,9 @@ class Container(metaclass=ABCMeta):
return _check_methods(C, "__contains__")
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
class Collection(Sized, Iterable, Container):
__slots__ = ()
@ -395,6 +408,7 @@ class Collection(Sized, Iterable, Container):
return _check_methods(C, "__len__", "__iter__", "__contains__")
return NotImplemented
class Callable(metaclass=ABCMeta):
__slots__ = ()
@ -409,6 +423,8 @@ class Callable(metaclass=ABCMeta):
return _check_methods(C, "__call__")
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
### SETS ###
@ -550,6 +566,7 @@ class Set(Collection):
h = 590923713
return h
Set.register(frozenset)
@ -632,6 +649,7 @@ class MutableSet(Set):
self.discard(value)
return self
MutableSet.register(set)
@ -688,6 +706,7 @@ class Mapping(Collection):
__reversed__ = None
Mapping.register(mappingproxy)
@ -704,6 +723,8 @@ class MappingView(Sized):
def __repr__(self):
return '{0.__class__.__name__}({0._mapping!r})'.format(self)
__class_getitem__ = classmethod(GenericAlias)
class KeysView(MappingView, Set):
@ -719,6 +740,7 @@ class KeysView(MappingView, Set):
def __iter__(self):
yield from self._mapping
KeysView.register(dict_keys)
@ -743,6 +765,7 @@ class ItemsView(MappingView, Set):
for key in self._mapping:
yield (key, self._mapping[key])
ItemsView.register(dict_items)
@ -761,6 +784,7 @@ class ValuesView(MappingView, Collection):
for key in self._mapping:
yield self._mapping[key]
ValuesView.register(dict_values)
@ -847,6 +871,7 @@ class MutableMapping(Mapping):
self[key] = default
return default
MutableMapping.register(dict)
@ -914,6 +939,7 @@ class Sequence(Reversible, Collection):
'S.count(value) -> integer -- return number of occurrences of value'
return sum(1 for v in self if v is value or v == value)
Sequence.register(tuple)
Sequence.register(str)
Sequence.register(range)
@ -1000,5 +1026,6 @@ class MutableSequence(Sequence):
self.extend(values)
return self
MutableSequence.register(list)
MutableSequence.register(bytearray) # Multiply inheriting, see ByteString