@@ -522,9 +522,6 @@ inplace_increment(PyObject *dummy, PyObject *args)
522
522
}
523
523
type_number = PyArray_TYPE(a);
524
524
525
-
526
-
527
-
528
525
while (type_numbers[i] >= 0 && addition_funcs[i] != NULL){
529
526
if (type_number == type_numbers[i]) {
530
527
add_inplace = addition_funcs[i];
@@ -558,6 +555,7 @@ fail:
558
555
return NULL;
559
556
}
560
557
558
+
561
559
#if !defined(NPY_PY3K)
562
560
static PyObject *
563
561
int_subclass(PyObject *dummy, PyObject *args)
@@ -581,6 +579,116 @@ int_subclass(PyObject *dummy, PyObject *args)
581
579
}
582
580
#endif
583
581
582
+
583
+ /*
584
+ * Create python string from a FLAG and or the corresponding PyBuf flag
585
+ * for the use in get_buffer_info.
586
+ */
587
+ #define GET_PYBUF_FLAG(FLAG) \
588
+ buf_flag = PyUnicode_FromString(#FLAG); \
589
+ flag_matches = PyObject_RichCompareBool(buf_flag, tmp, Py_EQ); \
590
+ Py_DECREF(buf_flag); \
591
+ if (flag_matches == 1) { \
592
+ Py_DECREF(tmp); \
593
+ flags |= PyBUF_##FLAG; \
594
+ continue; \
595
+ } \
596
+ else if (flag_matches == -1) { \
597
+ Py_DECREF(tmp); \
598
+ return NULL; \
599
+ }
600
+
601
+
602
+ /*
603
+ * Get information for a buffer through PyBuf_GetBuffer with the
604
+ * corresponding flags or'ed. Note that the python caller has to
605
+ * make sure that or'ing those flags actually makes sense.
606
+ * More information should probably be returned for future tests.
607
+ */
608
+ static PyObject *
609
+ get_buffer_info(PyObject *NPY_UNUSED(self), PyObject *args)
610
+ {
611
+ PyObject *buffer_obj, *pyflags;
612
+ PyObject *tmp, *buf_flag;
613
+ Py_buffer buffer;
614
+ PyObject *shape, *strides;
615
+ Py_ssize_t i, n;
616
+ int flag_matches;
617
+ int flags = 0;
618
+
619
+ if (!PyArg_ParseTuple(args, "OO", &buffer_obj, &pyflags)) {
620
+ return NULL;
621
+ }
622
+
623
+ n = PySequence_Length(pyflags);
624
+ if (n < 0) {
625
+ return NULL;
626
+ }
627
+
628
+ for (i=0; i < n; i++) {
629
+ tmp = PySequence_GetItem(pyflags, i);
630
+ if (tmp == NULL) {
631
+ return NULL;
632
+ }
633
+
634
+ GET_PYBUF_FLAG(SIMPLE);
635
+ GET_PYBUF_FLAG(WRITABLE);
636
+ GET_PYBUF_FLAG(STRIDES);
637
+ GET_PYBUF_FLAG(ND);
638
+ GET_PYBUF_FLAG(C_CONTIGUOUS);
639
+ GET_PYBUF_FLAG(F_CONTIGUOUS);
640
+ GET_PYBUF_FLAG(ANY_CONTIGUOUS);
641
+ GET_PYBUF_FLAG(INDIRECT);
642
+ GET_PYBUF_FLAG(FORMAT);
643
+ GET_PYBUF_FLAG(STRIDED);
644
+ GET_PYBUF_FLAG(STRIDED_RO);
645
+ GET_PYBUF_FLAG(RECORDS);
646
+ GET_PYBUF_FLAG(RECORDS_RO);
647
+ GET_PYBUF_FLAG(FULL);
648
+ GET_PYBUF_FLAG(FULL_RO);
649
+ GET_PYBUF_FLAG(CONTIG);
650
+ GET_PYBUF_FLAG(CONTIG_RO);
651
+
652
+ Py_DECREF(tmp);
653
+
654
+ /* One of the flags must match */
655
+ PyErr_SetString(PyExc_ValueError, "invalid flag used.");
656
+ return NULL;
657
+ }
658
+
659
+ if (PyObject_GetBuffer(buffer_obj, &buffer, flags) < 0) {
660
+ return NULL;
661
+ }
662
+
663
+ if (buffer.shape == NULL) {
664
+ Py_INCREF(Py_None);
665
+ shape = Py_None;
666
+ }
667
+ else {
668
+ shape = PyTuple_New(buffer.ndim);
669
+ for (i=0; i < buffer.ndim; i++) {
670
+ PyTuple_SET_ITEM(shape, i, PyLong_FromSsize_t(buffer.shape[i]));
671
+ }
672
+ }
673
+
674
+ if (buffer.strides == NULL) {
675
+ Py_INCREF(Py_None);
676
+ strides = Py_None;
677
+ }
678
+ else {
679
+ strides = PyTuple_New(buffer.ndim);
680
+ for (i=0; i < buffer.ndim; i++) {
681
+ PyTuple_SET_ITEM(strides, i, PyLong_FromSsize_t(buffer.strides[i]));
682
+ }
683
+ }
684
+
685
+ PyBuffer_Release(&buffer);
686
+ return Py_BuildValue("(NN)", shape, strides);
687
+ }
688
+
689
+ #undef GET_PYBUF_FLAG
690
+
691
+
584
692
static PyMethodDef Multiarray_TestsMethods[] = {
585
693
{"test_neighborhood_iterator",
586
694
test_neighborhood_iterator,
@@ -602,6 +710,9 @@ static PyMethodDef Multiarray_TestsMethods[] = {
602
710
int_subclass,
603
711
METH_VARARGS, NULL},
604
712
#endif
713
+ {"get_buffer_info",
714
+ get_buffer_info,
715
+ METH_VARARGS, NULL},
605
716
{NULL, NULL, 0, NULL} /* Sentinel */
606
717
};
607
718
0 commit comments