From df1be99fa8b479bd8f43b65d7456e787391c7c62 Mon Sep 17 00:00:00 2001 From: Bertrand MICHEL Date: Mon, 15 Feb 2021 17:17:14 +0100 Subject: [PATCH 1/8] [dtype]: add type() method to access type attribute of PyArray_Descr (eq. to dtype.char in Python) --- include/pybind11/numpy.h | 7 ++++++- tests/test_numpy_dtypes.cpp | 34 ++++++++++++++++++++++++++++++++++ tests/test_numpy_dtypes.py | 6 ++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 019f5688e7..bfc0a77aea 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -507,11 +507,16 @@ class dtype : public object { return detail::array_descriptor_proxy(m_ptr)->names != nullptr; } - /// Single-character type code. + /// Single-character for dtype's kind (ex: float and double are 'f' or int and long int are 'i') char kind() const { return detail::array_descriptor_proxy(m_ptr)->kind; } + /// Single-character for dtype's type (ex: float is 'f' and double 'd') + char type() const { + return detail::array_descriptor_proxy(m_ptr)->type; + } + private: static object _dtype_from_pep3118() { static PyObject *obj = module_::import("numpy.core._internal") diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index b2e5e60756..56f75b51a6 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -251,6 +251,38 @@ py::list test_dtype_ctors() { return list; } +py::list test_dtype_kind() { + py::list list; + for (auto& dt : { + py::dtype("bool8"), // bool + py::dtype("int16"), // short + py::dtype("int32"), // int + py::dtype("int64"), // long int + py::dtype("float32"), // float + py::dtype("float64"), // double + py::dtype("float128") // long double + }) { + list.append(dt.kind()); + } + return list; +} + +py::list test_dtype_type() { + py::list list; + for (auto& dt : { + py::dtype("bool8"), // bool + py::dtype("int16"), // short + py::dtype("int32"), // int + py::dtype("int64"), // long int + py::dtype("float32"), // float + py::dtype("float64"), // double + py::dtype("float128") // long double + }) { + list.append(dt.type()); + } + return list; +} + struct A {}; struct B {}; @@ -376,6 +408,8 @@ TEST_SUBMODULE(numpy_dtypes, m) { return l; }); m.def("test_dtype_ctors", &test_dtype_ctors); + m.def("test_dtype_kind", &test_dtype_kind); + m.def("test_dtype_type", &test_dtype_type); m.def("test_dtype_methods", []() { py::list list; auto dt1 = py::dtype::of(); diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index f56b776a40..f76753ac84 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -169,6 +169,12 @@ def test_dtype(simple_dtype): np.zeros(1, m.trailing_padding_dtype()) ) + # for dt in m.test_dtype_kind(): + # print("dt = ",dt) + assert m.test_dtype_kind() == ['b'] + ['i']*3 + ['f']*3 + assert m.test_dtype_type() == ['?', 'h', 'i', 'l', 'f', 'd', 'g'] + # assert False + def test_recarray(simple_dtype, packed_dtype): elements = [(False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)] From b59299da13eacd1bedbf35203a0b92b333c54027 Mon Sep 17 00:00:00 2001 From: Bertrand MICHEL Date: Mon, 15 Feb 2021 18:36:26 +0100 Subject: [PATCH 2/8] [dtype] change type() name method to char_() to be compliant with Python numpy interface --- include/pybind11/numpy.h | 2 +- tests/test_numpy_dtypes.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index bfc0a77aea..0f30a890fc 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -513,7 +513,7 @@ class dtype : public object { } /// Single-character for dtype's type (ex: float is 'f' and double 'd') - char type() const { + char char_() const { return detail::array_descriptor_proxy(m_ptr)->type; } diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index 56f75b51a6..d5e844370c 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -278,7 +278,7 @@ py::list test_dtype_type() { py::dtype("float64"), // double py::dtype("float128") // long double }) { - list.append(dt.type()); + list.append(dt.char_()); } return list; } From 14005204a9424310dbeede5fd89e74e5b6c9ada3 Mon Sep 17 00:00:00 2001 From: Bertrand MICHEL Date: Wed, 17 Feb 2021 15:53:48 +0100 Subject: [PATCH 3/8] [dtype] fix by pre-commit --- tests/test_numpy_dtypes.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index f76753ac84..329f6ba5b8 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -169,11 +169,8 @@ def test_dtype(simple_dtype): np.zeros(1, m.trailing_padding_dtype()) ) - # for dt in m.test_dtype_kind(): - # print("dt = ",dt) - assert m.test_dtype_kind() == ['b'] + ['i']*3 + ['f']*3 - assert m.test_dtype_type() == ['?', 'h', 'i', 'l', 'f', 'd', 'g'] - # assert False + assert m.test_dtype_kind() == ["b"] + ["i"] * 3 + ["f"] * 3 + assert m.test_dtype_type() == ["?", "h", "i", "l", "f", "d", "g"] def test_recarray(simple_dtype, packed_dtype): From f4552221db3b69f1ca4fcc775df85496496f725e Mon Sep 17 00:00:00 2001 From: Bertrand MICHEL Date: Wed, 17 Feb 2021 17:46:13 +0100 Subject: [PATCH 4/8] [dtype] Change comments and solutions format for test --- include/pybind11/numpy.h | 12 ++++++++++-- tests/test_numpy_dtypes.cpp | 4 ++-- tests/test_numpy_dtypes.py | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 0f30a890fc..df680a3e3b 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -507,12 +507,20 @@ class dtype : public object { return detail::array_descriptor_proxy(m_ptr)->names != nullptr; } - /// Single-character for dtype's kind (ex: float and double are 'f' or int and long int are 'i') + /** + * Single-character for dtype's kind + * ex: float and double are 'f' or int and long int are 'i', + * i.e. "float and double" could be "floating point types", + * and "int and long" could be "integral types") + */ char kind() const { return detail::array_descriptor_proxy(m_ptr)->kind; } - /// Single-character for dtype's type (ex: float is 'f' and double 'd') + /** Single-character for dtype's type (ex: float is 'f' and double 'd'). + * NB: Following the Python API (i.e., dtype.char) is preferred here + * rather than NumPy's internal C API (PyArray_Descr::type) + */ char char_() const { return detail::array_descriptor_proxy(m_ptr)->type; } diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index d5e844370c..58333dd9ba 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -267,7 +267,7 @@ py::list test_dtype_kind() { return list; } -py::list test_dtype_type() { +py::list test_dtype_char_() { py::list list; for (auto& dt : { py::dtype("bool8"), // bool @@ -409,7 +409,7 @@ TEST_SUBMODULE(numpy_dtypes, m) { }); m.def("test_dtype_ctors", &test_dtype_ctors); m.def("test_dtype_kind", &test_dtype_kind); - m.def("test_dtype_type", &test_dtype_type); + m.def("test_dtype_char_", &test_dtype_char_); m.def("test_dtype_methods", []() { py::list list; auto dt1 = py::dtype::of(); diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index 329f6ba5b8..5ea0318103 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -169,8 +169,8 @@ def test_dtype(simple_dtype): np.zeros(1, m.trailing_padding_dtype()) ) - assert m.test_dtype_kind() == ["b"] + ["i"] * 3 + ["f"] * 3 - assert m.test_dtype_type() == ["?", "h", "i", "l", "f", "d", "g"] + assert m.test_dtype_kind() == list("biiifff") + assert m.test_dtype_char_() == list("?hilfdg") def test_recarray(simple_dtype, packed_dtype): From 400ffeaee0fe75d1e726093066ea6fab49fcc190 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Wed, 17 Feb 2021 18:45:07 +0100 Subject: [PATCH 5/8] Clarify documentation and move note about dtype.char vs PyArray_Descr::type to a plain, non-doxygen comment --- include/pybind11/numpy.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index df680a3e3b..d1ddc4a9db 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -507,21 +507,18 @@ class dtype : public object { return detail::array_descriptor_proxy(m_ptr)->names != nullptr; } - /** - * Single-character for dtype's kind - * ex: float and double are 'f' or int and long int are 'i', - * i.e. "float and double" could be "floating point types", - * and "int and long" could be "integral types") - */ + /// Single-character code for dtype's kind. + /// For example, floating point types are 'f' and integral types are 'i'. char kind() const { return detail::array_descriptor_proxy(m_ptr)->kind; } - /** Single-character for dtype's type (ex: float is 'f' and double 'd'). - * NB: Following the Python API (i.e., dtype.char) is preferred here - * rather than NumPy's internal C API (PyArray_Descr::type) - */ + /// Single-character for dtype's type. + /// For example, ``float`` is 'f', ``double`` 'd', ``int`` 'i', and ``long`` 'd'. char char_() const { + // Note: The signature, `dtype::char_` follows the naming of NumPy's + // public Python API (i.e., ``dtype.char``), rather than its internal + // C API (``PyArray_Descr::type``). return detail::array_descriptor_proxy(m_ptr)->type; } From f3ba900f88c702a9dbb92e631c6ccb5a91b3fe0f Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Wed, 17 Feb 2021 21:00:22 +0100 Subject: [PATCH 6/8] Fix and extend tests --- tests/test_numpy_dtypes.cpp | 34 ++++++++++++---------------------- tests/test_numpy_dtypes.py | 4 ++-- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index 58333dd9ba..fcd6debe08 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -251,35 +251,25 @@ py::list test_dtype_ctors() { return list; } +auto dtype_names = { + "byte", "short", "intc", "int_", "longlong", + "ubyte", "ushort", "uintc", "uint", "ulonglong", + "half", "single", "double", "longdouble", + "csingle", "cdouble", "clongdouble", + "bool_", "datetime64", "timedelta64", "object_" +}; + py::list test_dtype_kind() { py::list list; - for (auto& dt : { - py::dtype("bool8"), // bool - py::dtype("int16"), // short - py::dtype("int32"), // int - py::dtype("int64"), // long int - py::dtype("float32"), // float - py::dtype("float64"), // double - py::dtype("float128") // long double - }) { - list.append(dt.kind()); - } + for (auto& dt_name : dtype_names) + list.append(py::dtype(dt_name).kind()); return list; } py::list test_dtype_char_() { py::list list; - for (auto& dt : { - py::dtype("bool8"), // bool - py::dtype("int16"), // short - py::dtype("int32"), // int - py::dtype("int64"), // long int - py::dtype("float32"), // float - py::dtype("float64"), // double - py::dtype("float128") // long double - }) { - list.append(dt.char_()); - } + for (auto& dt_name : dtype_names) + list.append(py::dtype(dt_name).char_()); return list; } diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index 5ea0318103..0a5881e49d 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -169,8 +169,8 @@ def test_dtype(simple_dtype): np.zeros(1, m.trailing_padding_dtype()) ) - assert m.test_dtype_kind() == list("biiifff") - assert m.test_dtype_char_() == list("?hilfdg") + assert m.test_dtype_kind() == list("iiiiiuuuuuffffcccbMmO") + assert m.test_dtype_char_() == list("bhilqBHILQefdgFDG?MmO") def test_recarray(simple_dtype, packed_dtype): From 14c9f7d52289a75193f7e0684c60ec5f6cd6fac3 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Wed, 17 Feb 2021 21:14:39 +0100 Subject: [PATCH 7/8] Fix the supposedly fixed tests --- tests/test_numpy_dtypes.cpp | 44 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index fcd6debe08..39e23fb20d 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -251,28 +251,6 @@ py::list test_dtype_ctors() { return list; } -auto dtype_names = { - "byte", "short", "intc", "int_", "longlong", - "ubyte", "ushort", "uintc", "uint", "ulonglong", - "half", "single", "double", "longdouble", - "csingle", "cdouble", "clongdouble", - "bool_", "datetime64", "timedelta64", "object_" -}; - -py::list test_dtype_kind() { - py::list list; - for (auto& dt_name : dtype_names) - list.append(py::dtype(dt_name).kind()); - return list; -} - -py::list test_dtype_char_() { - py::list list; - for (auto& dt_name : dtype_names) - list.append(py::dtype(dt_name).char_()); - return list; -} - struct A {}; struct B {}; @@ -380,6 +358,14 @@ TEST_SUBMODULE(numpy_dtypes, m) { }); // test_dtype + auto dtype_names = { + "byte", "short", "intc", "int_", "longlong", + "ubyte", "ushort", "uintc", "uint", "ulonglong", + "half", "single", "double", "longdouble", + "csingle", "cdouble", "clongdouble", + "bool_", "datetime64", "timedelta64", "object_" + }; + m.def("print_dtypes", []() { py::list l; for (const py::handle &d : { @@ -398,8 +384,18 @@ TEST_SUBMODULE(numpy_dtypes, m) { return l; }); m.def("test_dtype_ctors", &test_dtype_ctors); - m.def("test_dtype_kind", &test_dtype_kind); - m.def("test_dtype_char_", &test_dtype_char_); + m.def("test_dtype_kind", [dtype_names]() { + py::list list; + for (auto& dt_name : dtype_names) + list.append(py::dtype(dt_name).kind()); + return list; + }); + m.def("test_dtype_char_", [dtype_names]() { + py::list list; + for (auto& dt_name : dtype_names) + list.append(py::dtype(dt_name).char_()); + return list; + }); m.def("test_dtype_methods", []() { py::list list; auto dt1 = py::dtype::of(); From 46701eca04ae5041f4f07ca3a8c6cd9f9145c024 Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Wed, 17 Feb 2021 21:25:24 +0100 Subject: [PATCH 8/8] Fix the fixed tests again --- tests/test_numpy_dtypes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp index 39e23fb20d..9dece73ec3 100644 --- a/tests/test_numpy_dtypes.cpp +++ b/tests/test_numpy_dtypes.cpp @@ -358,7 +358,7 @@ TEST_SUBMODULE(numpy_dtypes, m) { }); // test_dtype - auto dtype_names = { + std::vector dtype_names{ "byte", "short", "intc", "int_", "longlong", "ubyte", "ushort", "uintc", "uint", "ulonglong", "half", "single", "double", "longdouble",