Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit75cd8e4

Browse files
authored
bpo-29587: Make gen.throw() chain exceptions with yield from (GH-19858)
The previous commits onbpo-29587 got exception chaining workingwith gen.throw() in the `yield` case. This patch also gets the`yield from` case working.As a consequence, implicit exception chaining now also works inthe asyncio scenario of awaiting on a task when an exception isalready active.Tests are included for both the asyncio case and the puregenerator-only case.
1 parentd6fb53f commit75cd8e4

File tree

3 files changed

+57
-11
lines changed

3 files changed

+57
-11
lines changed

‎Lib/test/test_asyncio/test_tasks.py‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,33 @@ async def inner2():
466466
t=outer()
467467
self.assertEqual(self.loop.run_until_complete(t),1042)
468468

469+
deftest_exception_chaining_after_await(self):
470+
# Test that when awaiting on a task when an exception is already
471+
# active, if the task raises an exception it will be chained
472+
# with the original.
473+
loop=asyncio.new_event_loop()
474+
self.set_event_loop(loop)
475+
476+
asyncdefraise_error():
477+
raiseValueError
478+
479+
asyncdefrun():
480+
try:
481+
raiseKeyError(3)
482+
exceptExceptionasexc:
483+
task=self.new_task(loop,raise_error())
484+
try:
485+
awaittask
486+
exceptExceptionasexc:
487+
self.assertEqual(type(exc),ValueError)
488+
chained=exc.__context__
489+
self.assertEqual((type(chained),chained.args),
490+
(KeyError, (3,)))
491+
492+
task=self.new_task(loop,run())
493+
loop.run_until_complete(task)
494+
loop.close()
495+
469496
deftest_cancel(self):
470497

471498
defgen():

‎Lib/test/test_generators.py‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def g():
318318

319319
classGeneratorThrowTest(unittest.TestCase):
320320

321-
deftest_exception_context_set(self):
321+
deftest_exception_context_with_yield(self):
322322
deff():
323323
try:
324324
raiseKeyError('a')
@@ -332,6 +332,23 @@ def f():
332332
context=cm.exception.__context__
333333
self.assertEqual((type(context),context.args), (KeyError, ('a',)))
334334

335+
deftest_exception_context_with_yield_from(self):
336+
deff():
337+
yield
338+
339+
defg():
340+
try:
341+
raiseKeyError('a')
342+
exceptException:
343+
yieldfromf()
344+
345+
gen=g()
346+
gen.send(None)
347+
withself.assertRaises(ValueError)ascm:
348+
gen.throw(ValueError)
349+
context=cm.exception.__context__
350+
self.assertEqual((type(context),context.args), (KeyError, ('a',)))
351+
335352
deftest_throw_after_none_exc_type(self):
336353
defg():
337354
try:

‎Objects/genobject.c‎

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,18 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing)
217217
assert(f->f_back==NULL);
218218
f->f_back=tstate->frame;
219219

220+
_PyErr_StackItem*gi_exc_state=&gen->gi_exc_state;
221+
if (exc&&gi_exc_state->exc_type!=NULL&&
222+
gi_exc_state->exc_type!=Py_None)
223+
{
224+
Py_INCREF(gi_exc_state->exc_type);
225+
Py_XINCREF(gi_exc_state->exc_value);
226+
Py_XINCREF(gi_exc_state->exc_traceback);
227+
_PyErr_ChainExceptions(gi_exc_state->exc_type,
228+
gi_exc_state->exc_value,
229+
gi_exc_state->exc_traceback);
230+
}
231+
220232
gen->gi_running=1;
221233
gen->gi_exc_state.previous_item=tstate->exc_info;
222234
tstate->exc_info=&gen->gi_exc_state;
@@ -512,16 +524,6 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
512524
}
513525

514526
PyErr_Restore(typ,val,tb);
515-
516-
_PyErr_StackItem*gi_exc_state=&gen->gi_exc_state;
517-
if (gi_exc_state->exc_type!=NULL&&gi_exc_state->exc_type!=Py_None) {
518-
Py_INCREF(gi_exc_state->exc_type);
519-
Py_XINCREF(gi_exc_state->exc_value);
520-
Py_XINCREF(gi_exc_state->exc_traceback);
521-
_PyErr_ChainExceptions(gi_exc_state->exc_type,
522-
gi_exc_state->exc_value,
523-
gi_exc_state->exc_traceback);
524-
}
525527
returngen_send_ex(gen,Py_None,1,0);
526528

527529
failed_throw:

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp