diff --git a/changes/3797.bugfix.md b/changes/3797.bugfix.md new file mode 100644 index 0000000000..c683213c5d --- /dev/null +++ b/changes/3797.bugfix.md @@ -0,0 +1,2 @@ +Fix an issue that prevents the correct parsing of special NumPy ``uint32`` dtypes resulting e.g. +from bit wise operations on ``uint32`` arrays on Windows. diff --git a/src/zarr/core/dtype/npy/int.py b/src/zarr/core/dtype/npy/int.py index f71f535abb..e5007b7acb 100644 --- a/src/zarr/core/dtype/npy/int.py +++ b/src/zarr/core/dtype/npy/int.py @@ -1070,6 +1070,28 @@ class UInt32(BaseInt[np.dtypes.UInt32DType, np.uint32], HasEndianness): _zarr_v3_name: ClassVar[Literal["uint32"]] = "uint32" _zarr_v2_names: ClassVar[tuple[Literal[">u4"], Literal["u4", " TypeGuard[np.dtypes.UInt32DType]: + """ + A type guard that checks if the input is assignable to the type of ``cls.dtype_class`` + + This method is overridden for this particular data type because of a Windows-specific issue + where ``np.array([1], dtype=np.uint32) & 1`` creates an instance of ``np.dtypes.UIntDType``, + rather than an instance of ``np.dtypes.UInt32DType``, even though both represent 32-bit + unsigned integers. (In contrast to ``np.dtype('i')``, ``np.dtype('u')`` raises an error.) + + Parameters + ---------- + dtype : TDType + The dtype to check. + + Returns + ------- + Bool + True if the dtype matches, False otherwise. + """ + return super()._check_native_dtype(dtype) or dtype == np.dtypes.UInt32DType() + @classmethod def from_native_dtype(cls, dtype: TBaseDType) -> Self: """ diff --git a/tests/test_dtype/test_npy/test_int.py b/tests/test_dtype/test_npy/test_int.py index f53ec7f5ae..9eab053080 100644 --- a/tests/test_dtype/test_npy/test_int.py +++ b/tests/test_dtype/test_npy/test_int.py @@ -216,7 +216,16 @@ class TestUInt16(BaseTestZDType): class TestUInt32(BaseTestZDType): test_cls = UInt32 scalar_type = np.uint32 - valid_dtype = (np.dtype(">u4"), np.dtype("u4"), np.dtype("