1From 74a767d42921001fc4569ecee3b8726383c42ad4 Mon Sep 17 00:00:00 2001 2From: Bertrand MICHEL <[email protected]> 3Date: Tue, 23 Feb 2021 10:57:28 +0100 4Subject: [PATCH] Dtype kind vs char (#2864) 5 6* [dtype]: add type() method to access type attribute of PyArray_Descr (eq. to dtype.char in Python) 7 8* [dtype] change type() name method to char_() to be compliant with Python numpy interface 9 10* [dtype] fix by pre-commit 11 12* [dtype] Change comments and solutions format for test 13 14* Clarify documentation and move note about dtype.char vs PyArray_Descr::type to a plain, non-doxygen comment 15 16* Fix and extend tests 17 18* Fix the supposedly fixed tests 19 20* Fix the fixed tests again 21 22Co-authored-by: Bertrand MICHEL <[email protected]> 23Co-authored-by: Yannick Jadoul <[email protected]> 24--- 25 include/pybind11/numpy.h | 12 +++++++++++- 26 tests/test_numpy_dtypes.cpp | 20 ++++++++++++++++++++ 27 tests/test_numpy_dtypes.py | 3 +++ 28 3 files changed, 34 insertions(+), 1 deletion(-) 29 30diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h 31index 019f5688e7..d1ddc4a9db 100644 32--- a/include/pybind11/numpy.h 33+++ b/include/pybind11/numpy.h 34@@ -507,11 +507,21 @@ class dtype : public object { 35 return detail::array_descriptor_proxy(m_ptr)->names != nullptr; 36 } 37 38- /// Single-character type code. 39+ /// Single-character code for dtype's kind. 40+ /// For example, floating point types are 'f' and integral types are 'i'. 41 char kind() const { 42 return detail::array_descriptor_proxy(m_ptr)->kind; 43 } 44 45+ /// Single-character for dtype's type. 46+ /// For example, ``float`` is 'f', ``double`` 'd', ``int`` 'i', and ``long`` 'd'. 47+ char char_() const { 48+ // Note: The signature, `dtype::char_` follows the naming of NumPy's 49+ // public Python API (i.e., ``dtype.char``), rather than its internal 50+ // C API (``PyArray_Descr::type``). 51+ return detail::array_descriptor_proxy(m_ptr)->type; 52+ } 53+ 54 private: 55 static object _dtype_from_pep3118() { 56 static PyObject *obj = module_::import("numpy.core._internal") 57diff --git a/tests/test_numpy_dtypes.cpp b/tests/test_numpy_dtypes.cpp 58index b2e5e60756..9dece73ec3 100644 59--- a/tests/test_numpy_dtypes.cpp 60+++ b/tests/test_numpy_dtypes.cpp 61@@ -358,6 +358,14 @@ TEST_SUBMODULE(numpy_dtypes, m) { 62 }); 63 64 // test_dtype 65+ std::vector<const char *> dtype_names{ 66+ "byte", "short", "intc", "int_", "longlong", 67+ "ubyte", "ushort", "uintc", "uint", "ulonglong", 68+ "half", "single", "double", "longdouble", 69+ "csingle", "cdouble", "clongdouble", 70+ "bool_", "datetime64", "timedelta64", "object_" 71+ }; 72+ 73 m.def("print_dtypes", []() { 74 py::list l; 75 for (const py::handle &d : { 76@@ -376,6 +384,18 @@ TEST_SUBMODULE(numpy_dtypes, m) { 77 return l; 78 }); 79 m.def("test_dtype_ctors", &test_dtype_ctors); 80+ m.def("test_dtype_kind", [dtype_names]() { 81+ py::list list; 82+ for (auto& dt_name : dtype_names) 83+ list.append(py::dtype(dt_name).kind()); 84+ return list; 85+ }); 86+ m.def("test_dtype_char_", [dtype_names]() { 87+ py::list list; 88+ for (auto& dt_name : dtype_names) 89+ list.append(py::dtype(dt_name).char_()); 90+ return list; 91+ }); 92 m.def("test_dtype_methods", []() { 93 py::list list; 94 auto dt1 = py::dtype::of<int32_t>(); 95diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py 96index f56b776a40..0a5881e49d 100644 97--- a/tests/test_numpy_dtypes.py 98+++ b/tests/test_numpy_dtypes.py 99@@ -169,6 +169,9 @@ def test_dtype(simple_dtype): 100 np.zeros(1, m.trailing_padding_dtype()) 101 ) 102 103+ assert m.test_dtype_kind() == list("iiiiiuuuuuffffcccbMmO") 104+ assert m.test_dtype_char_() == list("bhilqBHILQefdgFDG?MmO") 105+ 106 107 def test_recarray(simple_dtype, packed_dtype): 108 elements = [(False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)] 109