Skip to content
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
180 changes: 124 additions & 56 deletions addons/source-python/Python3/_collections_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
from abc import ABCMeta, abstractmethod
import sys

__all__ = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator",
"Hashable", "Iterable", "Iterator", "Generator",
"Sized", "Container", "Callable",
__all__ = ["Awaitable", "Coroutine",
"AsyncIterable", "AsyncIterator", "AsyncGenerator",
"Hashable", "Iterable", "Iterator", "Generator", "Reversible",
"Sized", "Container", "Callable", "Collection",
"Set", "MutableSet",
"Mapping", "MutableMapping",
"MappingView", "KeysView", "ItemsView", "ValuesView",
Expand All @@ -29,8 +30,8 @@
# so that they will pass tests like:
# it = iter(somebytearray)
# assert isinstance(it, Iterable)
# Note: in other implementations, these types many not be distinct
# and they make have their own implementation specific types that
# Note: in other implementations, these types might not be distinct
# and they may have their own implementation specific types that
# are not included on this list.
bytes_iterator = type(iter(b''))
bytearray_iterator = type(iter(bytearray()))
Expand All @@ -41,6 +42,7 @@
list_iterator = type(iter([]))
list_reverseiterator = type(iter(reversed([])))
range_iterator = type(iter(range(0)))
longrange_iterator = type(iter(range(1 << 1000)))
set_iterator = type(iter(set()))
str_iterator = type(iter(""))
tuple_iterator = type(iter(()))
Expand All @@ -58,10 +60,27 @@ async def _coro(): pass
coroutine = type(_coro)
_coro.close() # Prevent ResourceWarning
del _coro
## asynchronous generator ##
async def _ag(): yield
_ag = _ag()
async_generator = type(_ag)
del _ag


### ONE-TRICK PONIES ###

def _check_methods(C, *methods):
mro = C.__mro__
for method in methods:
for B in mro:
if method in B.__dict__:
if B.__dict__[method] is None:
return NotImplemented
break
else:
return NotImplemented
return True

class Hashable(metaclass=ABCMeta):

__slots__ = ()
Expand All @@ -73,11 +92,7 @@ def __hash__(self):
@classmethod
def __subclasshook__(cls, C):
if cls is Hashable:
for B in C.__mro__:
if "__hash__" in B.__dict__:
if B.__dict__["__hash__"]:
return True
break
return _check_methods(C, "__hash__")
return NotImplemented


Expand All @@ -92,11 +107,7 @@ def __await__(self):
@classmethod
def __subclasshook__(cls, C):
if cls is Awaitable:
for B in C.__mro__:
if "__await__" in B.__dict__:
if B.__dict__["__await__"]:
return True
break
return _check_methods(C, "__await__")
return NotImplemented


Expand Down Expand Up @@ -137,14 +148,7 @@ def close(self):
@classmethod
def __subclasshook__(cls, C):
if cls is Coroutine:
mro = C.__mro__
for method in ('__await__', 'send', 'throw', 'close'):
for base in mro:
if method in base.__dict__:
break
else:
return NotImplemented
return True
return _check_methods(C, '__await__', 'send', 'throw', 'close')
return NotImplemented


Expand All @@ -156,14 +160,13 @@ class AsyncIterable(metaclass=ABCMeta):
__slots__ = ()

@abstractmethod
async def __aiter__(self):
def __aiter__(self):
return AsyncIterator()

@classmethod
def __subclasshook__(cls, C):
if cls is AsyncIterable:
if any("__aiter__" in B.__dict__ for B in C.__mro__):
return True
return _check_methods(C, "__aiter__")
return NotImplemented


Expand All @@ -176,18 +179,67 @@ async def __anext__(self):
"""Return the next item or raise StopAsyncIteration when exhausted."""
raise StopAsyncIteration

async def __aiter__(self):
def __aiter__(self):
return self

@classmethod
def __subclasshook__(cls, C):
if cls is AsyncIterator:
if (any("__anext__" in B.__dict__ for B in C.__mro__) and
any("__aiter__" in B.__dict__ for B in C.__mro__)):
return True
return _check_methods(C, "__anext__", "__aiter__")
return NotImplemented


class AsyncGenerator(AsyncIterator):

__slots__ = ()

async def __anext__(self):
"""Return the next item from the asynchronous generator.
When exhausted, raise StopAsyncIteration.
"""
return await self.asend(None)

@abstractmethod
async def asend(self, value):
"""Send a value into the asynchronous generator.
Return next yielded value or raise StopAsyncIteration.
"""
raise StopAsyncIteration

@abstractmethod
async def athrow(self, typ, val=None, tb=None):
"""Raise an exception in the asynchronous generator.
Return next yielded value or raise StopAsyncIteration.
"""
if val is None:
if tb is None:
raise typ
val = typ()
if tb is not None:
val = val.with_traceback(tb)
raise val

async def aclose(self):
"""Raise GeneratorExit inside coroutine.
"""
try:
await self.athrow(GeneratorExit)
except (GeneratorExit, StopAsyncIteration):
pass
else:
raise RuntimeError("asynchronous generator ignored GeneratorExit")

@classmethod
def __subclasshook__(cls, C):
if cls is AsyncGenerator:
return _check_methods(C, '__aiter__', '__anext__',
'asend', 'athrow', 'aclose')
return NotImplemented


AsyncGenerator.register(async_generator)


class Iterable(metaclass=ABCMeta):

__slots__ = ()
Expand All @@ -200,8 +252,7 @@ def __iter__(self):
@classmethod
def __subclasshook__(cls, C):
if cls is Iterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return _check_methods(C, "__iter__")
return NotImplemented


Expand All @@ -220,9 +271,7 @@ def __iter__(self):
@classmethod
def __subclasshook__(cls, C):
if cls is Iterator:
if (any("__next__" in B.__dict__ for B in C.__mro__) and
any("__iter__" in B.__dict__ for B in C.__mro__)):
return True
return _check_methods(C, '__iter__', '__next__')
return NotImplemented

Iterator.register(bytes_iterator)
Expand All @@ -234,12 +283,29 @@ def __subclasshook__(cls, C):
Iterator.register(list_iterator)
Iterator.register(list_reverseiterator)
Iterator.register(range_iterator)
Iterator.register(longrange_iterator)
Iterator.register(set_iterator)
Iterator.register(str_iterator)
Iterator.register(tuple_iterator)
Iterator.register(zip_iterator)


class Reversible(Iterable):

__slots__ = ()

@abstractmethod
def __reversed__(self):
while False:
yield None

@classmethod
def __subclasshook__(cls, C):
if cls is Reversible:
return _check_methods(C, "__reversed__", "__iter__")
return NotImplemented


class Generator(Iterator):

__slots__ = ()
Expand Down Expand Up @@ -283,17 +349,10 @@ def close(self):
@classmethod
def __subclasshook__(cls, C):
if cls is Generator:
mro = C.__mro__
for method in ('__iter__', '__next__', 'send', 'throw', 'close'):
for base in mro:
if method in base.__dict__:
break
else:
return NotImplemented
return True
return _check_methods(C, '__iter__', '__next__',
'send', 'throw', 'close')
return NotImplemented


Generator.register(generator)


Expand All @@ -308,8 +367,7 @@ def __len__(self):
@classmethod
def __subclasshook__(cls, C):
if cls is Sized:
if any("__len__" in B.__dict__ for B in C.__mro__):
return True
return _check_methods(C, "__len__")
return NotImplemented


Expand All @@ -324,10 +382,18 @@ def __contains__(self, x):
@classmethod
def __subclasshook__(cls, C):
if cls is Container:
if any("__contains__" in B.__dict__ for B in C.__mro__):
return True
return _check_methods(C, "__contains__")
return NotImplemented

class Collection(Sized, Iterable, Container):

__slots__ = ()

@classmethod
def __subclasshook__(cls, C):
if cls is Collection:
return _check_methods(C, "__len__", "__iter__", "__contains__")
return NotImplemented

class Callable(metaclass=ABCMeta):

Expand All @@ -340,15 +406,14 @@ def __call__(self, *args, **kwds):
@classmethod
def __subclasshook__(cls, C):
if cls is Callable:
if any("__call__" in B.__dict__ for B in C.__mro__):
return True
return _check_methods(C, "__call__")
return NotImplemented


### SETS ###


class Set(Sized, Iterable, Container):
class Set(Collection):

"""A set is a finite, iterable container.

Expand Down Expand Up @@ -573,7 +638,7 @@ def __isub__(self, it):
### MAPPINGS ###


class Mapping(Sized, Iterable, Container):
class Mapping(Collection):

__slots__ = ()

Expand Down Expand Up @@ -621,6 +686,8 @@ def __eq__(self, other):
return NotImplemented
return dict(self.items()) == dict(other.items())

__reversed__ = None

Mapping.register(mappingproxy)


Expand Down Expand Up @@ -670,7 +737,7 @@ def __contains__(self, item):
except KeyError:
return False
else:
return v == value
return v is value or v == value

def __iter__(self):
for key in self._mapping:
Expand All @@ -685,7 +752,8 @@ class ValuesView(MappingView):

def __contains__(self, value):
for key in self._mapping:
if value == self._mapping[key]:
v = self._mapping[key]
if v is value or v == value:
return True
return False

Expand Down Expand Up @@ -794,7 +862,7 @@ def setdefault(self, key, default=None):
### SEQUENCES ###


class Sequence(Sized, Iterable, Container):
class Sequence(Reversible, Collection):

"""All the operations on a read-only sequence.

Expand All @@ -820,7 +888,7 @@ def __iter__(self):

def __contains__(self, value):
for v in self:
if v == value:
if v is value or v == value:
return True
return False

Expand Down
14 changes: 14 additions & 0 deletions addons/source-python/Python3/_compat_pickle.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@
'DocXMLRPCServer': 'xmlrpc.server',
'SimpleHTTPServer': 'http.server',
'CGIHTTPServer': 'http.server',
# For compatibility with broken pickles saved in old Python 3 versions
'UserDict': 'collections',
'UserList': 'collections',
'UserString': 'collections',
'whichdb': 'dbm',
'StringIO': 'io',
'cStringIO': 'io',
})

REVERSE_IMPORT_MAPPING.update({
Expand Down Expand Up @@ -235,3 +242,10 @@

for excname in PYTHON3_OSERROR_EXCEPTIONS:
REVERSE_NAME_MAPPING[('builtins', excname)] = ('exceptions', 'OSError')

PYTHON3_IMPORTERROR_EXCEPTIONS = (
'ModuleNotFoundError',
)

for excname in PYTHON3_IMPORTERROR_EXCEPTIONS:
REVERSE_NAME_MAPPING[('builtins', excname)] = ('exceptions', 'ImportError')
Loading