1- import asyncio
1+ import functools
22from contextlib import (
33 asynccontextmanager , AbstractAsyncContextManager ,
44 AsyncExitStack , nullcontext , aclosing , contextmanager )
55from test import support
6+ from test .support import run_no_yield_async_fn as _run_async_fn
67import unittest
78import traceback
89
910from test .test_contextlib import TestBaseExitStack
1011
11- support .requires_working_socket (module = True )
1212
13- def tearDownModule ():
14- asyncio .set_event_loop_policy (None )
13+ def _async_test (async_fn ):
14+ """Decorator to turn an async function into a synchronous function"""
15+ @functools .wraps (async_fn )
16+ def wrapper (* args , ** kwargs ):
17+ return _run_async_fn (async_fn , * args , ** kwargs )
1518
19+ return wrapper
1620
17- class TestAbstractAsyncContextManager (unittest .IsolatedAsyncioTestCase ):
1821
22+ class TestAbstractAsyncContextManager (unittest .TestCase ):
23+
24+ @_async_test
1925 async def test_enter (self ):
2026 class DefaultEnter (AbstractAsyncContextManager ):
2127 async def __aexit__ (self , * args ):
@@ -27,6 +33,7 @@ async def __aexit__(self, *args):
2733 async with manager as context :
2834 self .assertIs (manager , context )
2935
36+ @_async_test
3037 async def test_slots (self ):
3138 class DefaultAsyncContextManager (AbstractAsyncContextManager ):
3239 __slots__ = ()
@@ -38,6 +45,7 @@ async def __aexit__(self, *args):
3845 manager = DefaultAsyncContextManager ()
3946 manager .var = 42
4047
48+ @_async_test
4149 async def test_async_gen_propagates_generator_exit (self ):
4250 # A regression test for https://bugs.python.org/issue33786.
4351
@@ -69,27 +77,28 @@ async def __aenter__(self):
6977 async def __aexit__ (self , exc_type , exc_value , traceback ):
7078 return None
7179
72- self .assertTrue ( issubclass ( ManagerFromScratch , AbstractAsyncContextManager ) )
80+ self .assertIsSubclass ( ManagerFromScratch , AbstractAsyncContextManager )
7381
7482 class DefaultEnter (AbstractAsyncContextManager ):
7583 async def __aexit__ (self , * args ):
7684 await super ().__aexit__ (* args )
7785
78- self .assertTrue ( issubclass ( DefaultEnter , AbstractAsyncContextManager ) )
86+ self .assertIsSubclass ( DefaultEnter , AbstractAsyncContextManager )
7987
8088 class NoneAenter (ManagerFromScratch ):
8189 __aenter__ = None
8290
83- self .assertFalse ( issubclass ( NoneAenter , AbstractAsyncContextManager ) )
91+ self .assertNotIsSubclass ( NoneAenter , AbstractAsyncContextManager )
8492
8593 class NoneAexit (ManagerFromScratch ):
8694 __aexit__ = None
8795
88- self .assertFalse ( issubclass ( NoneAexit , AbstractAsyncContextManager ) )
96+ self .assertNotIsSubclass ( NoneAexit , AbstractAsyncContextManager )
8997
9098
91- class AsyncContextManagerTestCase (unittest .IsolatedAsyncioTestCase ):
99+ class AsyncContextManagerTestCase (unittest .TestCase ):
92100
101+ @_async_test
93102 async def test_contextmanager_plain (self ):
94103 state = []
95104 @asynccontextmanager
@@ -103,6 +112,7 @@ async def woohoo():
103112 state .append (x )
104113 self .assertEqual (state , [1 , 42 , 999 ])
105114
115+ @_async_test
106116 async def test_contextmanager_finally (self ):
107117 state = []
108118 @asynccontextmanager
@@ -120,7 +130,8 @@ async def woohoo():
120130 raise ZeroDivisionError ()
121131 self .assertEqual (state , [1 , 42 , 999 ])
122132
123- @unittest .expectedFailure # TODO: RUSTPYTHON
133+ @unittest .expectedFailure # TODO: RUSTPYTHON
134+ @_async_test
124135 async def test_contextmanager_traceback (self ):
125136 @asynccontextmanager
126137 async def f ():
@@ -176,6 +187,7 @@ class StopAsyncIterationSubclass(StopAsyncIteration):
176187 self .assertEqual (frames [0 ].name , 'test_contextmanager_traceback' )
177188 self .assertEqual (frames [0 ].line , 'raise stop_exc' )
178189
190+ @_async_test
179191 async def test_contextmanager_no_reraise (self ):
180192 @asynccontextmanager
181193 async def whee ():
@@ -185,6 +197,7 @@ async def whee():
185197 # Calling __aexit__ should not result in an exception
186198 self .assertFalse (await ctx .__aexit__ (TypeError , TypeError ("foo" ), None ))
187199
200+ @_async_test
188201 async def test_contextmanager_trap_yield_after_throw (self ):
189202 @asynccontextmanager
190203 async def whoo ():
@@ -200,6 +213,7 @@ async def whoo():
200213 # The "gen" attribute is an implementation detail.
201214 self .assertFalse (ctx .gen .ag_suspended )
202215
216+ @_async_test
203217 async def test_contextmanager_trap_no_yield (self ):
204218 @asynccontextmanager
205219 async def whoo ():
@@ -209,6 +223,7 @@ async def whoo():
209223 with self .assertRaises (RuntimeError ):
210224 await ctx .__aenter__ ()
211225
226+ @_async_test
212227 async def test_contextmanager_trap_second_yield (self ):
213228 @asynccontextmanager
214229 async def whoo ():
@@ -222,6 +237,7 @@ async def whoo():
222237 # The "gen" attribute is an implementation detail.
223238 self .assertFalse (ctx .gen .ag_suspended )
224239
240+ @_async_test
225241 async def test_contextmanager_non_normalised (self ):
226242 @asynccontextmanager
227243 async def whoo ():
@@ -235,6 +251,7 @@ async def whoo():
235251 with self .assertRaises (SyntaxError ):
236252 await ctx .__aexit__ (RuntimeError , None , None )
237253
254+ @_async_test
238255 async def test_contextmanager_except (self ):
239256 state = []
240257 @asynccontextmanager
@@ -252,6 +269,7 @@ async def woohoo():
252269 raise ZeroDivisionError (999 )
253270 self .assertEqual (state , [1 , 42 , 999 ])
254271
272+ @_async_test
255273 async def test_contextmanager_except_stopiter (self ):
256274 @asynccontextmanager
257275 async def woohoo ():
@@ -278,6 +296,7 @@ class StopAsyncIterationSubclass(StopAsyncIteration):
278296 else :
279297 self .fail (f'{ stop_exc } was suppressed' )
280298
299+ @_async_test
281300 async def test_contextmanager_wrap_runtimeerror (self ):
282301 @asynccontextmanager
283302 async def woohoo ():
@@ -322,12 +341,14 @@ def test_contextmanager_doc_attrib(self):
322341 self .assertEqual (baz .__doc__ , "Whee!" )
323342
324343 @support .requires_docstrings
344+ @_async_test
325345 async def test_instance_docstring_given_cm_docstring (self ):
326346 baz = self ._create_contextmanager_attribs ()(None )
327347 self .assertEqual (baz .__doc__ , "Whee!" )
328348 async with baz :
329349 pass # suppress warning
330350
351+ @_async_test
331352 async def test_keywords (self ):
332353 # Ensure no keyword arguments are inhibited
333354 @asynccontextmanager
@@ -336,6 +357,7 @@ async def woohoo(self, func, args, kwds):
336357 async with woohoo (self = 11 , func = 22 , args = 33 , kwds = 44 ) as target :
337358 self .assertEqual (target , (11 , 22 , 33 , 44 ))
338359
360+ @_async_test
339361 async def test_recursive (self ):
340362 depth = 0
341363 ncols = 0
@@ -362,6 +384,7 @@ async def recursive():
362384 self .assertEqual (ncols , 10 )
363385 self .assertEqual (depth , 0 )
364386
387+ @_async_test
365388 async def test_decorator (self ):
366389 entered = False
367390
@@ -380,6 +403,7 @@ async def test():
380403 await test ()
381404 self .assertFalse (entered )
382405
406+ @_async_test
383407 async def test_decorator_with_exception (self ):
384408 entered = False
385409
@@ -402,6 +426,7 @@ async def test():
402426 await test ()
403427 self .assertFalse (entered )
404428
429+ @_async_test
405430 async def test_decorating_method (self ):
406431
407432 @asynccontextmanager
@@ -436,14 +461,15 @@ async def method(self, a, b, c=None):
436461 self .assertEqual (test .b , 2 )
437462
438463
439- class AclosingTestCase (unittest .IsolatedAsyncioTestCase ):
464+ class AclosingTestCase (unittest .TestCase ):
440465
441466 @support .requires_docstrings
442467 def test_instance_docs (self ):
443468 cm_docstring = aclosing .__doc__
444469 obj = aclosing (None )
445470 self .assertEqual (obj .__doc__ , cm_docstring )
446471
472+ @_async_test
447473 async def test_aclosing (self ):
448474 state = []
449475 class C :
@@ -455,6 +481,7 @@ async def aclose(self):
455481 self .assertEqual (x , y )
456482 self .assertEqual (state , [1 ])
457483
484+ @_async_test
458485 async def test_aclosing_error (self ):
459486 state = []
460487 class C :
@@ -468,6 +495,7 @@ async def aclose(self):
468495 1 / 0
469496 self .assertEqual (state , [1 ])
470497
498+ @_async_test
471499 async def test_aclosing_bpo41229 (self ):
472500 state = []
473501
@@ -493,45 +521,27 @@ async def agenfunc():
493521 self .assertEqual (state , [1 ])
494522
495523
496- class TestAsyncExitStack (TestBaseExitStack , unittest .IsolatedAsyncioTestCase ):
524+ class TestAsyncExitStack (TestBaseExitStack , unittest .TestCase ):
497525 class SyncAsyncExitStack (AsyncExitStack ):
498- @staticmethod
499- def run_coroutine (coro ):
500- loop = asyncio .get_event_loop_policy ().get_event_loop ()
501- t = loop .create_task (coro )
502- t .add_done_callback (lambda f : loop .stop ())
503- loop .run_forever ()
504-
505- exc = t .exception ()
506- if not exc :
507- return t .result ()
508- else :
509- context = exc .__context__
510-
511- try :
512- raise exc
513- except :
514- exc .__context__ = context
515- raise exc
516526
517527 def close (self ):
518- return self . run_coroutine (self .aclose () )
528+ return _run_async_fn (self .aclose )
519529
520530 def __enter__ (self ):
521- return self . run_coroutine (self .__aenter__ () )
531+ return _run_async_fn (self .__aenter__ )
522532
523533 def __exit__ (self , * exc_details ):
524- return self . run_coroutine (self .__aexit__ ( * exc_details ) )
534+ return _run_async_fn (self .__aexit__ , * exc_details )
525535
526536 exit_stack = SyncAsyncExitStack
527537 callback_error_internal_frames = [
528- ('__exit__' , 'return self.run_coroutine(self.__aexit__(*exc_details))' ),
529- ('run_coroutine' , 'raise exc' ),
530- ('run_coroutine' , 'raise exc' ),
538+ ('__exit__' , 'return _run_async_fn(self.__aexit__, *exc_details)' ),
539+ ('run_no_yield_async_fn' , 'coro.send(None)' ),
531540 ('__aexit__' , 'raise exc' ),
532541 ('__aexit__' , 'cb_suppress = cb(*exc_details)' ),
533542 ]
534543
544+ @_async_test
535545 async def test_async_callback (self ):
536546 expected = [
537547 ((), {}),
@@ -574,6 +584,7 @@ async def _exit(*args, **kwds):
574584 stack .push_async_callback (callback = _exit , arg = 3 )
575585 self .assertEqual (result , [])
576586
587+ @_async_test
577588 async def test_async_push (self ):
578589 exc_raised = ZeroDivisionError
579590 async def _expect_exc (exc_type , exc , exc_tb ):
@@ -609,6 +620,7 @@ async def __aexit__(self, *exc_details):
609620 self .assertIs (stack ._exit_callbacks [- 1 ][1 ], _expect_exc )
610621 1 / 0
611622
623+ @_async_test
612624 async def test_enter_async_context (self ):
613625 class TestCM (object ):
614626 async def __aenter__ (self ):
@@ -630,6 +642,7 @@ async def _exit():
630642
631643 self .assertEqual (result , [1 , 2 , 3 , 4 ])
632644
645+ @_async_test
633646 async def test_enter_async_context_errors (self ):
634647 class LacksEnterAndExit :
635648 pass
@@ -649,6 +662,7 @@ async def __aenter__(self):
649662 await stack .enter_async_context (LacksExit ())
650663 self .assertFalse (stack ._exit_callbacks )
651664
665+ @_async_test
652666 async def test_async_exit_exception_chaining (self ):
653667 # Ensure exception chaining matches the reference behaviour
654668 async def raise_exc (exc ):
@@ -680,6 +694,7 @@ async def suppress_exc(*exc_details):
680694 self .assertIsInstance (inner_exc , ValueError )
681695 self .assertIsInstance (inner_exc .__context__ , ZeroDivisionError )
682696
697+ @_async_test
683698 async def test_async_exit_exception_explicit_none_context (self ):
684699 # Ensure AsyncExitStack chaining matches actual nested `with` statements
685700 # regarding explicit __context__ = None.
@@ -714,6 +729,7 @@ async def my_cm_with_exit_stack():
714729 else :
715730 self .fail ("Expected IndexError, but no exception was raised" )
716731
732+ @_async_test
717733 async def test_instance_bypass_async (self ):
718734 class Example (object ): pass
719735 cm = Example ()
@@ -726,8 +742,8 @@ class Example(object): pass
726742 self .assertIs (stack ._exit_callbacks [- 1 ][1 ], cm )
727743
728744
729-
730- class TestAsyncNullcontext ( unittest . IsolatedAsyncioTestCase ):
745+ class TestAsyncNullcontext ( unittest . TestCase ):
746+ @ _async_test
731747 async def test_async_nullcontext (self ):
732748 class C :
733749 pass
0 commit comments