From 436a1b6a03298338a4027c4ca374b73480adff14 Mon Sep 17 00:00:00 2001 From: Nicholas Devenish Date: Tue, 25 Jul 2023 18:42:06 +0100 Subject: [PATCH] Flumpy: Don't allow converting 1D vectors to vec2/3 (#648) Previously, a size (3,) array would have erroneously converted to a 0x3 length vec3. This is now explicitly forbidden; you must pass at least a (0, 3) multidimensional array. Fixes #439. --- newsfragments/439.bugfix | 1 + src/dxtbx/boost_python/flumpy.cc | 7 +++++++ tests/test_flumpy.py | 10 +++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 newsfragments/439.bugfix diff --git a/newsfragments/439.bugfix b/newsfragments/439.bugfix new file mode 100644 index 000000000..a97cc5116 --- /dev/null +++ b/newsfragments/439.bugfix @@ -0,0 +1 @@ +``flumpy``: Fix case where incorrect ``flex.vec2``, ``flex.vec3`` could be generated. diff --git a/src/dxtbx/boost_python/flumpy.cc b/src/dxtbx/boost_python/flumpy.cc index 12e5ebf94..d7ce34b20 100644 --- a/src/dxtbx/boost_python/flumpy.cc +++ b/src/dxtbx/boost_python/flumpy.cc @@ -520,6 +520,13 @@ py::object vec_from_numpy(py::array np_array) { static_assert(VecType::fixed_size == 2 || VecType::fixed_size == 3, "Only vec2/vec3 supported"); + + // Only accept arrays that have a dimension higher than 1 - we want + // numpy.array([1,2,3]) to fail but numpy.array([[1,2,3]]) to work + if (np_array.ndim() == 1) { + throw std::invalid_argument("Array for conversion to vec must be multidimensional"); + } + // Only accept arrays whose last dimension is the size of this object if (np_array.shape(np_array.ndim() - 1) != VecType::fixed_size) { throw std::invalid_argument("Input array last dimension is not size " diff --git a/tests/test_flumpy.py b/tests/test_flumpy.py index cd09e3c09..88ef9f8cc 100644 --- a/tests/test_flumpy.py +++ b/tests/test_flumpy.py @@ -136,7 +136,7 @@ def test_reverse_numeric_2d(flex_numeric): def test_numeric_4d(flex_numeric): - #  Check that we can think fourth-dimnesionally + # Check that we can think fourth-dimensionally grid = flex.grid(1, 9, 8, 5) fo = flex_numeric(grid) assert fo.nd() == 4 @@ -402,3 +402,11 @@ def test_int_long_degeneracy(): npo[0] = 42 assert all(fo[x] == npo[x] for x in range(4)) assert fo[0] == 42 + + +def test_single_entry_vec_from_numpy(): + with pytest.raises(ValueError): + flumpy.vec_from_numpy(np.array([2.0, 3.0, 4.0])) + ao = flumpy.vec_from_numpy(np.array([[2.0, 3.0, 4.0]])) + assert len(ao) == 1 + assert ao[0] == pytest.approx([2.0, 3.0, 4.0])