mirror of
https://github.com/pybind/pybind11.git
synced 2026-03-14 20:27:47 +00:00
Add format_descriptor<> & npy_format_descriptor<> PyObject * specializations. (#4674)
* Add `npy_format_descriptor<PyObject *>` to enable `py::array_t<PyObject *>` to/from-python conversions.
* resolve clang-tidy warning
* Use existing constructor instead of adding a static method. Thanks @Skylion007 for pointing out.
* Add `format_descriptor<PyObject *>`
Trivial addition, but still in search for a meaningful test.
* Add test_format_descriptor_format
* Ensure the Eigen `type_caster`s do not segfault when loading arrays with dtype=object
* Use `static_assert()` `!std::is_pointer<>` to replace runtime guards.
* Add comments to explain how to check for ref-count bugs. (NO code changes.)
* Make the "Pointer types ... are not supported" message Eigen-specific, as suggested by @Lalaland. Move to new pybind11/eigen/common.h header.
* Change "format_descriptor_format" implementation as suggested by @Lalaland. Additional tests meant to ensure consistency between py::format_descriptor<>, np.array, np.format_parser turn out to be useful only to highlight long-standing inconsistencies.
* resolve clang-tidy warning
* Account for np.float128, np.complex256 not being available on Windows, in a future-proof way.
* Fully address i|q|l ambiguity (hopefully).
* Remove the new `np.format_parser()`-based test, it's much more distracting than useful.
* Use bi.itemsize to disambiguate "l" or "L"
* Use `py::detail::compare_buffer_info<T>::compare()` to validate the `format_descriptor<T>::format()` strings.
* Add `buffer_info::compare<T>` to make `detail::compare_buffer_info<T>::compare` more visible & accessible.
* silence clang-tidy warning
* pytest-compatible access to np.float128, np.complex256
* Revert "pytest-compatible access to np.float128, np.complex256"
This reverts commit e9a289c50f.
* Use `sizeof(long double) == sizeof(double)` instead of `std::is_same<>`
* Report skipped `long double` tests.
* Change the name of the new `buffer_info` member function to `item_type_is_equivalent_to`. Add comment defining "equivalent" by example.
* Change `item_type_is_equivalent_to<>()` from `static` function to member function, as suggested by @Lalaland
This commit is contained in:
committed by
GitHub
parent
6e6bcca5b2
commit
8e1f9d5c40
@@ -10,6 +10,63 @@ from pybind11_tests import buffers as m
|
||||
|
||||
np = pytest.importorskip("numpy")
|
||||
|
||||
if m.long_double_and_double_have_same_size:
|
||||
# Determined by the compiler used to build the pybind11 tests
|
||||
# (e.g. MSVC gets here, but MinGW might not).
|
||||
np_float128 = None
|
||||
np_complex256 = None
|
||||
else:
|
||||
# Determined by the compiler used to build numpy (e.g. MinGW).
|
||||
np_float128 = getattr(np, *["float128"] * 2)
|
||||
np_complex256 = getattr(np, *["complex256"] * 2)
|
||||
|
||||
CPP_NAME_FORMAT_NP_DTYPE_TABLE = [
|
||||
("PyObject *", "O", object),
|
||||
("bool", "?", np.bool_),
|
||||
("std::int8_t", "b", np.int8),
|
||||
("std::uint8_t", "B", np.uint8),
|
||||
("std::int16_t", "h", np.int16),
|
||||
("std::uint16_t", "H", np.uint16),
|
||||
("std::int32_t", "i", np.int32),
|
||||
("std::uint32_t", "I", np.uint32),
|
||||
("std::int64_t", "q", np.int64),
|
||||
("std::uint64_t", "Q", np.uint64),
|
||||
("float", "f", np.float32),
|
||||
("double", "d", np.float64),
|
||||
("long double", "g", np_float128),
|
||||
("std::complex<float>", "Zf", np.complex64),
|
||||
("std::complex<double>", "Zd", np.complex128),
|
||||
("std::complex<long double>", "Zg", np_complex256),
|
||||
]
|
||||
CPP_NAME_FORMAT_TABLE = [
|
||||
(cpp_name, format)
|
||||
for cpp_name, format, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
|
||||
if np_dtype is not None
|
||||
]
|
||||
CPP_NAME_NP_DTYPE_TABLE = [
|
||||
(cpp_name, np_dtype) for cpp_name, _, np_dtype in CPP_NAME_FORMAT_NP_DTYPE_TABLE
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("cpp_name", "np_dtype"), CPP_NAME_NP_DTYPE_TABLE)
|
||||
def test_format_descriptor_format_buffer_info_equiv(cpp_name, np_dtype):
|
||||
if np_dtype is None:
|
||||
pytest.skip(
|
||||
f"cpp_name=`{cpp_name}`: `long double` and `double` have same size."
|
||||
)
|
||||
if isinstance(np_dtype, str):
|
||||
pytest.skip(f"np.{np_dtype} does not exist.")
|
||||
np_array = np.array([], dtype=np_dtype)
|
||||
for other_cpp_name, expected_format in CPP_NAME_FORMAT_TABLE:
|
||||
format, np_array_is_matching = m.format_descriptor_format_buffer_info_equiv(
|
||||
other_cpp_name, np_array
|
||||
)
|
||||
assert format == expected_format
|
||||
if other_cpp_name == cpp_name:
|
||||
assert np_array_is_matching
|
||||
else:
|
||||
assert not np_array_is_matching
|
||||
|
||||
|
||||
def test_from_python():
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
|
||||
Reference in New Issue
Block a user