Skip to content

Commit 94ee309

Browse files
authored
Simplify Python bindings internally. (#3024)
Use nanobind to simplify the implementation of: * `NpySObj_contains`, * `NPySecObj_insert`, * `seg_point_processes`.
1 parent 514efd6 commit 94ee309

File tree

1 file changed

+16
-20
lines changed

1 file changed

+16
-20
lines changed

src/nrnpython/nrnpy_nrn.cpp

+16-20
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,13 @@ static Object* pysec_cell(Section* sec) {
191191
}
192192

193193
static int NpySObj_contains(PyObject* s, PyObject* obj, const char* string) {
194-
/* Checks is provided PyObject* s contains obj */
195-
if (!PyObject_HasAttrString(obj, string)) {
194+
/* Checks is provided PyObject* s matches obj.<string> */
195+
auto pyobj = nb::borrow(obj); // keep refcount+1 during use
196+
if (!nb::hasattr(pyobj, string)) {
196197
return 0;
197198
}
198-
auto _pyobj = nb::borrow(obj); // keep refcount+1 during use
199-
auto obj_seg = nb::steal(PyObject_GetAttrString(obj, string));
200-
return PyObject_RichCompareBool(s, obj_seg.ptr(), Py_EQ);
199+
auto obj_seg = pyobj.attr(string);
200+
return nb::handle{s}.equal(obj_seg);
201201
}
202202

203203
static int NPySecObj_contains(PyObject* sec, PyObject* obj) {
@@ -1493,29 +1493,27 @@ static PyObject* NPySecObj_connect_safe(NPySecObj* self, PyObject* args) {
14931493
static PyObject* NPySecObj_insert(NPySecObj* self, PyObject* args) {
14941494
CHECK_SEC_INVALID(self->sec_);
14951495
char* tname;
1496-
PyObject *tpyobj, *tpyobj2;
14971496
if (!PyArg_ParseTuple(args, "s", &tname)) {
14981497
PyErr_Clear();
14991498
// if called with an object that has an insert method, use that
1499+
PyObject* tpyobj;
15001500
if (PyArg_ParseTuple(args, "O", &tpyobj)) {
1501-
Py_INCREF(tpyobj);
1502-
Py_INCREF((PyObject*) self);
1503-
tpyobj2 = PyObject_CallMethod(tpyobj, "insert", "O", (PyObject*) self);
1504-
Py_DECREF(tpyobj);
1505-
if (tpyobj2 == NULL) {
1506-
Py_DECREF((PyObject*) self);
1501+
auto _tpyobj_tracker = nb::borrow(tpyobj);
1502+
// Returned object to be discarded
1503+
auto out_o = nb::steal(PyObject_CallMethod(tpyobj, "insert", "O", (PyObject*) self));
1504+
if (!out_o.is_valid()) {
15071505
PyErr_Clear();
15081506
PyErr_SetString(
15091507
PyExc_TypeError,
15101508
"insert argument must be either a string or an object with an insert method");
1511-
return NULL;
1509+
return nullptr;
15121510
}
1513-
Py_DECREF(tpyobj2);
1511+
Py_INCREF(self);
15141512
return (PyObject*) self;
15151513
}
15161514
PyErr_Clear();
15171515
PyErr_SetString(PyExc_TypeError, "insert takes a single positional argument");
1518-
return NULL;
1516+
return nullptr;
15191517
}
15201518
PyObject* otype = PyDict_GetItemString(pmech_types, tname);
15211519
if (!otype) {
@@ -1693,16 +1691,14 @@ static PyObject* seg_point_processes(NPySegObj* self) {
16931691
Section* sec = self->pysec_->sec_;
16941692
CHECK_SEC_INVALID(sec);
16951693
Node* nd = node_exact(sec, self->x_);
1696-
PyObject* result = PyList_New(0);
1694+
nb::list result{};
16971695
for (Prop* p = nd->prop; p; p = p->next) {
16981696
if (memb_func[p->_type].is_point) {
16991697
auto* pp = p->dparam[1].get<Point_process*>();
1700-
auto item = nb::steal(nrnpy_ho2po(pp->ob));
1701-
int err = PyList_Append(result, item.ptr());
1702-
assert(err == 0);
1698+
result.append(nb::steal(nrnpy_ho2po(pp->ob)));
17031699
}
17041700
}
1705-
return result;
1701+
return result.release().ptr();
17061702
}
17071703

17081704
static PyObject* seg_point_processes_safe(NPySegObj* self) {

0 commit comments

Comments
 (0)