Skip to content

Commit d16e3cb

Browse files
author
Anselm Kruis
committed
Merge with branch default.
This merge breaks the Stackless reference counting in Python/ceval.c
2 parents f491db9 + baaadbf commit d16e3cb

File tree

2 files changed

+119
-1
lines changed

2 files changed

+119
-1
lines changed

Lib/test/test_coroutines.py

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,31 @@ async def foo():
492492
run_async(foo())
493493

494494
def test_with_7(self):
495+
class CM:
496+
async def __aenter__(self):
497+
return self
498+
499+
def __aexit__(self, *e):
500+
return 444
501+
502+
async def foo():
503+
async with CM():
504+
1/0
505+
506+
try:
507+
run_async(foo())
508+
except TypeError as exc:
509+
self.assertRegex(
510+
exc.args[0], "object int can't be used in 'await' expression")
511+
self.assertTrue(exc.__context__ is not None)
512+
self.assertTrue(isinstance(exc.__context__, ZeroDivisionError))
513+
else:
514+
self.fail('invalid asynchronous context manager did not fail')
515+
516+
517+
def test_with_8(self):
518+
CNT = 0
519+
495520
class CM:
496521
async def __aenter__(self):
497522
return self
@@ -500,14 +525,105 @@ def __aexit__(self, *e):
500525
return 456
501526

502527
async def foo():
528+
nonlocal CNT
503529
async with CM():
504-
pass
530+
CNT += 1
531+
505532

506533
with self.assertRaisesRegex(
507534
TypeError, "object int can't be used in 'await' expression"):
508535

509536
run_async(foo())
510537

538+
self.assertEqual(CNT, 1)
539+
540+
541+
def test_with_9(self):
542+
CNT = 0
543+
544+
class CM:
545+
async def __aenter__(self):
546+
return self
547+
548+
async def __aexit__(self, *e):
549+
1/0
550+
551+
async def foo():
552+
nonlocal CNT
553+
async with CM():
554+
CNT += 1
555+
556+
with self.assertRaises(ZeroDivisionError):
557+
run_async(foo())
558+
559+
self.assertEqual(CNT, 1)
560+
561+
def test_with_10(self):
562+
CNT = 0
563+
564+
class CM:
565+
async def __aenter__(self):
566+
return self
567+
568+
async def __aexit__(self, *e):
569+
1/0
570+
571+
async def foo():
572+
nonlocal CNT
573+
async with CM():
574+
async with CM():
575+
raise RuntimeError
576+
577+
try:
578+
run_async(foo())
579+
except ZeroDivisionError as exc:
580+
self.assertTrue(exc.__context__ is not None)
581+
self.assertTrue(isinstance(exc.__context__, ZeroDivisionError))
582+
self.assertTrue(isinstance(exc.__context__.__context__,
583+
RuntimeError))
584+
else:
585+
self.fail('exception from __aexit__ did not propagate')
586+
587+
def test_with_11(self):
588+
CNT = 0
589+
590+
class CM:
591+
async def __aenter__(self):
592+
raise NotImplementedError
593+
594+
async def __aexit__(self, *e):
595+
1/0
596+
597+
async def foo():
598+
nonlocal CNT
599+
async with CM():
600+
raise RuntimeError
601+
602+
try:
603+
run_async(foo())
604+
except NotImplementedError as exc:
605+
self.assertTrue(exc.__context__ is None)
606+
else:
607+
self.fail('exception from __aenter__ did not propagate')
608+
609+
def test_with_12(self):
610+
CNT = 0
611+
612+
class CM:
613+
async def __aenter__(self):
614+
return self
615+
616+
async def __aexit__(self, *e):
617+
return True
618+
619+
async def foo():
620+
nonlocal CNT
621+
async with CM() as cm:
622+
self.assertIs(cm.__class__, CM)
623+
raise RuntimeError
624+
625+
run_async(foo())
626+
511627
def test_for_1(self):
512628
aiter_calls = 0
513629

Python/ceval.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3800,6 +3800,7 @@ slp_eval_frame_value(PyFrameObject *f, int throwflag, PyObject *retval)
38003800
if (res == NULL)
38013801
goto error;
38023802

3803+
Py_INCREF(exc); /* Duplicating the exception on the stack */
38033804
PUSH(exc);
38043805
PUSH(res);
38053806
PREDICT(WITH_CLEANUP_FINISH);
@@ -3818,6 +3819,7 @@ slp_eval_frame_value(PyFrameObject *f, int throwflag, PyObject *retval)
38183819
err = 0;
38193820

38203821
Py_DECREF(res);
3822+
Py_DECREF(exc);
38213823

38223824
if (err < 0)
38233825
goto error;

0 commit comments

Comments
 (0)