diff --git a/panda/src/event/pythonTask.cxx b/panda/src/event/pythonTask.cxx index a978b9d613..2e2213eacc 100644 --- a/panda/src/event/pythonTask.cxx +++ b/panda/src/event/pythonTask.cxx @@ -638,17 +638,31 @@ do_python_task() { // We are calling a generator. Use "send" rather than PyIter_Next since // we need to be able to read the value from a StopIteration exception. PyObject *func = PyObject_GetAttrString(_generator, "send"); - nassertr(func != nullptr, DS_interrupt); - result = PyObject_CallOneArg(func, Py_None); - Py_DECREF(func); + if (func != nullptr) { + result = PyObject_CallOneArg(func, Py_None); + Py_DECREF(func); + } else { + // It has no send(), just call next() directly. + nassertr(Py_TYPE(_generator)->tp_iternext != nullptr, DS_interrupt); + PyErr_Clear(); + result = Py_TYPE(_generator)->tp_iternext(_generator); + } } else { // Throw a CancelledError into the generator. _must_cancel = false; - PyObject *exc = PyObject_CallNoArgs(Extension::get_cancelled_error_type()); + PyObject *exc_type = Extension::get_cancelled_error_type(); PyObject *func = PyObject_GetAttrString(_generator, "throw"); - result = PyObject_CallFunctionObjArgs(func, exc, nullptr); - Py_DECREF(func); - Py_DECREF(exc); + if (func != nullptr) { + PyObject *exc = PyObject_CallNoArgs(exc_type); + result = PyObject_CallFunctionObjArgs(func, exc, nullptr); + Py_DECREF(exc); + Py_DECREF(func); + } else { + // If it has no throw(), assume it propagated the CancelledException. + PyErr_Clear(); + PyErr_SetNone(exc_type); + result = nullptr; + } } if (result == nullptr) {