diff --git a/src/core/IronPython.StdLib/lib/_collections_abc.py b/src/core/IronPython.StdLib/lib/_collections_abc.py
index 5f8c3186e..aafd43046 100644
--- a/src/core/IronPython.StdLib/lib/_collections_abc.py
+++ b/src/core/IronPython.StdLib/lib/_collections_abc.py
@@ -9,8 +9,8 @@
from abc import ABCMeta, abstractmethod
import sys
-__all__ = ["Awaitable",
- # "Coroutine", "AsyncIterable", "AsyncIterator", "AsyncGenerator", # https://github.com/IronLanguages/ironpython3/issues/1428
+__all__ = ["Awaitable", "Coroutine",
+ "AsyncIterable", "AsyncIterator", "AsyncGenerator",
"Hashable", "Iterable", "Iterator", "Generator", "Reversible",
"Sized", "Container", "Callable", "Collection",
"Set", "MutableSet",
@@ -54,18 +54,17 @@
## misc ##
mappingproxy = type(type.__dict__)
generator = type((lambda: (yield))())
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# ## coroutine ##
-# async def _coro(): pass
-# _coro = _coro()
-# coroutine = type(_coro)
-# _coro.close() # Prevent ResourceWarning
-# del _coro
-# ## asynchronous generator ##
-# async def _ag(): yield
-# _ag = _ag()
-# async_generator = type(_ag)
-# del _ag
+## coroutine ##
+async def _coro(): pass
+_coro = _coro()
+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 ###
@@ -112,134 +111,133 @@ def __subclasshook__(cls, C):
return NotImplemented
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# class Coroutine(Awaitable):
-#
-# __slots__ = ()
-#
-# @abstractmethod
-# def send(self, value):
-# """Send a value into the coroutine.
-# Return next yielded value or raise StopIteration.
-# """
-# raise StopIteration
-#
-# @abstractmethod
-# def throw(self, typ, val=None, tb=None):
-# """Raise an exception in the coroutine.
-# Return next yielded value or raise StopIteration.
-# """
-# if val is None:
-# if tb is None:
-# raise typ
-# val = typ()
-# if tb is not None:
-# val = val.with_traceback(tb)
-# raise val
-#
-# def close(self):
-# """Raise GeneratorExit inside coroutine.
-# """
-# try:
-# self.throw(GeneratorExit)
-# except (GeneratorExit, StopIteration):
-# pass
-# else:
-# raise RuntimeError("coroutine ignored GeneratorExit")
-#
-# @classmethod
-# def __subclasshook__(cls, C):
-# if cls is Coroutine:
-# return _check_methods(C, '__await__', 'send', 'throw', 'close')
-# return NotImplemented
-#
-#
-# Coroutine.register(coroutine)
-#
-#
-# class AsyncIterable(metaclass=ABCMeta):
-#
-# __slots__ = ()
-#
-# @abstractmethod
-# def __aiter__(self):
-# return AsyncIterator()
-#
-# @classmethod
-# def __subclasshook__(cls, C):
-# if cls is AsyncIterable:
-# return _check_methods(C, "__aiter__")
-# return NotImplemented
-#
-#
-# class AsyncIterator(AsyncIterable):
-#
-# __slots__ = ()
-#
-# @abstractmethod
-# async def __anext__(self):
-# """Return the next item or raise StopAsyncIteration when exhausted."""
-# raise StopAsyncIteration
-#
-# def __aiter__(self):
-# return self
-#
-# @classmethod
-# def __subclasshook__(cls, C):
-# if cls is AsyncIterator:
-# 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 Coroutine(Awaitable):
+
+ __slots__ = ()
+
+ @abstractmethod
+ def send(self, value):
+ """Send a value into the coroutine.
+ Return next yielded value or raise StopIteration.
+ """
+ raise StopIteration
+
+ @abstractmethod
+ def throw(self, typ, val=None, tb=None):
+ """Raise an exception in the coroutine.
+ Return next yielded value or raise StopIteration.
+ """
+ if val is None:
+ if tb is None:
+ raise typ
+ val = typ()
+ if tb is not None:
+ val = val.with_traceback(tb)
+ raise val
+
+ def close(self):
+ """Raise GeneratorExit inside coroutine.
+ """
+ try:
+ self.throw(GeneratorExit)
+ except (GeneratorExit, StopIteration):
+ pass
+ else:
+ raise RuntimeError("coroutine ignored GeneratorExit")
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is Coroutine:
+ return _check_methods(C, '__await__', 'send', 'throw', 'close')
+ return NotImplemented
+
+
+Coroutine.register(coroutine)
+
+
+class AsyncIterable(metaclass=ABCMeta):
+
+ __slots__ = ()
+
+ @abstractmethod
+ def __aiter__(self):
+ return AsyncIterator()
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is AsyncIterable:
+ return _check_methods(C, "__aiter__")
+ return NotImplemented
+
+
+class AsyncIterator(AsyncIterable):
+
+ __slots__ = ()
+
+ @abstractmethod
+ async def __anext__(self):
+ """Return the next item or raise StopAsyncIteration when exhausted."""
+ raise StopAsyncIteration
+
+ def __aiter__(self):
+ return self
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is AsyncIterator:
+ 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):
diff --git a/src/core/IronPython.StdLib/lib/test/test_collections.py b/src/core/IronPython.StdLib/lib/test/test_collections.py
index 9e0774c9a..6f3b44eba 100644
--- a/src/core/IronPython.StdLib/lib/test/test_collections.py
+++ b/src/core/IronPython.StdLib/lib/test/test_collections.py
@@ -19,9 +19,8 @@
from collections import UserDict, UserString, UserList
from collections import ChainMap
from collections import deque
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# from collections.abc import Awaitable, Coroutine
-# from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator
+from collections.abc import Awaitable, Coroutine
+from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator
from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
from collections.abc import Sized, Container, Callable, Collection
from collections.abc import Set, MutableSet
@@ -510,121 +509,120 @@ def _test_gen():
class TestOneTrickPonyABCs(ABCTestCase):
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# def test_Awaitable(self):
-# def gen():
-# yield
-#
-# @types.coroutine
-# def coro():
-# yield
-#
-# async def new_coro():
-# pass
-#
-# class Bar:
-# def __await__(self):
-# yield
-#
-# class MinimalCoro(Coroutine):
-# def send(self, value):
-# return value
-# def throw(self, typ, val=None, tb=None):
-# super().throw(typ, val, tb)
-# def __await__(self):
-# yield
-#
-# non_samples = [None, int(), gen(), object()]
-# for x in non_samples:
-# self.assertNotIsInstance(x, Awaitable)
-# self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
-#
-# samples = [Bar(), MinimalCoro()]
-# for x in samples:
-# self.assertIsInstance(x, Awaitable)
-# self.assertTrue(issubclass(type(x), Awaitable))
-#
-# c = coro()
-# # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
-# # flag don't have '__await__' method, hence can't be instances
-# # of Awaitable. Use inspect.isawaitable to detect them.
-# self.assertNotIsInstance(c, Awaitable)
-#
-# c = new_coro()
-# self.assertIsInstance(c, Awaitable)
-# c.close() # avoid RuntimeWarning that coro() was not awaited
-#
-# class CoroLike: pass
-# Coroutine.register(CoroLike)
-# self.assertTrue(isinstance(CoroLike(), Awaitable))
-# self.assertTrue(issubclass(CoroLike, Awaitable))
-# CoroLike = None
-# support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
-#
-# def test_Coroutine(self):
-# def gen():
-# yield
-#
-# @types.coroutine
-# def coro():
-# yield
-#
-# async def new_coro():
-# pass
-#
-# class Bar:
-# def __await__(self):
-# yield
-#
-# class MinimalCoro(Coroutine):
-# def send(self, value):
-# return value
-# def throw(self, typ, val=None, tb=None):
-# super().throw(typ, val, tb)
-# def __await__(self):
-# yield
-#
-# non_samples = [None, int(), gen(), object(), Bar()]
-# for x in non_samples:
-# self.assertNotIsInstance(x, Coroutine)
-# self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
-#
-# samples = [MinimalCoro()]
-# for x in samples:
-# self.assertIsInstance(x, Awaitable)
-# self.assertTrue(issubclass(type(x), Awaitable))
-#
-# c = coro()
-# # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
-# # flag don't have '__await__' method, hence can't be instances
-# # of Coroutine. Use inspect.isawaitable to detect them.
-# self.assertNotIsInstance(c, Coroutine)
-#
-# c = new_coro()
-# self.assertIsInstance(c, Coroutine)
-# c.close() # avoid RuntimeWarning that coro() was not awaited
-#
-# class CoroLike:
-# def send(self, value):
-# pass
-# def throw(self, typ, val=None, tb=None):
-# pass
-# def close(self):
-# pass
-# def __await__(self):
-# pass
-# self.assertTrue(isinstance(CoroLike(), Coroutine))
-# self.assertTrue(issubclass(CoroLike, Coroutine))
-#
-# class CoroLike:
-# def send(self, value):
-# pass
-# def close(self):
-# pass
-# def __await__(self):
-# pass
-# self.assertFalse(isinstance(CoroLike(), Coroutine))
-# self.assertFalse(issubclass(CoroLike, Coroutine))
+ def test_Awaitable(self):
+ def gen():
+ yield
+
+ @types.coroutine
+ def coro():
+ yield
+
+ async def new_coro():
+ pass
+
+ class Bar:
+ def __await__(self):
+ yield
+
+ class MinimalCoro(Coroutine):
+ def send(self, value):
+ return value
+ def throw(self, typ, val=None, tb=None):
+ super().throw(typ, val, tb)
+ def __await__(self):
+ yield
+
+ non_samples = [None, int(), gen(), object()]
+ for x in non_samples:
+ self.assertNotIsInstance(x, Awaitable)
+ self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
+
+ samples = [Bar(), MinimalCoro()]
+ for x in samples:
+ self.assertIsInstance(x, Awaitable)
+ self.assertTrue(issubclass(type(x), Awaitable))
+
+ c = coro()
+ # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
+ # flag don't have '__await__' method, hence can't be instances
+ # of Awaitable. Use inspect.isawaitable to detect them.
+ self.assertNotIsInstance(c, Awaitable)
+
+ c = new_coro()
+ self.assertIsInstance(c, Awaitable)
+ c.close() # avoid RuntimeWarning that coro() was not awaited
+
+ class CoroLike: pass
+ Coroutine.register(CoroLike)
+ self.assertTrue(isinstance(CoroLike(), Awaitable))
+ self.assertTrue(issubclass(CoroLike, Awaitable))
+ CoroLike = None
+ support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
+
+ def test_Coroutine(self):
+ def gen():
+ yield
+
+ @types.coroutine
+ def coro():
+ yield
+
+ async def new_coro():
+ pass
+
+ class Bar:
+ def __await__(self):
+ yield
+
+ class MinimalCoro(Coroutine):
+ def send(self, value):
+ return value
+ def throw(self, typ, val=None, tb=None):
+ super().throw(typ, val, tb)
+ def __await__(self):
+ yield
+
+ non_samples = [None, int(), gen(), object(), Bar()]
+ for x in non_samples:
+ self.assertNotIsInstance(x, Coroutine)
+ self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
+
+ samples = [MinimalCoro()]
+ for x in samples:
+ self.assertIsInstance(x, Awaitable)
+ self.assertTrue(issubclass(type(x), Awaitable))
+
+ c = coro()
+ # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
+ # flag don't have '__await__' method, hence can't be instances
+ # of Coroutine. Use inspect.isawaitable to detect them.
+ self.assertNotIsInstance(c, Coroutine)
+
+ c = new_coro()
+ self.assertIsInstance(c, Coroutine)
+ c.close() # avoid RuntimeWarning that coro() was not awaited
+
+ class CoroLike:
+ def send(self, value):
+ pass
+ def throw(self, typ, val=None, tb=None):
+ pass
+ def close(self):
+ pass
+ def __await__(self):
+ pass
+ self.assertTrue(isinstance(CoroLike(), Coroutine))
+ self.assertTrue(issubclass(CoroLike, Coroutine))
+
+ class CoroLike:
+ def send(self, value):
+ pass
+ def close(self):
+ pass
+ def __await__(self):
+ pass
+ self.assertFalse(isinstance(CoroLike(), Coroutine))
+ self.assertFalse(issubclass(CoroLike, Coroutine))
def test_Hashable(self):
# Check some non-hashables
@@ -652,40 +650,39 @@ def __hash__(self):
self.validate_abstract_methods(Hashable, '__hash__')
self.validate_isinstance(Hashable, '__hash__')
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# def test_AsyncIterable(self):
-# class AI:
-# async def __aiter__(self):
-# return self
-# self.assertTrue(isinstance(AI(), AsyncIterable))
-# self.assertTrue(issubclass(AI, AsyncIterable))
-# # Check some non-iterables
-# non_samples = [None, object, []]
-# for x in non_samples:
-# self.assertNotIsInstance(x, AsyncIterable)
-# self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
-# self.validate_abstract_methods(AsyncIterable, '__aiter__')
-# self.validate_isinstance(AsyncIterable, '__aiter__')
-#
-# def test_AsyncIterator(self):
-# class AI:
-# async def __aiter__(self):
-# return self
-# async def __anext__(self):
-# raise StopAsyncIteration
-# self.assertTrue(isinstance(AI(), AsyncIterator))
-# self.assertTrue(issubclass(AI, AsyncIterator))
-# non_samples = [None, object, []]
-# # Check some non-iterables
-# for x in non_samples:
-# self.assertNotIsInstance(x, AsyncIterator)
-# self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
-# # Similarly to regular iterators (see issue 10565)
-# class AnextOnly:
-# async def __anext__(self):
-# raise StopAsyncIteration
-# self.assertNotIsInstance(AnextOnly(), AsyncIterator)
-# self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
+ def test_AsyncIterable(self):
+ class AI:
+ async def __aiter__(self):
+ return self
+ self.assertTrue(isinstance(AI(), AsyncIterable))
+ self.assertTrue(issubclass(AI, AsyncIterable))
+ # Check some non-iterables
+ non_samples = [None, object, []]
+ for x in non_samples:
+ self.assertNotIsInstance(x, AsyncIterable)
+ self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
+ self.validate_abstract_methods(AsyncIterable, '__aiter__')
+ self.validate_isinstance(AsyncIterable, '__aiter__')
+
+ def test_AsyncIterator(self):
+ class AI:
+ async def __aiter__(self):
+ return self
+ async def __anext__(self):
+ raise StopAsyncIteration
+ self.assertTrue(isinstance(AI(), AsyncIterator))
+ self.assertTrue(issubclass(AI, AsyncIterator))
+ non_samples = [None, object, []]
+ # Check some non-iterables
+ for x in non_samples:
+ self.assertNotIsInstance(x, AsyncIterator)
+ self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
+ # Similarly to regular iterators (see issue 10565)
+ class AnextOnly:
+ async def __anext__(self):
+ raise StopAsyncIteration
+ self.assertNotIsInstance(AnextOnly(), AsyncIterator)
+ self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
def test_Iterable(self):
# Check some non-iterables
@@ -963,87 +960,86 @@ def throw(self, *args): pass
self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# def test_AsyncGenerator(self):
-# class NonAGen1:
-# def __aiter__(self): return self
-# def __anext__(self): return None
-# def aclose(self): pass
-# def athrow(self, typ, val=None, tb=None): pass
-#
-# class NonAGen2:
-# def __aiter__(self): return self
-# def __anext__(self): return None
-# def aclose(self): pass
-# def asend(self, value): return value
-#
-# class NonAGen3:
-# def aclose(self): pass
-# def asend(self, value): return value
-# def athrow(self, typ, val=None, tb=None): pass
-#
-# non_samples = [
-# None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
-# iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
-# for x in non_samples:
-# self.assertNotIsInstance(x, AsyncGenerator)
-# self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
-#
-# class Gen:
-# def __aiter__(self): return self
-# async def __anext__(self): return None
-# async def aclose(self): pass
-# async def asend(self, value): return value
-# async def athrow(self, typ, val=None, tb=None): pass
-#
-# class MinimalAGen(AsyncGenerator):
-# async def asend(self, value):
-# return value
-# async def athrow(self, typ, val=None, tb=None):
-# await super().athrow(typ, val, tb)
-#
-# async def gen():
-# yield 1
-#
-# samples = [gen(), Gen(), MinimalAGen()]
-# for x in samples:
-# self.assertIsInstance(x, AsyncIterator)
-# self.assertIsInstance(x, AsyncGenerator)
-# self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
-# self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
-#
-# def run_async(coro):
-# result = None
-# while True:
-# try:
-# coro.send(None)
-# except StopIteration as ex:
-# result = ex.args[0] if ex.args else None
-# break
-# return result
-#
-# # mixin tests
-# mgen = MinimalAGen()
-# self.assertIs(mgen, mgen.__aiter__())
-# self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
-# self.assertEqual(2, run_async(mgen.asend(2)))
-# self.assertIsNone(run_async(mgen.aclose()))
-# with self.assertRaises(ValueError):
-# run_async(mgen.athrow(ValueError))
-#
-# class FailOnClose(AsyncGenerator):
-# async def asend(self, value): return value
-# async def athrow(self, *args): raise ValueError
-#
-# with self.assertRaises(ValueError):
-# run_async(FailOnClose().aclose())
-#
-# class IgnoreGeneratorExit(AsyncGenerator):
-# async def asend(self, value): return value
-# async def athrow(self, *args): pass
-#
-# with self.assertRaises(RuntimeError):
-# run_async(IgnoreGeneratorExit().aclose())
+ def test_AsyncGenerator(self):
+ class NonAGen1:
+ def __aiter__(self): return self
+ def __anext__(self): return None
+ def aclose(self): pass
+ def athrow(self, typ, val=None, tb=None): pass
+
+ class NonAGen2:
+ def __aiter__(self): return self
+ def __anext__(self): return None
+ def aclose(self): pass
+ def asend(self, value): return value
+
+ class NonAGen3:
+ def aclose(self): pass
+ def asend(self, value): return value
+ def athrow(self, typ, val=None, tb=None): pass
+
+ non_samples = [
+ None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
+ iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
+ for x in non_samples:
+ self.assertNotIsInstance(x, AsyncGenerator)
+ self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
+
+ class Gen:
+ def __aiter__(self): return self
+ async def __anext__(self): return None
+ async def aclose(self): pass
+ async def asend(self, value): return value
+ async def athrow(self, typ, val=None, tb=None): pass
+
+ class MinimalAGen(AsyncGenerator):
+ async def asend(self, value):
+ return value
+ async def athrow(self, typ, val=None, tb=None):
+ await super().athrow(typ, val, tb)
+
+ async def gen():
+ yield 1
+
+ samples = [gen(), Gen(), MinimalAGen()]
+ for x in samples:
+ self.assertIsInstance(x, AsyncIterator)
+ self.assertIsInstance(x, AsyncGenerator)
+ self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
+ self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
+
+ def run_async(coro):
+ result = None
+ while True:
+ try:
+ coro.send(None)
+ except StopIteration as ex:
+ result = ex.args[0] if ex.args else None
+ break
+ return result
+
+ # mixin tests
+ mgen = MinimalAGen()
+ self.assertIs(mgen, mgen.__aiter__())
+ self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
+ self.assertEqual(2, run_async(mgen.asend(2)))
+ self.assertIsNone(run_async(mgen.aclose()))
+ with self.assertRaises(ValueError):
+ run_async(mgen.athrow(ValueError))
+
+ class FailOnClose(AsyncGenerator):
+ async def asend(self, value): return value
+ async def athrow(self, *args): raise ValueError
+
+ with self.assertRaises(ValueError):
+ run_async(FailOnClose().aclose())
+
+ class IgnoreGeneratorExit(AsyncGenerator):
+ async def asend(self, value): return value
+ async def athrow(self, *args): pass
+
+ with self.assertRaises(RuntimeError):
+ run_async(IgnoreGeneratorExit().aclose())
def test_Sized(self):
non_samples = [None, 42, 3.14, 1j,
diff --git a/src/core/IronPython.StdLib/lib/test/test_grammar.py b/src/core/IronPython.StdLib/lib/test/test_grammar.py
index fb18489cf..e89748067 100644
--- a/src/core/IronPython.StdLib/lib/test/test_grammar.py
+++ b/src/core/IronPython.StdLib/lib/test/test_grammar.py
@@ -1414,77 +1414,77 @@ def __imatmul__(self, o):
m @= 42
self.assertEqual(m.other, 42)
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# def test_async_await(self):
-# async def test():
-# def sum():
-# pass
-# if 1:
-# await someobj()
-#
-# self.assertEqual(test.__name__, 'test')
-# self.assertTrue(bool(test.__code__.co_flags & inspect.CO_COROUTINE))
-#
-# def decorator(func):
-# setattr(func, '_marked', True)
-# return func
-#
-# @decorator
-# async def test2():
-# return 22
-# self.assertTrue(test2._marked)
-# self.assertEqual(test2.__name__, 'test2')
-# self.assertTrue(bool(test2.__code__.co_flags & inspect.CO_COROUTINE))
-#
-# def test_async_for(self):
-# class Done(Exception): pass
-#
-# class AIter:
-# def __aiter__(self):
-# return self
-# async def __anext__(self):
-# raise StopAsyncIteration
-#
-# async def foo():
-# async for i in AIter():
-# pass
-# async for i, j in AIter():
-# pass
-# async for i in AIter():
-# pass
-# else:
-# pass
-# raise Done
-#
-# with self.assertRaises(Done):
-# foo().send(None)
-#
-# def test_async_with(self):
-# class Done(Exception): pass
-#
-# class manager:
-# async def __aenter__(self):
-# return (1, 2)
-# async def __aexit__(self, *exc):
-# return False
-#
-# async def foo():
-# async with manager():
-# pass
-# async with manager() as x:
-# pass
-# async with manager() as (x, y):
-# pass
-# async with manager(), manager():
-# pass
-# async with manager() as x, manager() as y:
-# pass
-# async with manager() as x, manager():
-# pass
-# raise Done
-#
-# with self.assertRaises(Done):
-# foo().send(None)
+ def test_async_await(self):
+ async def test():
+ def sum():
+ pass
+ if 1:
+ await someobj()
+
+ self.assertEqual(test.__name__, 'test')
+ self.assertTrue(bool(test.__code__.co_flags & inspect.CO_COROUTINE))
+
+ def decorator(func):
+ setattr(func, '_marked', True)
+ return func
+
+ @decorator
+ async def test2():
+ return 22
+ self.assertTrue(test2._marked)
+ self.assertEqual(test2.__name__, 'test2')
+ self.assertTrue(bool(test2.__code__.co_flags & inspect.CO_COROUTINE))
+
+ def test_async_for(self):
+ class Done(Exception): pass
+
+ class AIter:
+ def __aiter__(self):
+ return self
+ async def __anext__(self):
+ raise StopAsyncIteration
+
+ async def foo():
+ async for i in AIter():
+ pass
+ async for i, j in AIter():
+ pass
+ async for i in AIter():
+ pass
+ else:
+ pass
+ raise Done
+
+ with self.assertRaises(Done):
+ foo().send(None)
+
+ def test_async_with(self):
+ class Done(Exception): pass
+
+ class manager:
+ async def __aenter__(self):
+ return (1, 2)
+ async def __aexit__(self, *exc):
+ return False
+
+ async def foo():
+ async with manager():
+ pass
+ async with manager() as x:
+ pass
+ async with manager() as (x, y):
+ pass
+ # ironpython: todo implement this
+ #async with manager(), manager():
+ # pass
+ #async with manager() as x, manager() as y:
+ # pass
+ #async with manager() as x, manager():
+ # pass
+ raise Done
+
+ with self.assertRaises(Done):
+ foo().send(None)
if __name__ == '__main__':
diff --git a/src/core/IronPython.StdLib/lib/test/test_types.py b/src/core/IronPython.StdLib/lib/test/test_types.py
index fa935c0ca..73fbdbf9b 100644
--- a/src/core/IronPython.StdLib/lib/test/test_types.py
+++ b/src/core/IronPython.StdLib/lib/test/test_types.py
@@ -1264,8 +1264,7 @@ def test_async_def(self):
# Test that types.coroutine passes 'async def' coroutines
# without modification
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# async def foo(): pass
+ async def foo(): pass
foo_code = foo.__code__
foo_flags = foo.__code__.co_flags
decorated_foo = types.coroutine(foo)
@@ -1456,9 +1455,8 @@ def foo(): return Generator('spam')
wrapper = foo()
self.assertIsInstance(wrapper, types._GeneratorWrapper)
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# async def corofunc():
-# return await foo() + 100
+ async def corofunc():
+ return await foo() + 100
coro = corofunc()
self.assertEqual(coro.send(None), 'spam')
diff --git a/src/core/IronPython.StdLib/lib/test/test_typing.py b/src/core/IronPython.StdLib/lib/test/test_typing.py
index ba46420a9..4843d6faf 100644
--- a/src/core/IronPython.StdLib/lib/test/test_typing.py
+++ b/src/core/IronPython.StdLib/lib/test/test_typing.py
@@ -37,7 +37,7 @@
from test import mod_generics_cache
-PY36 = sys.version_info[:2] >= (3, 6) and not sys.implementation.name == 'ironpython' # https://github.com/IronLanguages/ironpython3/issues/98
+PY36 = sys.version_info[:2] >= (3, 6)
class BaseTestCase(TestCase):
@@ -1647,7 +1647,7 @@ def blah():
blah()
-ASYNCIO = sys.version_info[:2] >= (3, 5) and not sys.implementation.name == 'ironpython' # https://github.com/IronLanguages/ironpython3/issues/98
+ASYNCIO = sys.version_info[:2] >= (3, 5)
ASYNCIO_TESTS = """
import asyncio
diff --git a/src/core/IronPython.StdLib/lib/types.py b/src/core/IronPython.StdLib/lib/types.py
index b59b0681a..84bb5514d 100644
--- a/src/core/IronPython.StdLib/lib/types.py
+++ b/src/core/IronPython.StdLib/lib/types.py
@@ -19,16 +19,15 @@ def _g():
yield 1
GeneratorType = type(_g())
-# https://github.com/IronLanguages/ironpython3/issues/1428
-# async def _c(): pass
-# _c = _c()
-# CoroutineType = type(_c)
-# _c.close() # Prevent ResourceWarning
-#
-# async def _ag():
-# yield
-# _ag = _ag()
-# AsyncGeneratorType = type(_ag)
+async def _c(): pass
+_c = _c()
+CoroutineType = type(_c)
+_c.close() # Prevent ResourceWarning
+
+async def _ag():
+ yield
+_ag = _ag()
+AsyncGeneratorType = type(_ag)
class _C:
def _m(self): pass
@@ -51,8 +50,8 @@ def _m(self): pass
GetSetDescriptorType = type(FunctionType.__code__)
MemberDescriptorType = type(ModuleType.__dict__["__dict__"]) # ironpython: type(FunctionType.__globals__) is getset_descriptor
-del sys, _f, _g, _C, # Not for export
- #_c, # https://github.com/IronLanguages/ironpython3/issues/1428
+del sys, _f, _g, _C, _c, # Not for export
+
# Provide a PEP 3115 compliant mechanism for class creation
def new_class(name, bases=(), kwds=None, exec_body=None):
@@ -228,6 +227,7 @@ def coroutine(func):
# Check if 'func' is a generator function.
# (0x20 == CO_GENERATOR)
if co_flags & 0x20:
+ return func # ironpython: todo figure this out
# TODO: Implement this in C.
co = func.__code__
func.__code__ = CodeType(
diff --git a/src/core/IronPython.StdLib/lib/typing.py b/src/core/IronPython.StdLib/lib/typing.py
index 5744601c8..f2b6aaf3a 100644
--- a/src/core/IronPython.StdLib/lib/typing.py
+++ b/src/core/IronPython.StdLib/lib/typing.py
@@ -1975,30 +1975,30 @@ class AsyncContextManager(Generic[T_co],
__slots__ = ()
__all__.append('AsyncContextManager')
-#elif sys.version_info[:2] >= (3, 5):
-# exec("""
-#class AsyncContextManager(Generic[T_co]):
-# __slots__ = ()
-#
-# async def __aenter__(self):
-# return self
-#
-# @abc.abstractmethod
-# async def __aexit__(self, exc_type, exc_value, traceback):
-# return None
-#
-# @classmethod
-# def __subclasshook__(cls, C):
-# if cls is AsyncContextManager:
-# if sys.version_info[:2] >= (3, 6):
-# return _collections_abc._check_methods(C, "__aenter__", "__aexit__")
-# if (any("__aenter__" in B.__dict__ for B in C.__mro__) and
-# any("__aexit__" in B.__dict__ for B in C.__mro__)):
-# return True
-# return NotImplemented
-#
-#__all__.append('AsyncContextManager')
-#""")
+elif sys.version_info[:2] >= (3, 5):
+ exec("""
+class AsyncContextManager(Generic[T_co]):
+ __slots__ = ()
+
+ async def __aenter__(self):
+ return self
+
+ @abc.abstractmethod
+ async def __aexit__(self, exc_type, exc_value, traceback):
+ return None
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is AsyncContextManager:
+ if sys.version_info[:2] >= (3, 6):
+ return _collections_abc._check_methods(C, "__aenter__", "__aexit__")
+ if (any("__aenter__" in B.__dict__ for B in C.__mro__) and
+ any("__aexit__" in B.__dict__ for B in C.__mro__)):
+ return True
+ return NotImplemented
+
+__all__.append('AsyncContextManager')
+""")
class Dict(dict, MutableMapping[KT, VT], extra=dict):
diff --git a/src/core/IronPython/Compiler/Parser.cs b/src/core/IronPython/Compiler/Parser.cs
index 8853fe6f9..5033b6cf3 100644
--- a/src/core/IronPython/Compiler/Parser.cs
+++ b/src/core/IronPython/Compiler/Parser.cs
@@ -1457,8 +1457,8 @@ private WithItem ParseWithItem() {
// async_stmt: 'async' (funcdef | with_stmt | for_stmt)
private Statement ParseAsyncStmt() {
- var start = GetStart();
Eat(TokenKind.KeywordAsync);
+ var start = GetStart();
switch (PeekToken().Kind) {
case TokenKind.KeywordDef:
diff --git a/src/core/IronPython/Runtime/FunctionAttributes.cs b/src/core/IronPython/Runtime/FunctionAttributes.cs
index 8e7f667e5..5f2a7196c 100644
--- a/src/core/IronPython/Runtime/FunctionAttributes.cs
+++ b/src/core/IronPython/Runtime/FunctionAttributes.cs
@@ -25,7 +25,7 @@ public enum FunctionAttributes {
///
/// Set if the function is a coroutine (async def).
///
- Coroutine = 0x100,
+ Coroutine = 0x80,
///
/// IronPython specific: Set if the function includes nested exception handling and therefore can alter
/// sys.exc_info().
diff --git a/tests/suite/test_socket_stdlib.py b/tests/suite/test_socket_stdlib.py
index a35eed082..cd5360a79 100644
--- a/tests/suite/test_socket_stdlib.py
+++ b/tests/suite/test_socket_stdlib.py
@@ -37,7 +37,7 @@ def load_tests(loader, standard_tests, pattern):
test.test_socket.TestSocketSharing('testTypes'), # https://github.com/IronLanguages/ironpython3/issues/1226
test.test_socket.UnbufferedFileObjectClassTestCase('testSmallReadNonBlocking'), # TODO: figure out
]
- if is_linux or (is_osx and net_version < (10, 0)):
+ if is_mono:
failing_tests += [
test.test_socket.NonBlockingTCPTests('testRecv'), # TODO: figure out
]
@@ -63,10 +63,6 @@ def load_tests(loader, standard_tests, pattern):
skip_tests += [
test.test_socket.NonBlockingTCPTests('testAccept')
]
- if is_osx: # TODO: figure out
- skip_tests += [
- test.test_socket.NonBlockingTCPTests('testRecv'),
- ]
return generate_suite(tests, failing_tests, skip_tests)
diff --git a/tests/suite/test_types_stdlib.py b/tests/suite/test_types_stdlib.py
index b6c41c32e..43db83ef6 100644
--- a/tests/suite/test_types_stdlib.py
+++ b/tests/suite/test_types_stdlib.py
@@ -6,7 +6,7 @@
## Run selected tests from test_types from StdLib
##
-from iptest import is_ironpython, generate_suite, run_test, is_linux, is_netcoreapp21
+from iptest import is_ironpython, generate_suite, run_test
import test.test_types
@@ -17,16 +17,9 @@ def load_tests(loader, standard_tests, pattern):
failing_tests = [
test.test_types.ClassCreationTests('test_bad___prepare__'), # AssertionError
test.test_types.ClassCreationTests('test_one_argument_type'), # AssertionError: TypeError not raised
- test.test_types.CoroutineTests('test_async_def'), # https://github.com/IronLanguages/ironpython3/issues/98
- test.test_types.CoroutineTests('test_duck_coro'), # https://github.com/IronLanguages/ironpython3/issues/98
- test.test_types.CoroutineTests('test_duck_corogen'), # https://github.com/IronLanguages/ironpython3/issues/98
- test.test_types.CoroutineTests('test_duck_functional_gen'), # https://github.com/IronLanguages/ironpython3/issues/98
- test.test_types.CoroutineTests('test_duck_gen'), # https://github.com/IronLanguages/ironpython3/issues/98
test.test_types.CoroutineTests('test_gen'), # https://github.com/IronLanguages/ironpython3/issues/98
test.test_types.CoroutineTests('test_genfunc'), # https://github.com/IronLanguages/ironpython3/issues/98
- test.test_types.CoroutineTests('test_non_gen_values'), # https://github.com/IronLanguages/ironpython3/issues/98
test.test_types.CoroutineTests('test_returning_itercoro'), # https://github.com/IronLanguages/ironpython3/issues/98
- test.test_types.CoroutineTests('test_wrapper_object'), # https://github.com/IronLanguages/ironpython3/issues/98
test.test_types.MappingProxyTests('test_chainmap'), # TypeError: expected dict, got Object_1$1
test.test_types.MappingProxyTests('test_constructor'), # TypeError: expected dict, got Object_1$1
test.test_types.MappingProxyTests('test_customdict'), # AssertionError: False is not true
diff --git a/tests/suite/test_typing_stdlib.py b/tests/suite/test_typing_stdlib.py
index ca9a7ca90..a01ad5245 100644
--- a/tests/suite/test_typing_stdlib.py
+++ b/tests/suite/test_typing_stdlib.py
@@ -16,10 +16,17 @@ def load_tests(loader, standard_tests, pattern):
if is_ironpython:
failing_tests = [
test.test_typing.GenericTests('test_generic_hashes'), # https://github.com/IronLanguages/ironpython3/issues/30
+ test.test_typing.GenericTests('test_init_subclass'), # AttributeError: 'GenericMeta' object has no attribute 'attr'
test.test_typing.GenericTests('test_repr_2'), # https://github.com/IronLanguages/ironpython3/issues/30
test.test_typing.GenericTests('test_parameterized_slots_dict'), # TypeError: slots must be one string or a list of strings
test.test_typing.GenericTests('test_type_erasure_special'), # TypeError: Parameterized Tuple cannot be used with isinstance().
+ test.test_typing.GetTypeHintTests('test_get_type_hints_ClassVar'), # AssertionError
+ test.test_typing.GetTypeHintTests('test_get_type_hints_classes'), # AssertionError
+ test.test_typing.GetTypeHintTests('test_get_type_hints_modules'), # AssertionError
test.test_typing.IOTests('test_io_submodule'), # ImportError: Cannot import name __name__
+ test.test_typing.NamedTupleTests('test_annotation_usage'), # TypeError: __new__() takes exactly 1 argument (3 given)
+ test.test_typing.NamedTupleTests('test_annotation_usage_with_default'), # TypeError: __new__() takes exactly 1 argument (2 given)
+ test.test_typing.NamedTupleTests('test_annotation_usage_with_methods'), # TypeError: __new__() takes exactly 1 argument (2 given)
test.test_typing.RETests('test_basics'), # TypeError: issubclass(): _TypeAlias is not a class nor a tuple of classes
test.test_typing.RETests('test_cannot_subclass'), # AssertionError
test.test_typing.RETests('test_re_submodule'), # ImportError: Cannot import name __name__
@@ -38,7 +45,9 @@ def load_tests(loader, standard_tests, pattern):
test.test_typing.GenericTests('test_type_erasure'),
]
- skip_tests = []
+ skip_tests = [
+ test.test_typing.NamedTupleTests('test_namedtuple_keyword_usage'), # AssertionError
+ ]
return generate_suite(tests, failing_tests, skip_tests)