arraykit 0.6.3__tar.gz → 0.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {arraykit-0.6.3/arraykit.egg-info → arraykit-0.7.1}/PKG-INFO +1 -1
  2. {arraykit-0.6.3 → arraykit-0.7.1}/README.rst +15 -0
  3. {arraykit-0.6.3 → arraykit-0.7.1/arraykit.egg-info}/PKG-INFO +1 -1
  4. {arraykit-0.6.3 → arraykit-0.7.1}/setup.py +1 -1
  5. {arraykit-0.6.3 → arraykit-0.7.1}/src/__init__.py +2 -0
  6. {arraykit-0.6.3 → arraykit-0.7.1}/src/__init__.pyi +2 -0
  7. {arraykit-0.6.3 → arraykit-0.7.1}/src/_arraykit.c +223 -1
  8. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_util.py +127 -0
  9. {arraykit-0.6.3 → arraykit-0.7.1}/LICENSE.txt +0 -0
  10. {arraykit-0.6.3 → arraykit-0.7.1}/MANIFEST.in +0 -0
  11. {arraykit-0.6.3 → arraykit-0.7.1}/arraykit.egg-info/SOURCES.txt +0 -0
  12. {arraykit-0.6.3 → arraykit-0.7.1}/arraykit.egg-info/dependency_links.txt +0 -0
  13. {arraykit-0.6.3 → arraykit-0.7.1}/arraykit.egg-info/requires.txt +0 -0
  14. {arraykit-0.6.3 → arraykit-0.7.1}/arraykit.egg-info/top_level.txt +0 -0
  15. {arraykit-0.6.3 → arraykit-0.7.1}/setup.cfg +0 -0
  16. {arraykit-0.6.3 → arraykit-0.7.1}/src/py.typed +0 -0
  17. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_array_go.py +0 -0
  18. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_block_index.py +0 -0
  19. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_delimited_to_arrays.py +0 -0
  20. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_delimited_to_arrays_integration.py +0 -0
  21. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_delimited_to_arrays_property.py +0 -0
  22. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_nonzero_1d.py +0 -0
  23. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_nonzero_1d_property.py +0 -0
  24. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_pyi.py +0 -0
  25. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_split_after_count.py +0 -0
  26. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_tri_map.py +0 -0
  27. {arraykit-0.6.3 → arraykit-0.7.1}/test/test_type_discovery.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: arraykit
3
- Version: 0.6.3
3
+ Version: 0.7.1
4
4
  Summary: Array utilities for StaticFrame
5
5
  Home-page: https://github.com/static-frame/arraykit
6
6
  Author: Christopher Ariza, Brandt Bucher, Charles Burkland
@@ -37,6 +37,21 @@ ArrayKit requires the following:
37
37
  What is New in ArrayKit
38
38
  -------------------------
39
39
 
40
+
41
+ 0.7.1
42
+ ............
43
+
44
+ Extended ``array_to_tuple_array()`` and ``array_to_tuple_iter()`` to support 1D arrays.
45
+
46
+
47
+ 0.7.0
48
+ ............
49
+
50
+ Added ``array_to_tuple_array()``.
51
+
52
+ Added ``array_to_tuple_iter()``.
53
+
54
+
40
55
  0.6.3
41
56
  ............
42
57
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: arraykit
3
- Version: 0.6.3
3
+ Version: 0.7.1
4
4
  Summary: Array utilities for StaticFrame
5
5
  Home-page: https://github.com/static-frame/arraykit
6
6
  Author: Christopher Ariza, Brandt Bucher, Charles Burkland
@@ -5,7 +5,7 @@ from setuptools import Extension # type: ignore
5
5
  from setuptools import setup
6
6
  from pathlib import Path
7
7
 
8
- AK_VERSION = '0.6.3'
8
+ AK_VERSION = '0.7.1'
9
9
 
10
10
  def get_long_description() -> str:
