@@ -148,22 +148,25 @@ AK_ResolveDTypeIter(PyObject *dtypes)
148
148
return resolved ;
149
149
}
150
150
151
- // Numpy implementation: https://github.com/numpy/numpy/blob/a14c41264855e44ebd6187d7541b5b8d59bb32cb/numpy/core/src/multiarray/methods.c#L1557
151
+ // Perform a deepcopy on an array, using an optional memo dictionary, and specialized to depend on immutable arrays. Related Numpy implementation: https://github.com/numpy/numpy/blob/a14c41264855e44ebd6187d7541b5b8d59bb32cb/numpy/core/src/multiarray/methods.c#L1557
152
152
PyObject *
153
153
AK_ArrayDeepCopy (PyArrayObject * array , PyObject * memo )
154
154
{
155
155
PyObject * id = PyLong_FromVoidPtr ((PyObject * )array );
156
156
if (!id ) {
157
157
return NULL ;
158
158
}
159
- PyObject * found = PyDict_GetItemWithError (memo , id );
160
- if (found ) { // found will be NULL if not in dict
161
- Py_INCREF (found ); // got a borrowed ref, increment first
162
- Py_DECREF (id );
163
- return found ;
164
- }
165
- else if (PyErr_Occurred ()) {
166
- goto error ;
159
+
160
+ if (memo ) {
161
+ PyObject * found = PyDict_GetItemWithError (memo , id );
162
+ if (found ) { // found will be NULL if not in dict
163
+ Py_INCREF (found ); // got a borrowed ref, increment first
164
+ Py_DECREF (id );
165
+ return found ;
166
+ }
167
+ else if (PyErr_Occurred ()) {
168
+ goto error ;
169
+ }
167
170
}
168
171
169
172
// if dtype is object, call deepcopy with memo
@@ -187,14 +190,17 @@ AK_ArrayDeepCopy(PyArrayObject *array, PyObject *memo)
187
190
}
188
191
}
189
192
else {
193
+ // if not a n object dtype, we will force a copy (even if this is an immutable array) so as to not hold on to any references
190
194
Py_INCREF (dtype ); // PyArray_FromArray steals a reference
191
195
array_new = PyArray_FromArray (
192
196
array ,
193
197
dtype ,
194
198
NPY_ARRAY_ENSURECOPY );
195
- if (!array_new || PyDict_SetItem (memo , id , array_new )) {
196
- Py_XDECREF (array_new );
197
- goto error ;
199
+ if (memo ) {
200
+ if (!array_new || PyDict_SetItem (memo , id , array_new )) {
201
+ Py_XDECREF (array_new );
202
+ goto error ;
203
+ }
198
204
}
199
205
}
200
206
// set immutable
@@ -311,20 +317,25 @@ row_1d_filter(PyObject *Py_UNUSED(m), PyObject *a)
311
317
//------------------------------------------------------------------------------
312
318
// array utility
313
319
314
- // Specialized array deepcopy that stores immutable arrays in memo dict.
320
+ static char * array_deepcopy_kwarg_names [] = {
321
+ "array" ,
322
+ "memo" ,
323
+ NULL
324
+ };
325
+
326
+ // Specialized array deepcopy that stores immutable arrays in an optional memo dict that can be provided with kwargs.
315
327
static PyObject *
316
- array_deepcopy (PyObject * Py_UNUSED (m ), PyObject * args )
328
+ array_deepcopy (PyObject * Py_UNUSED (m ), PyObject * args , PyObject * kwargs )
317
329
{
318
- PyObject * array , * memo ;
319
- if (!PyArg_UnpackTuple (args , "array_deepcopy" , 2 , 2 , & array , & memo )) {
330
+ PyObject * array ;
331
+ PyObject * memo = NULL ;
332
+ if (!PyArg_ParseTupleAndKeywords (args , kwargs ,
333
+ "O|O!:array_deepcopy" , array_deepcopy_kwarg_names ,
334
+ & array ,
335
+ & PyDict_Type , & memo )) {
320
336
return NULL ;
321
337
}
322
338
AK_CHECK_NUMPY_ARRAY (array );
323
- if (!PyDict_CheckExact (memo )) {
324
- PyErr_Format (PyExc_TypeError , "expected a dict (got %s)" ,
325
- Py_TYPE (memo )-> tp_name );
326
- return NULL ;
327
- }
328
339
return AK_ArrayDeepCopy ((PyArrayObject * )array , memo );
329
340
}
330
341
@@ -623,7 +634,10 @@ static PyMethodDef arraykit_methods[] = {
623
634
{"column_2d_filter" , column_2d_filter , METH_O , NULL },
624
635
{"column_1d_filter" , column_1d_filter , METH_O , NULL },
625
636
{"row_1d_filter" , row_1d_filter , METH_O , NULL },
626
- {"array_deepcopy" , array_deepcopy , METH_VARARGS , NULL },
637
+ {"array_deepcopy" ,
638
+ (PyCFunction )array_deepcopy ,
639
+ METH_VARARGS | METH_KEYWORDS ,
640
+ NULL },
627
641
{"resolve_dtype" , resolve_dtype , METH_VARARGS , NULL },
628
642
{"resolve_dtype_iter" , resolve_dtype_iter , METH_O , NULL },
629
643
{NULL },
0 commit comments