Skip to content
This repository was archived by the owner on May 19, 2025. It is now read-only.

Commit 19120ae

Browse files
committed
Implement ENTITY_LIST::array() as a Python iterator
for ent in ent_list.array(): ... ... ... ...
1 parent 8129d81 commit 19120ae

File tree

1 file changed

+60
-7
lines changed

1 file changed

+60
-7
lines changed

src/acis_lists.cpp

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,17 @@ ACIS_Lists_method_ENTITY_LIST_next(ACIS_Lists_ENTITY_LIST *self)
205205
{
206206
PyObject *retobj = _ACIS_new_ENTITY();
207207
ENTITY *_elem = self->_acis_obj->next();
208-
((ACIS_Entity_ENTITY *) retobj)->_acis_obj = _elem;
208+
if (_elem)
209+
{
210+
((ACIS_Entity_ENTITY *) retobj)->_acis_obj = _elem;
211+
}
212+
else
213+
{
214+
// This is a requirement for iterator/generator to stop. Otherwise, you will observe an infinite loop.
215+
PyErr_SetNone(PyExc_StopIteration);
216+
return NULL;
217+
}
218+
209219
return retobj;
210220
}
211221

@@ -220,17 +230,60 @@ ACIS_Lists_method_ENTITY_LIST_next_from(ACIS_Lists_ENTITY_LIST *self, PyObject *
220230

221231
Py_INCREF(arg);
222232
int _from_index = (int) PyLong_AsLong(arg);
233+
Py_DECREF(arg);
223234

224235
PyObject *retobj = _ACIS_new_ENTITY();
225236
ENTITY *_elem = self->_acis_obj->next_from(_from_index);
226-
((ACIS_Entity_ENTITY *) retobj)->_acis_obj = _elem;
227237

228-
Py_DECREF(arg);
238+
if (_elem)
239+
{
240+
((ACIS_Entity_ENTITY *) retobj)->_acis_obj = _elem;
241+
}
242+
else
243+
{
244+
// This is a requirement for iterator/generator to stop. Otherwise, you will observe an infinite loop.
245+
PyErr_SetNone(PyExc_StopIteration);
246+
return NULL;
247+
}
229248

230249
return retobj;
231250
}
232251

233-
/* TO-DO: Implement ENTITY_LIST::array as a Python iterator */
252+
static PyObject *
253+
ACIS_Lists_method_ENTITY_LIST_array(ACIS_Lists_ENTITY_LIST *self)
254+
{
255+
/* This function will create a Python generator/iterator */
256+
257+
// Reference increment is necessary, otherwise this ENTITY_LIST will be garbage collected
258+
Py_INCREF(self);
259+
260+
// Iterator/Generator creation functions always return self!
261+
return (PyObject *) self;
262+
}
263+
264+
static PyObject *
265+
ACIS_Lists_iter_ENTITY_LIST(PyObject *self)
266+
{
267+
/* Must have the same signature as PyObject_GetIter() */
268+
269+
// Move the ENTITY_LIST pointer to the beginning
270+
ACIS_Lists_method_ENTITY_LIST_init((ACIS_Lists_ENTITY_LIST *) self);
271+
272+
Py_INCREF(self);
273+
return self;
274+
}
275+
276+
static PyObject *
277+
ACIS_Lists_iter_next_ENTITY_LIST(PyObject *self)
278+
{
279+
/* Must have the same signature as PyIter_Next() */
280+
281+
// Convert the input argument to a ENTITY_LIST object
282+
ACIS_Lists_ENTITY_LIST *_ent_list = (ACIS_Lists_ENTITY_LIST *) self;
283+
284+
// Return the next element
285+
return ACIS_Lists_method_ENTITY_LIST_next(_ent_list);
286+
}
234287

235288
static PyGetSetDef
236289
ACIS_Lists_getseters_ENTITY_LIST[] =
@@ -258,7 +311,7 @@ static PyMethodDef
258311
{ "first", (PyCFunction) ACIS_Lists_method_ENTITY_LIST_first, METH_NOARGS, "Initializes the iterator, which is used by the next method, to the beginning of the list" },
259312
{ "next", (PyCFunction) ACIS_Lists_method_ENTITY_LIST_next, METH_NOARGS, "Returns the next undeleted (live) entry" },
260313
{ "next_from", (PyCFunction) ACIS_Lists_method_ENTITY_LIST_next_from, METH_O, "Returns the next non deleted entry after the index given without affecting the member variables used by init and next" },
261-
//{ "array", (PyCFunction)ACIS_Lists_method_ENTITY_LIST_array, METH_VARARGS | METH_KEYWORDS, "Gets an array of the entities in the list" },
314+
{ "array", (PyCFunction) ACIS_Lists_method_ENTITY_LIST_array, METH_NOARGS, "Gets an array of the entities in the list (creates a Python generator)" },
262315
{ NULL } /* Sentinel */
263316
};
264317

@@ -290,8 +343,8 @@ static PyTypeObject
290343
0, /* tp_clear */
291344
0, /* tp_richcompare */
292345
0, /* tp_weaklistoffset */
293-
0, /* tp_iter */
294-
0, /* tp_iternext */
346+
(getiterfunc) ACIS_Lists_iter_ENTITY_LIST, /* tp_iter */
347+
(iternextfunc) ACIS_Lists_iter_next_ENTITY_LIST, /* tp_iternext */
295348
ACIS_Lists_methods_ENTITY_LIST, /* tp_methods */
296349
ACIS_Lists_members_ENTITY_LIST, /* tp_members */
297350
ACIS_Lists_getseters_ENTITY_LIST, /* tp_getset */

0 commit comments

Comments
 (0)