11
11
  return '''The ArrayKit library provides utilities for creating and transforming NumPy arrays, implementing performance-critical StaticFrame operations as Python C extensions.
@@ -28,4 +28,6 @@ from ._arraykit import count_iteration as count_iteration
28
28
  from ._arraykit import first_true_1d as first_true_1d
29
29
  from ._arraykit import first_true_2d as first_true_2d
30
30
  from ._arraykit import slice_to_ascending_slice as slice_to_ascending_slice
31
+ from ._arraykit import array_to_tuple_array as array_to_tuple_array
32
+ from ._arraykit import array_to_tuple_iter as array_to_tuple_iter
31
33
  from ._arraykit import nonzero_1d as nonzero_1d
@@ -161,3 +161,5 @@ def first_true_1d(__array: np.ndarray, *, forward: bool) -> int: ...
161
161
  def first_true_2d(__array: np.ndarray, *, forward: bool, axis: int) -> np.ndarray: ...
162
162
  def nonzero_1d(__array: np.ndarray, /) -> np.ndarray: ...
163
163
  def slice_to_ascending_slice(__slice: slice, __size: int) -> slice: ...
164
+ def array_to_tuple_array(__array: np.ndarray) -> np.ndarray: ...
165
+ def array_to_tuple_iter(__array: np.ndarray) -> tp.Iterator[tp.Tuple[tp.Any, ...]]: ...
@@ -37,6 +37,18 @@ const static size_t UCS4_SIZE = sizeof(Py_UCS4);
37
37
  } \
38
38
  } while (0)
39
39
 
40
+ // Given a PyObject, raise if not an array or is not two dimensional.
41
+ # define AK_CHECK_NUMPY_ARRAY_2D(O) \
42
+ do { \
43
+ AK_CHECK_NUMPY_ARRAY(O) \
44
+ int ndim = PyArray_NDIM((PyArrayObject *)O); \
45
+ if (ndim != 2) { \
46
+ return PyErr_Format(PyExc_NotImplementedError,\
47
+ "Expected a 2D array, not %i.", \
48
+ ndim); \
49
+ } \
50
+ } while (0)
51
+
40
52
  // Placeholder of not implemented pathways / debugging.
41
53
  # define AK_NOT_IMPLEMENTED(msg) \
42
54
  do { \
@@ -3511,6 +3523,215 @@ array_deepcopy(PyObject *m, PyObject *args, PyObject *kwargs)
3511
3523
  return AK_ArrayDeepCopy(m, (PyArrayObject*)array, memo);
3512
3524
  }
3513
3525
 
3526
+ //------------------------------------------------------------------------------
3527
+ // Given a 1D or 2D array, return a 1D object array of tuples.
3528
+ static PyObject *
3529
+ array_to_tuple_array(PyObject *Py_UNUSED(m), PyObject *a)
3530
+ {
3531
+ AK_CHECK_NUMPY_ARRAY(a);
3532
+ PyArrayObject *input_array = (PyArrayObject *)a;
3533
+ int ndim = PyArray_NDIM(input_array);
3534
+ if (ndim != 1 && ndim != 2) {
3535
+ return PyErr_Format(PyExc_NotImplementedError,
3536
+ "Expected 1D or 2D array, not %i.",
3537
+ ndim);
3538
+ }
3539
+
3540
+ npy_intp num_rows = PyArray_DIM(input_array, 0);
3541
+ npy_intp dims[] = {num_rows};
3542
+ // NOTE: this initializes values to NULL, not None
3543
+ PyObject* output = PyArray_SimpleNew(1, dims, NPY_OBJECT);
3544
+ if (output == NULL) {
3545
+ return NULL;
3546
+ }
3547
+
3548
+ PyObject** output_data = (PyObject**)PyArray_DATA((PyArrayObject*)output);
3549
+ PyObject** p = output_data;
3550
+ PyObject** p_end = p + num_rows;
3551
+ npy_intp i = 0;
3552
+ PyObject* tuple;
3553
+ PyObject* item;
3554
+
3555
+ if (ndim == 2) {
3556
+ npy_intp num_cols = PyArray_DIM(input_array, 1);
3557
+ npy_intp j;
3558
+ while (p < p_end) {
3559
+ tuple = PyTuple_New(num_cols);
3560
+ if (tuple == NULL) {
3561
+ goto error;
3562
+ }
3563
+ for (j = 0; j < num_cols; ++j) {
3564
+ // cannot assume input_array is contiguous
3565
+ item = PyArray_ToScalar(PyArray_GETPTR2(input_array, i, j), input_array);
3566
+ if (item == NULL) {
3567
+ Py_DECREF(tuple);
3568
+ goto error;
3569
+ }
3570
+ PyTuple_SET_ITEM(tuple, j, item); // steals reference to item
3571
+ }
3572
+ *p++ = tuple; // assign with new ref, no incr needed
3573
+ i++;
3574
+ }
3575
+ }
3576
+ else { // ndim == 1
3577
+ while (p < p_end) {
3578
+ tuple = PyTuple_New(1);
3579
+ if (tuple == NULL) {
3580
+ goto error;
3581
+ }
3582
+ // scalar returned in is native PyObject from object arrays
3583
+ item = PyArray_ToScalar(PyArray_GETPTR1(input_array, i), input_array);
3584
+ if (item == NULL) {
3585
+ Py_DECREF(tuple);
3586
+ goto error;
3587
+ }
3588
+ PyTuple_SET_ITEM(tuple, 0, item); // steals reference to item
3589
+ *p++ = tuple; // assign with new ref, no incr needed
3590
+ i++;
3591
+ }
3592
+ }
3593
+ PyArray_CLEARFLAGS((PyArrayObject *)output, NPY_ARRAY_WRITEABLE);
3594
+ return output;
3595
+ error:
3596
+ p = output_data;
3597
+ p_end = p + num_rows;
3598
+ while (p < p_end) { // decref all tuples within array
3599
+ Py_XDECREF(*p++); // xdec as might be NULL
3600
+ }
3601
+ Py_DECREF(output);
3602
+ return NULL;
3603
+ }
3604
+
3605
+ //------------------------------------------------------------------------------
3606
+ // ArrayToTupleIterator
3607
+
3608
+ static PyTypeObject ATTType;
3609
+
3610
+ typedef struct ATTObject {
3611
+ PyObject_HEAD
3612
+ PyArrayObject* array;
3613
+ npy_intp num_rows;
3614
+ npy_intp num_cols;
3615
+ Py_ssize_t pos; // current index state, mutated in-place
3616
+ } ATTObject;
3617
+
3618
+ static PyObject *
3619
+ ATT_new(PyArrayObject* array,
3620
+ npy_intp num_rows,
3621
+ npy_intp num_cols) {
3622
+ ATTObject* a2dt = PyObject_New(ATTObject, &ATTType);
3623
+ if (!a2dt) {
3624
+ return NULL;
3625
+ }
3626
+ Py_INCREF((PyObject*)array);
3627
+ a2dt->array = array;
3628
+ a2dt->num_rows = num_rows;
3629
+ a2dt->num_cols = num_cols; // -1 for 1D array
3630
+ a2dt->pos = 0;
3631
+ return (PyObject *)a2dt;
3632
+ }
3633
+
3634
+ static void
3635
+ ATT_dealloc(ATTObject *self) {
3636
+ Py_DECREF((PyObject*)self->array);
3637
+ PyObject_Del((PyObject*)self);
3638
+ }
3639
+
3640
+ static PyObject*
3641
+ ATT_iter(ATTObject *self) {
3642
+ Py_INCREF(self);
3643
+ return (PyObject*)self;
3644
+ }
3645
+
3646
+ static PyObject *
3647
+ ATT_iternext(ATTObject *self) {
3648
+ Py_ssize_t i = self->pos;
3649
+ if (i < self->num_rows) {
3650
+ npy_intp num_cols = self->num_cols;
3651
+ PyArrayObject* array = self->array;
3652
+ PyObject* item;
3653
+ PyObject* tuple;
3654
+
3655
+ if (num_cols > -1) { // ndim == 2
3656
+ tuple = PyTuple_New(num_cols);
3657
+ if (tuple == NULL) {
3658
+ return NULL;
3659
+ }
3660
+ for (npy_intp j = 0; j < num_cols; ++j) {
3661
+ // cannot assume array is contiguous
3662
+ item = PyArray_ToScalar(PyArray_GETPTR2(array, i, j), array);
3663
+ if (item == NULL) {
3664
+ Py_DECREF(tuple);
3665
+ return NULL;
3666
+ }
3667
+ PyTuple_SET_ITEM(tuple, j, item); // steals reference to item
3668
+ }
3669
+ }
3670
+ else { // ndim == 1
3671
+ tuple = PyTuple_New(1);
3672
+ if (tuple == NULL) {
3673
+ return NULL;
3674
+ }
3675
+ item = PyArray_ToScalar(PyArray_GETPTR1(array, i), array);
3676
+ if (item == NULL) {
3677
+ Py_DECREF(tuple);
3678
+ return NULL;
3679
+ }
3680
+ PyTuple_SET_ITEM(tuple, 0, item); // steals reference to item
3681
+ }
3682
+ self->pos++;
3683
+ return tuple;
3684
+ }
3685
+ return NULL;
3686
+ }
3687
+
3688
+ // static PyObject *
3689
+ // ATT_reversed(ATTObject *self) {
3690
+ // return ATT_new(self->bi, !self->reversed);
3691
+ // }
3692
+
3693
+ static PyObject *
3694
+ ATT_length_hint(ATTObject *self) {
3695
+ Py_ssize_t len = Py_MAX(0, self->num_rows - self->pos);
3696
+ return PyLong_FromSsize_t(len);
3697
+ }
3698
+
3699
+ static PyMethodDef ATT_methods[] = {
3700
+ {"__length_hint__", (PyCFunction)ATT_length_hint, METH_NOARGS, NULL},
3701
+ // {"__reversed__", (PyCFunction)ATT_reversed, METH_NOARGS, NULL},
3702
+ {NULL},
3703
+ };
3704
+
3705
+ static PyTypeObject ATTType = {
3706
+ PyVarObject_HEAD_INIT(NULL, 0)
3707
+ .tp_basicsize = sizeof(ATTObject),
3708
+ .tp_dealloc = (destructor) ATT_dealloc,
3709
+ .tp_iter = (getiterfunc) ATT_iter,
3710
+ .tp_iternext = (iternextfunc) ATT_iternext,
3711
+ .tp_methods = ATT_methods,
3712
+ .tp_name = "arraykit.ATTIterator",
3713
+ };
3714
+
3715
+ // Given a 2D array, return an iterator of row tuples.
3716
+ static PyObject *
3717
+ array_to_tuple_iter(PyObject *Py_UNUSED(m), PyObject *a)
3718
+ {
3719
+ AK_CHECK_NUMPY_ARRAY(a);
3720
+ PyArrayObject *array = (PyArrayObject *)a;
3721
+ int ndim = PyArray_NDIM(array);
3722
+ if (ndim != 1 && ndim != 2) {
3723
+ return PyErr_Format(PyExc_NotImplementedError,
3724
+ "Expected 1D or 2D array, not %i.",
3725
+ ndim);
3726
+ }
3727
+ npy_intp num_rows = PyArray_DIM(array, 0);
3728
+ npy_intp num_cols = -1; // indicate 1d
3729
+ if (ndim == 2) {
3730
+ num_cols = PyArray_DIM(array, 1);
3731
+ }
3732
+ return ATT_new(array, num_rows, num_cols);
3733
+ }
3734
+
3514
3735
  //------------------------------------------------------------------------------
3515
3736
  // type resolution
3516
3737
 
@@ -5944,7 +6165,6 @@ TriMap_dealloc(TriMapObject *self) {
5944
6165
  if (self->many_from != NULL) {
5945
6166
  // decref all arrays before freeing
5946
6167
  for (Py_ssize_t i = 0; i < self->many_count; i++) {
5947
- // NOTE: using dot to get to pointer?
5948
6168
  Py_DECREF((PyObject*)self->many_from[i].dst);
5949
6169
  }
5950
6170
  PyMem_Free(self->many_from);
@@ -7259,6 +7479,8 @@ static PyMethodDef arraykit_methods[] = {
7259
7479
  (PyCFunction)array_deepcopy,
7260
7480
  METH_VARARGS | METH_KEYWORDS,
7261
7481
  NULL},
7482
+ {"array_to_tuple_array", array_to_tuple_array, METH_O, NULL},
7483
+ {"array_to_tuple_iter", array_to_tuple_iter, METH_O, NULL},
7262
7484
  {"resolve_dtype", resolve_dtype, METH_VARARGS, NULL},
7263
7485
  {"resolve_dtype_iter", resolve_dtype_iter, METH_O, NULL},
7264
7486
  {"first_true_1d",
@@ -22,6 +22,8 @@ from arraykit import count_iteration
22
22
  from arraykit import first_true_1d
23
23
  from arraykit import first_true_2d
24
24
  from arraykit import slice_to_ascending_slice
25
+ from arraykit import array_to_tuple_array
26
+ from arraykit import array_to_tuple_iter
25
27
 
26
28
  from performance.reference.util import get_new_indexers_and_screen_ak as get_new_indexers_and_screen_full
27
29
  from arraykit import get_new_indexers_and_screen
@@ -283,6 +285,131 @@ class TestUnit(unittest.TestCase):
283
285
  with self.assertRaises(TypeError):
284
286
  a2 = array_deepcopy(a1, ())
285
287
 
288
+ #---------------------------------------------------------------------------
289
+ def test_array2d_to_array1d_1d_a(self) -> None:
290
+ a1 = np.arange(10)
291
+ a2 = array_to_tuple_array(a1)
292
+ self.assertEqual(a2.tolist(), [(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,), (8,), (9,)])
293
+
294
+ def test_array2d_to_array1d_1d_b(self) -> None:
295
+ a1 = np.array(['aaa', 'b', 'ccc'])
296
+ a2 = array_to_tuple_array(a1)
297
+ self.assertEqual(a2.tolist(), [('aaa',), ('b',), ('ccc',)])
298
+
299
+ def test_array2d_to_array1d_1d_c(self) -> None:
300
+ a1 = np.array([None, 'b', 30])
301
+ a2 = array_to_tuple_array(a1)
302
+ self.assertEqual(a2.tolist(), [(None,), ('b',), (30,)])
303
+
304
+ def test_array2d_to_array1d_1d_d(self) -> None:
305
+ a1 = np.array([('a', 10), ('b', 30), ('c', 5)], dtype=object)
306
+ a2 = array_to_tuple_array(a1)
307
+ self.assertEqual(a2.tolist(), [('a', 10), ('b', 30), ('c', 5)])
308
+
309
+ def test_array2d_to_array1d_1d_e(self) -> None:
310
+ a1 = np.array([True, False, True], dtype=object)
311
+ a2 = array_to_tuple_array(a1)
312
+ self.assertIs(a2[0][0].__class__, bool)
313
+ self.assertEqual(a2.tolist(), [(True,), (False,), (True,)])
314
+
315
+ def test_array2d_to_array1d_b(self) -> None:
316
+ a1 = np.arange(10, dtype=np.int64).reshape(5, 2)
317
+ result = array_to_tuple_array(a1)
318
+ assert isinstance(result[0], tuple)
319
+ assert result[0] == (0, 1)
320
+ self.assertIs(type(result[0][0]), np.int64)
321
+ self.assertFalse(result.flags.writeable)
322
+ self.assertEqual(tuple(result), ((0, 1), (2, 3), (4, 5), (6, 7), (8, 9)))
323
+
324
+
325
+ def test_array2d_to_array1d_c(self) -> None:
326
+ a1 = np.array([["a", "b"], ["ccc", "ddd"], ["ee", "ff"]])
327
+ a2 = array_to_tuple_array(a1)
328
+ self.assertEqual(a2.tolist(), [('a', 'b'), ('ccc', 'ddd'), ('ee', 'ff')])
329
+
330
+ def test_array2d_to_array1d_d(self) -> None:
331
+ a1 = np.array([[3, 5], [10, 20], [7, 2]], dtype=np.uint8)
332
+ a2 = array_to_tuple_array(a1)
333
+ self.assertEqual(a2.tolist(), [(3, 5), (10, 20), (7, 2)])
334
+ self.assertIs(type(a2[0][0]), np.uint8)
335
+
336
+ def test_array2d_to_array1d_e(self) -> None:
337
+ a1 = np.arange(20, dtype=np.int64).reshape(4, 5)
338
+ result = array_to_tuple_array(a1)
339
+ self.assertEqual(result.tolist(), [(0, 1, 2, 3, 4), (5, 6, 7, 8, 9), (10, 11, 12, 13, 14), (15, 16, 17, 18, 19)])
340
+
341
+ #---------------------------------------------------------------------------
342
+ def test_array2d_tuple_iter_a(self) -> None:
343
+ a1 = np.arange(20, dtype=np.int64).reshape(4, 5)
344
+ result = list(array_to_tuple_iter(a1))
345
+ self.assertEqual(len(result), 4)
346
+ self.assertEqual(result, [(0, 1, 2, 3, 4), (5, 6, 7, 8, 9), (10, 11, 12, 13, 14), (15, 16, 17, 18, 19)])
347
+
348
+ def test_array2d_tuple_iter_b(self) -> None:
349
+ a1 = np.arange(20, dtype=np.int64).reshape(10, 2)
350
+ result = list(array_to_tuple_iter(a1))
351
+ self.assertEqual(result, [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, 11), (12, 13), (14, 15), (16, 17), (18, 19)])
352
+
353
+ def test_array2d_tuple_iter_c(self) -> None:
354
+ a1 = np.array([['aaa', 'bb'], ['c', 'dd'], ['ee', 'fffff']])
355
+ it = array_to_tuple_iter(a1)
356
+ self.assertEqual(it.__length_hint__(), 3)
357
+ self.assertEqual(next(it), ('aaa', 'bb'))
358
+ self.assertEqual(it.__length_hint__(), 2)
359
+ self.assertEqual(next(it), ('c', 'dd'))
360
+ self.assertEqual(it.__length_hint__(), 1)
361
+ self.assertEqual(next(it), ('ee', 'fffff'))
362
+ self.assertEqual(it.__length_hint__(), 0)
363
+ with self.assertRaises(StopIteration):
364
+ next(it)
365
+
366
+ def test_array2d_tuple_iter_d(self) -> None:
367
+ a1 = np.array([['aaa', 'bb'], ['c', 'dd'], ['ee', 'fffff']])
368
+ it = array_to_tuple_iter(a1)
369
+ # __reversed__ not implemented
370
+ with self.assertRaises(TypeError):
371
+ reversed(it)
372
+
373
+ def test_array2d_tuple_iter_e(self) -> None:
374
+ a1 = np.array([[None, 'bb'], [None, 'dd'], [3, None]])
375
+ it = array_to_tuple_iter(a1)
376
+ del a1
377
+ self.assertEqual(list(it), [(None, 'bb'), (None, 'dd'), (3, None)])
378
+
379
+ def test_array2d_tuple_iter_f(self) -> None:
380
+ a1 = np.array([[None, 'bb'], [None, 'dd'], [3, None]])
381
+ it1 = array_to_tuple_iter(a1)
382
+ del a1
383
+ it2 = iter(it1)
384
+ self.assertEqual(list(it1), [(None, 'bb'), (None, 'dd'), (3, None)])
385
+ self.assertEqual(list(it2), []) # expected behavior
386
+
387
+ def test_array2d_tuple_iter_g(self) -> None:
388
+ a1 = np.array([[None, 'bb'], [None, 'dd'], [3, None]])
389
+ it1 = array_to_tuple_iter(a1)
390
+ it2 = array_to_tuple_iter(a1)
391
+ del a1
392
+ self.assertEqual(list(it1), [(None, 'bb'), (None, 'dd'), (3, None)])
393
+ self.assertEqual(list(it2), [(None, 'bb'), (None, 'dd'), (3, None)])
394
+
395
+ def test_array2d_tuple_iter_1d_a(self) -> None:
396
+ a1 = np.array(['bb', 'c', 'aaa'])
397
+ result = list(array_to_tuple_iter(a1))
398
+ self.assertEqual(len(result), 3)
399
+ self.assertEqual(result, [('bb',), ('c',), ('aaa',)])
400
+
401
+ def test_array2d_tuple_iter_1d_b(self) -> None:
402
+ a1 = np.array([20, -1, 8])
403
+ result = list(array_to_tuple_iter(a1))
404
+ self.assertEqual(len(result), 3)
405
+ self.assertEqual(result, [(20,), (-1,), (8,)])
406
+
407
+ def test_array2d_tuple_iter_1d_c(self) -> None:
408
+ a1 = np.array([('a', 4), ('c', -1), ('d', 8)], dtype=object)
409
+ result = list(array_to_tuple_iter(a1))
410
+ self.assertEqual(len(result), 3)
411
+ self.assertEqual(result, [('a', 4), ('c', -1), ('d', 8)])
412
+
286
413
  #---------------------------------------------------------------------------
287
414
 
288
415
  def test_isna_element_a(self) -> None:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes