@@ -452,8 +452,8 @@ gen_close(PyObject *self, PyObject *args)
452452
453453
454454PyDoc_STRVAR (throw_doc ,
455- "throw(value)\n\
456- throw(type[,value[,tb]])\n\
455+ "throw(value, /, *, exc_context=None )\n\
456+ throw(type[,value[,tb]], /, *, exc_context=None )\n\
457457\n\
458458Raise exception in generator, return next yielded value or raise\n\
459459StopIteration.\n\
@@ -592,14 +592,22 @@ _gen_throw(PyGenObject *gen, int close_on_genexit,
592592 return NULL ;
593593}
594594
595+ /*
596+ throw(...) method of builtins.generator instance
597+ throw(value, /, *, exc_context=None)
598+ throw(type[,value[,tb]], /, *, exc_context=None)
595599
600+ Raise exception in generator, return next yielded value or raise
601+ StopIteration.
602+ */
596603static PyObject *
597- gen_throw (PyObject * op , PyObject * const * args , Py_ssize_t nargs )
604+ gen_throw (PyObject * op , PyObject * const * args , Py_ssize_t nargs , PyObject * kwnames )
598605{
599606 PyGenObject * gen = _PyGen_CAST (op );
600607 PyObject * typ ;
601608 PyObject * tb = NULL ;
602609 PyObject * val = NULL ;
610+ PyObject * exc_context = NULL ;
603611
604612 if (!_PyArg_CheckPositional ("throw" , nargs , 1 , 3 )) {
605613 return NULL ;
@@ -612,6 +620,18 @@ gen_throw(PyObject *op, PyObject *const *args, Py_ssize_t nargs)
612620 return NULL ;
613621 }
614622 }
623+
624+ static const char * const _keywords [] = {"" , "" , "" , "exc_context" , NULL };
625+ static _PyArg_Parser _parser = {
626+ .keywords = _keywords ,
627+ .fname = "throw" ,
628+ };
629+ PyObject * argsbuf [4 ];
630+ args = _PyArg_UnpackKeywords (args , nargs , NULL , kwnames , & _parser , 1 , 3 , 0 , 1 , argsbuf );
631+ if (!args ) {
632+ return NULL ;
633+ }
634+
615635 typ = args [0 ];
616636 if (nargs == 3 ) {
617637 val = args [1 ];
@@ -620,6 +640,17 @@ gen_throw(PyObject *op, PyObject *const *args, Py_ssize_t nargs)
620640 else if (nargs == 2 ) {
621641 val = args [1 ];
622642 }
643+
644+ if (kwnames && PyTuple_GET_SIZE (kwnames )){
645+ exc_context = args [3 ];
646+ if (!Py_IsNone (exc_context ) && !PyExceptionInstance_Check (exc_context )){
647+ PyErr_SetString (PyExc_TypeError , "exc_context must be an Exception object or None" );
648+ return NULL ;
649+ }
650+ }
651+ // update the generator's current exception context before throwing the
652+ // exception into it
653+ PyErr_SetHandledException (exc_context == NULL ? Py_None : exc_context );
623654 return _gen_throw (gen , 1 , typ , val , tb );
624655}
625656
@@ -841,7 +872,7 @@ PyDoc_STRVAR(sizeof__doc__,
841872
842873static PyMethodDef gen_methods [] = {
843874 {"send" , gen_send , METH_O , send_doc },
844- {"throw" , _PyCFunction_CAST (gen_throw ), METH_FASTCALL , throw_doc },
875+ {"throw" , _PyCFunction_CAST (gen_throw ), METH_FASTCALL | METH_KEYWORDS , throw_doc },
845876 {"close" , gen_close , METH_NOARGS , close_doc },
846877 {"__sizeof__" , gen_sizeof , METH_NOARGS , sizeof__doc__ },
847878 {"__class_getitem__" , Py_GenericAlias , METH_O |METH_CLASS , PyDoc_STR ("See PEP 585" )},
@@ -1187,8 +1218,8 @@ PyDoc_STRVAR(coro_send_doc,
11871218return next iterated value or raise StopIteration." );
11881219
11891220PyDoc_STRVAR (coro_throw_doc ,
1190- "throw(value)\n\
1191- throw(type[,value[,traceback]] )\n\
1221+ "throw(value, /, *, exc_context=None )\n\
1222+ throw(type[,value[,tb]], *, exc_context=None )\n\
11921223\n\
11931224Raise exception in coroutine, return next iterated value or raise\n\
11941225StopIteration.\n\
@@ -1201,7 +1232,7 @@ PyDoc_STRVAR(coro_close_doc,
12011232
12021233static PyMethodDef coro_methods [] = {
12031234 {"send" , gen_send , METH_O , coro_send_doc },
1204- {"throw" ,_PyCFunction_CAST (gen_throw ), METH_FASTCALL , coro_throw_doc },
1235+ {"throw" , _PyCFunction_CAST (gen_throw ), METH_FASTCALL | METH_KEYWORDS , coro_throw_doc },
12051236 {"close" , gen_close , METH_NOARGS , coro_close_doc },
12061237 {"__sizeof__" , gen_sizeof , METH_NOARGS , sizeof__doc__ },
12071238 {"__class_getitem__" , Py_GenericAlias , METH_O |METH_CLASS , PyDoc_STR ("See PEP 585" )},
@@ -1291,10 +1322,10 @@ coro_wrapper_send(PyObject *self, PyObject *arg)
12911322}
12921323
12931324static PyObject *
1294- coro_wrapper_throw (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
1325+ coro_wrapper_throw (PyObject * self , PyObject * const * args , Py_ssize_t nargs , PyObject * kwnames )
12951326{
12961327 PyCoroWrapper * cw = _PyCoroWrapper_CAST (self );
1297- return gen_throw ((PyObject * )cw -> cw_coroutine , args , nargs );
1328+ return gen_throw ((PyObject * )cw -> cw_coroutine , args , nargs , kwnames );
12981329}
12991330
13001331static PyObject *
@@ -1314,8 +1345,8 @@ coro_wrapper_traverse(PyObject *self, visitproc visit, void *arg)
13141345
13151346static PyMethodDef coro_wrapper_methods [] = {
13161347 {"send" , coro_wrapper_send , METH_O , coro_send_doc },
1317- {"throw" , _PyCFunction_CAST (coro_wrapper_throw ), METH_FASTCALL ,
1318- coro_throw_doc },
1348+ {"throw" , _PyCFunction_CAST (coro_wrapper_throw ),
1349+ METH_FASTCALL | METH_KEYWORDS , coro_throw_doc },
13191350 {"close" , coro_wrapper_close , METH_NOARGS , coro_close_doc },
13201351 {NULL , NULL } /* Sentinel */
13211352};
@@ -1827,7 +1858,7 @@ async_gen_asend_iternext(PyObject *ags)
18271858
18281859
18291860static PyObject *
1830- async_gen_asend_throw (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
1861+ async_gen_asend_throw (PyObject * self , PyObject * const * args , Py_ssize_t nargs , PyObject * kwnames )
18311862{
18321863 PyAsyncGenASend * o = _PyAsyncGenASend_CAST (self );
18331864
@@ -1851,7 +1882,7 @@ async_gen_asend_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
18511882 o -> ags_gen -> ag_running_async = 1 ;
18521883 }
18531884
1854- PyObject * result = gen_throw ((PyObject * )o -> ags_gen , args , nargs );
1885+ PyObject * result = gen_throw ((PyObject * )o -> ags_gen , args , nargs , kwnames );
18551886 result = async_gen_unwrap_value (o -> ags_gen , result );
18561887
18571888 if (result == NULL ) {
@@ -1871,7 +1902,7 @@ async_gen_asend_close(PyObject *self, PyObject *args)
18711902 Py_RETURN_NONE ;
18721903 }
18731904
1874- PyObject * result = async_gen_asend_throw (self , & PyExc_GeneratorExit , 1 );
1905+ PyObject * result = async_gen_asend_throw (self , & PyExc_GeneratorExit , 1 , NULL );
18751906 if (result == NULL ) {
18761907 if (PyErr_ExceptionMatches (PyExc_StopIteration ) ||
18771908 PyErr_ExceptionMatches (PyExc_StopAsyncIteration ) ||
@@ -1899,7 +1930,8 @@ async_gen_asend_finalize(PyObject *self)
18991930
19001931static PyMethodDef async_gen_asend_methods [] = {
19011932 {"send" , async_gen_asend_send , METH_O , send_doc },
1902- {"throw" , _PyCFunction_CAST (async_gen_asend_throw ), METH_FASTCALL , throw_doc },
1933+ {"throw" , _PyCFunction_CAST (async_gen_asend_throw ),
1934+ METH_FASTCALL |METH_KEYWORDS , throw_doc },
19031935 {"close" , async_gen_asend_close , METH_NOARGS , close_doc },
19041936 {NULL , NULL } /* Sentinel */
19051937};
@@ -2227,7 +2259,7 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
22272259
22282260
22292261static PyObject *
2230- async_gen_athrow_throw (PyObject * self , PyObject * const * args , Py_ssize_t nargs )
2262+ async_gen_athrow_throw (PyObject * self , PyObject * const * args , Py_ssize_t nargs , PyObject * kwnames )
22312263{
22322264 PyAsyncGenAThrow * o = _PyAsyncGenAThrow_CAST (self );
22332265
@@ -2258,7 +2290,7 @@ async_gen_athrow_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
22582290 o -> agt_gen -> ag_running_async = 1 ;
22592291 }
22602292
2261- PyObject * retval = gen_throw ((PyObject * )o -> agt_gen , args , nargs );
2293+ PyObject * retval = gen_throw ((PyObject * )o -> agt_gen , args , nargs , kwnames );
22622294 if (o -> agt_args ) {
22632295 retval = async_gen_unwrap_value (o -> agt_gen , retval );
22642296 if (retval == NULL ) {
@@ -2311,7 +2343,7 @@ async_gen_athrow_close(PyObject *self, PyObject *args)
23112343 Py_RETURN_NONE ;
23122344 }
23132345 PyObject * result = async_gen_athrow_throw ((PyObject * )agt ,
2314- & PyExc_GeneratorExit , 1 );
2346+ & PyExc_GeneratorExit , 1 , NULL );
23152347 if (result == NULL ) {
23162348 if (PyErr_ExceptionMatches (PyExc_StopIteration ) ||
23172349 PyErr_ExceptionMatches (PyExc_StopAsyncIteration ) ||
@@ -2342,7 +2374,7 @@ async_gen_athrow_finalize(PyObject *op)
23422374static PyMethodDef async_gen_athrow_methods [] = {
23432375 {"send" , async_gen_athrow_send , METH_O , send_doc },
23442376 {"throw" , _PyCFunction_CAST (async_gen_athrow_throw ),
2345- METH_FASTCALL , throw_doc },
2377+ METH_FASTCALL | METH_KEYWORDS , throw_doc },
23462378 {"close" , async_gen_athrow_close , METH_NOARGS , close_doc },
23472379 {NULL , NULL } /* Sentinel */
23482380};
0 commit comments