@@ -3263,17 +3263,61 @@ name_filter(PyObject *Py_UNUSED(m), PyObject *n) {
3263
3263
return n ;
3264
3264
}
3265
3265
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
+
3266
3311
// Represent a 1D array as a 2D array with length as rows of a single-column array.
3267
3312
// https://stackoverflow.com/questions/56182259/how-does-one-acces-numpy-multidimensionnal-array-in-c-extensions
3268
3313
static PyObject *
3269
3314
shape_filter (PyObject * Py_UNUSED (m ), PyObject * a ) {
3270
3315
AK_CHECK_NUMPY_ARRAY_1D_2D (a );
3271
3316
PyArrayObject * array = (PyArrayObject * )a ;
3272
-
3273
- npy_intp size0 = PyArray_DIM (array , 0 );
3317
+ npy_intp rows = PyArray_DIM (array , 0 );
3274
3318
// 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 );
3277
3321
}
3278
3322
3279
3323
// 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) {
4240
4284
return NULL ;
4241
4285
}
4242
4286
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
4244
4288
}
4245
4289
4246
4290
//------------------------------------------------------------------------------
@@ -4788,7 +4832,7 @@ BIIterContiguous_iternext(BIIterContiguousObject *self)
4788
4832
}
4789
4833
// no more pairs, return previous slice_start, flag for end on next call
4790
4834
self -> next_block = -2 ;
4791
- return Py_BuildValue ( "nN" , // N steals ref
4835
+ return AK_build_pair_ssize_t_slice ( // steals ref
4792
4836
self -> last_block ,
4793
4837
AK_build_slice_inclusive (slice_start ,
4794
4838
self -> last_column ,
@@ -4813,7 +4857,7 @@ BIIterContiguous_iternext(BIIterContiguousObject *self)
4813
4857
}
4814
4858
self -> next_block = block ;
4815
4859
self -> next_column = column ;
4816
- return Py_BuildValue ( "nN" , // N steals ref
4860
+ return AK_build_pair_ssize_t_slice ( // steals ref
4817
4861
self -> last_block ,
4818
4862
AK_build_slice_inclusive (slice_start ,
4819
4863
self -> last_column ,
@@ -5211,7 +5255,7 @@ BlockIndex_to_list(BlockIndexObject *self, PyObject *Py_UNUSED(unused)) {
5211
5255
BlockIndexRecord * bir = self -> bir ;
5212
5256
5213
5257
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 );
5215
5259
if (item == NULL ) {
5216
5260
Py_DECREF (list );
5217
5261
return NULL ;
@@ -5248,17 +5292,14 @@ BlockIndex_getstate(BlockIndexObject *self) {
5248
5292
return NULL ;
5249
5293
}
5250
5294
PyObject * dt = self -> dtype == NULL ? Py_None : (PyObject * ) self -> dtype ;
5251
-
5252
5295
// 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
5254
5297
self -> block_count ,
5255
5298
self -> row_count ,
5256
5299
self -> bir_count ,
5257
5300
self -> bir_capacity ,
5258
5301
bi ,
5259
5302
dt ); // increfs passed object
5260
-
5261
- Py_DECREF (bi );
5262
5303
return state ;
5263
5304
}
5264
5305
@@ -5283,7 +5324,7 @@ BlockIndex_shape_getter(BlockIndexObject *self, void* Py_UNUSED(closure))
5283
5324
{
5284
5325
if (self -> shape == NULL || self -> shape_recache ) {
5285
5326
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 );
5287
5328
}
5288
5329
// shape is not null and shape_recache is false
5289
5330
Py_INCREF (self -> shape ); // for caller
0 commit comments