aboderinsamuel commented on code in PR #50203:
URL: https://github.com/apache/arrow/pull/50203#discussion_r3477415070


##########
python/pyarrow/array.pxi:
##########
@@ -266,6 +266,26 @@ def array(object obj, type=None, mask=None, size=None, 
from_pandas=None,
     if type is not None and type.id == _Type_EXTENSION:
         extension_type = type
         type = type.storage_type
+        # GH-49644: when building a fixed_shape_tensor from a sequence of 
arrays,
+        # the converter only sees the flat storage type, so validate the
+        # tensor-specific constraints here where the type is still known.
+        if (isinstance(extension_type, FixedShapeTensorType)
+                and isinstance(obj, Sequence)
+                and not _is_array_like(obj)
+                and not isinstance(obj, (str, bytes, bytearray))):
+            if extension_type.permutation is not None:
+                raise NotImplementedError(
+                    "Converting a sequence of arrays to a fixed_shape_tensor 
with "
+                    "a permutation is not supported; use "
+                    "FixedShapeTensorArray.from_numpy_ndarray instead")
+            if np is not None:
+                expected_shape = tuple(extension_type.shape)
+                for element in obj:
+                    if (isinstance(element, np.ndarray) and element.ndim >= 2
+                            and tuple(element.shape) != expected_shape):
+                        raise ValueError(
+                            f"Cannot convert array of shape {element.shape} to 
a "
+                            f"fixed_shape_tensor of shape {expected_shape}")

Review Comment:
   Simplified, with two tweaks: I used getattr(element, "shape", None) so it 
isn't numpy-specific (works for any array-like with a shape) and safely skips 
None/non-array elements. I kept it a loop rather than any(...), since the any() 
form leaves `element` undefined in the error message and would raise on None 
elements.



##########
python/pyarrow/tests/test_array.py:
##########
@@ -2924,6 +2924,36 @@ def test_array_from_invalid_dim_raises():
         pa.array(arr0d)
 
 
[email protected]
+def test_fixed_size_list_from_multidim_ndarray():
+    # GH-49644: a fixed-size list can be built from multi-dimensional ndarray
+    # elements by flattening them in C order.
+    arr = pa.array([np.array([[1, 2, 3]], dtype=np.int64),
+                    np.array([[4, 5, 6]], dtype=np.int64)],
+                   type=pa.list_(pa.int64(), 3))
+    assert arr.type == pa.list_(pa.int64(), 3)
+    assert arr.to_pylist() == [[1, 2, 3], [4, 5, 6]]
+
+    # A non-trivial 2D shape confirms values are flattened in C (row-major) 
order
+    arr = pa.array([np.array([[1, 2], [3, 4]], dtype=np.int64)],
+                   type=pa.list_(pa.int64(), 4))
+    assert arr.to_pylist() == [[1, 2, 3, 4]]
+
+    # The flattened length must still match the fixed size
+    with pytest.raises(pa.lib.ArrowInvalid):
+        pa.array([np.array([[1, 2], [3, 4]], dtype=np.int64)],
+                 type=pa.list_(pa.int64(), 3))
+
+    # Variable-sized lists still require 1-dimensional values
+    with pytest.raises(pa.lib.ArrowInvalid, match="1-dimensional"):
+        pa.array([np.array([[1, 2, 3]], dtype=np.int64)],
+                 type=pa.list_(pa.int64()))
+
+    # 0-dimensional arrays are still rejected (not flattened to length 1)
+    with pytest.raises(pa.lib.ArrowInvalid, match="1-dimensional"):
+        pa.array([np.array(1, dtype=np.int64)], type=pa.list_(pa.int64(), 1))

Review Comment:
   Yes , with the 0-D rejection removed, these now work. Updated the test to 
assert the 0-D array builds a length-1 fixed-size list ([[1]]) instead of 
raising.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to