Skip to content

Commit 2810a66

Browse files
committed
replaced usage of Py_BuildValue with custom builders
1 parent 4e64d12 commit 2810a66

File tree

1 file changed

+54
-13
lines changed

1 file changed

+54
-13
lines changed

src/_arraykit.c

+54-13
Original file line numberDiff line numberDiff line change
@@ -3263,17 +3263,61 @@ name_filter(PyObject *Py_UNUSED(m), PyObject *n) {
32633263
return n;
32643264
}
32653265

3266+
// Returns NULL on error. Returns a new reference.
3267+
static inline PyObject*
3268+
AK_build_pair_ssize_t(Py_ssize_t a, Py_ssize_t b)
3269+
{
3270+
PyObject* t = PyTuple_New(2);
3271+
if (t == NULL) {
3272+
return NULL;
3273+
}
3274+
PyObject* py_a = PyLong_FromSsize_t(a);
3275+
if (py_a == NULL) {
3276+
Py_DECREF(t);
3277+
return NULL;
3278+
}
3279+
PyObject* py_b = PyLong_FromSsize_t(b);
3280+
if (py_b == NULL) {
3281+
Py_DECREF(t);
3282+
Py_DECREF(py_a);
3283+
return NULL;
3284+
}
3285+
PyTuple_SET_ITEM(t, 0, py_a);
3286+
PyTuple_SET_ITEM(t, 1, py_b);
3287+
return t;
3288+
}
3289+
3290+
// Returns NULL on error. Returns a new reference. Note that a reference is stolen from the PyObject argument.
3291+
static inline PyObject*
3292+
AK_build_pair_ssize_t_slice(Py_ssize_t a, PyObject* py_b)
3293+
{
3294+
if (py_b == NULL) { // construction failed
3295+
return NULL;
3296+
}
3297+
PyObject* t = PyTuple_New(2);
3298+
if (t == NULL) {
3299+
return NULL;
3300+
}
3301+
PyObject* py_a = PyLong_FromSsize_t(a);
3302+
if (py_a == NULL) {
3303+
Py_DECREF(t);
3304+
return NULL;
3305+
}
3306+
PyTuple_SET_ITEM(t, 0, py_a);
3307+
PyTuple_SET_ITEM(t, 1, py_b);
3308+
return t;
3309+
}
3310+
32663311
// Represent a 1D array as a 2D array with length as rows of a single-column array.
32673312
// https://stackoverflow.com/questions/56182259/how-does-one-acces-numpy-multidimensionnal-array-in-c-extensions
32683313
static PyObject *
32693314
shape_filter(PyObject *Py_UNUSED(m), PyObject *a) {
32703315
AK_CHECK_NUMPY_ARRAY_1D_2D(a);
32713316
PyArrayObject *array = (PyArrayObject *)a;
3272-
3273-
npy_intp size0 = PyArray_DIM(array, 0);
3317+
npy_intp rows = PyArray_DIM(array, 0);
32743318
// If 1D array, set size for axis 1 at 1, else use 2D array to get the size of axis 1
3275-
npy_intp size1 = PyArray_NDIM(array) == 1 ? 1 : PyArray_DIM(array, 1);
3276-
return Py_BuildValue("nn", size0, size1);
3319+
npy_intp cols = PyArray_NDIM(array) == 1 ? 1 : PyArray_DIM(array, 1);
3320+
return AK_build_pair_ssize_t(rows, cols);
32773321
}
32783322

32793323
// Reshape if necessary a flat ndim 1 array into a 2D array with one columns and rows of length.
@@ -4240,7 +4284,7 @@ AK_BI_item(BlockIndexObject* self, Py_ssize_t i) {
42404284
return NULL;
42414285
}
42424286
BlockIndexRecord* biri = &self->bir[i];
4243-
return Py_BuildValue("nn", biri->block, biri->column); // maybe NULL
4287+
return AK_build_pair_ssize_t(biri->block, biri->column); // may be NULL
42444288
}
42454289

42464290
//------------------------------------------------------------------------------
@@ -4788,7 +4832,7 @@ BIIterContiguous_iternext(BIIterContiguousObject *self)
47884832
}
47894833
// no more pairs, return previous slice_start, flag for end on next call
47904834
self->next_block = -2;
4791-
return Py_BuildValue("nN", // N steals ref
4835+
return AK_build_pair_ssize_t_slice( // steals ref
47924836
self->last_block,
47934837
AK_build_slice_inclusive(slice_start,
47944838
self->last_column,
@@ -4813,7 +4857,7 @@ BIIterContiguous_iternext(BIIterContiguousObject *self)
48134857
}
48144858
self->next_block = block;
48154859
self->next_column = column;
4816-
return Py_BuildValue("nN", // N steals ref
4860+
return AK_build_pair_ssize_t_slice( // steals ref
48174861
self->last_block,
48184862
AK_build_slice_inclusive(slice_start,
48194863
self->last_column,
@@ -5211,7 +5255,7 @@ BlockIndex_to_list(BlockIndexObject *self, PyObject *Py_UNUSED(unused)) {
52115255
BlockIndexRecord* bir = self->bir;
52125256

52135257
for (Py_ssize_t i = 0; i < self->bir_count; i++) {
5214-
PyObject* item = Py_BuildValue("nn", bir[i].block, bir[i].column);
5258+
PyObject* item = AK_build_pair_ssize_t(bir[i].block, bir[i].column);
52155259
if (item == NULL) {
52165260
Py_DECREF(list);
52175261
return NULL;
@@ -5248,17 +5292,14 @@ BlockIndex_getstate(BlockIndexObject *self) {
52485292
return NULL;
52495293
}
52505294
PyObject* dt = self->dtype == NULL ? Py_None : (PyObject*) self->dtype;
5251-
52525295
// state might be NULL on failure; assume exception set
5253-
PyObject* state = Py_BuildValue("nnnnOO",
5296+
PyObject* state = Py_BuildValue("nnnnNO", // use N to steal ref of bytes
52545297
self->block_count,
52555298
self->row_count,
52565299
self->bir_count,
52575300
self->bir_capacity,
52585301
bi,
52595302
dt); // increfs passed object
5260-
5261-
Py_DECREF(bi);
52625303
return state;
52635304
}
52645305

@@ -5283,7 +5324,7 @@ BlockIndex_shape_getter(BlockIndexObject *self, void* Py_UNUSED(closure))
52835324
{
52845325
if (self->shape == NULL || self->shape_recache) {
52855326
Py_XDECREF(self->shape); // get rid of old if it exists
5286-
self->shape = Py_BuildValue("nn", self->row_count, self->bir_count); // new ref
5327+
self->shape = AK_build_pair_ssize_t(self->row_count, self->bir_count);
52875328
}
52885329
// shape is not null and shape_recache is false
52895330
Py_INCREF(self->shape); // for caller

0 commit comments

Comments
 (0)