Skip to content

Commit 4cf93da

Browse files
committed
Add send() and throw() methods to generator wrapper
1 parent 502b480 commit 4cf93da

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "scikit_build_core.build"
66

77
[project]
88
name = "panda3d-interrogate"
9-
version = "0.6.0"
9+
version = "0.6.1"
1010
description = "Binding generator designed for Panda3D"
1111
readme = "README.md"
1212
requires-python = ">=3.2"

src/interrogatedb/py_wrappers.cxx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,53 @@ static PyObject *Dtool_MutableMappingWrapper_update(PyObject *self, PyObject *ar
965965
return Py_XNewRef(result);
966966
}
967967

968+
/**
969+
* "send" method, accepts only None.
970+
*/
971+
static PyObject *Dtool_GeneratorWrapper_send(PyObject *self, PyObject *arg) {
972+
Dtool_GeneratorWrapper *wrap = (Dtool_GeneratorWrapper *)self;
973+
nassertr(wrap, nullptr);
974+
nassertr(wrap->_iternext_func, nullptr);
975+
if (arg == Py_None) {
976+
return wrap->_iternext_func(wrap->_base._self);
977+
} else {
978+
return Dtool_Raise_TypeError("can't send non-None value to a just-started generator");
979+
}
980+
}
981+
982+
/**
983+
* "throw" method, simply re-raises exception.
984+
*/
985+
static PyObject *Dtool_GeneratorWrapper_throw(PyObject *self, PyObject *args) {
986+
Dtool_GeneratorWrapper *wrap = (Dtool_GeneratorWrapper *)self;
987+
nassertr(wrap, nullptr);
988+
989+
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
990+
if (nargs < 1 || nargs > 3) {
991+
return PyErr_Format(PyExc_TypeError, "throw() takes 1, 2 or 3 arguments");
992+
}
993+
994+
PyObject *exc_type = PyTuple_GET_ITEM(args, 0);
995+
PyObject *exc_val = (nargs >= 2) ? PyTuple_GET_ITEM(args, 1) : nullptr;
996+
PyObject *exc_tb = (nargs >= 3) ? PyTuple_GET_ITEM(args, 2) : nullptr;
997+
if (exc_val == nullptr && exc_tb == nullptr && PyExceptionInstance_Check(exc_type)) {
998+
// We were just given an exception instance.
999+
#if PY_VERSION_HEX >= 0x030C0000 // 3.12
1000+
Py_INCREF(exc_type);
1001+
PyErr_SetRaisedException(exc_type);
1002+
return nullptr;
1003+
#else
1004+
exc_val = exc_type;
1005+
exc_type = (PyObject *)Py_TYPE(exc_val);
1006+
#endif
1007+
}
1008+
Py_XINCREF(exc_type);
1009+
Py_XINCREF(exc_val);
1010+
Py_XINCREF(exc_tb);
1011+
PyErr_Restore(exc_type, exc_val, exc_tb);
1012+
return nullptr;
1013+
}
1014+
9681015
/**
9691016
* This variant defines only a generator interface.
9701017
*/
@@ -1246,11 +1293,18 @@ Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char
12461293
*/
12471294
PyObject *
12481295
Dtool_NewGenerator(PyObject *self, iternextfunc gen_next) {
1296+
static PyMethodDef methods[] = {
1297+
{"send", &Dtool_GeneratorWrapper_send, METH_O, nullptr},
1298+
{"throw", &Dtool_GeneratorWrapper_throw, METH_VARARGS, nullptr},
1299+
{nullptr, nullptr, 0, nullptr}
1300+
};
1301+
12491302
static PyType_Slot wrapper_slots[] = {
12501303
{Py_tp_dealloc, (void *)&Dtool_WrapperBase_dealloc},
12511304
{Py_tp_repr, (void *)&Dtool_SequenceWrapper_repr},
12521305
{Py_tp_iter, (void *)&PyObject_SelfIter},
12531306
{Py_tp_iternext, (void *)&Dtool_GeneratorWrapper_iternext},
1307+
{Py_tp_methods, (void *)methods},
12541308
{0, nullptr},
12551309
};
12561310

0 commit comments

Comments
 (0)