From fefab07cfeb168f88a50f326af4fcb70afcda811 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sun, 19 Jan 2025 04:47:23 -0500 Subject: [PATCH 1/7] Avoid unsafe casts from float to unsigned int Fixes #9815 --- xarray/coding/variables.py | 5 ++++- xarray/core/duck_array_ops.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/xarray/coding/variables.py b/xarray/coding/variables.py index 83112628dbb..b036fd5dfb6 100644 --- a/xarray/coding/variables.py +++ b/xarray/coding/variables.py @@ -426,7 +426,10 @@ def encode(self, variable: Variable, name: T_Name = None): if fill_value is not None and has_unsigned: pop_to(encoding, attrs, "_Unsigned") # XXX: Is this actually needed? Doesn't the backend handle this? - data = duck_array_ops.astype(duck_array_ops.around(data), dtype) + signed_dtype = np.dtype(f"i{dtype.itemsize}") + data = duck_array_ops.view( + duck_array_ops.astype(duck_array_ops.around(data), signed_dtype), dtype + ) attrs["_FillValue"] = fill_value return Variable(dims, data, attrs, encoding, fastpath=True) diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index 7e7333fd8ea..be842b661c3 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -236,6 +236,16 @@ def astype(data, dtype, **kwargs): return data.astype(dtype, **kwargs) +def view(data, *args, **kwargs): + if hasattr(data, "__array_namespace__"): + xp = get_array_namespace(data) + if xp == np: + # numpy currently doesn't have a view: + return data.view(*args, **kwargs) + return xp.view(data, *args, **kwargs) + return data.view(*args, **kwargs) + + def asarray(data, xp=np, dtype=None): converted = data if is_duck_array(data) else xp.asarray(data) From 78138268677cd2a2e50fa9ba87e9761d29996698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=BChlbauer?= Date: Tue, 27 May 2025 11:53:41 +0200 Subject: [PATCH 2/7] Update xarray/coding/variables.py --- xarray/coding/variables.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xarray/coding/variables.py b/xarray/coding/variables.py index b036fd5dfb6..2c94cbb298b 100644 --- a/xarray/coding/variables.py +++ b/xarray/coding/variables.py @@ -426,9 +426,9 @@ def encode(self, variable: Variable, name: T_Name = None): if fill_value is not None and has_unsigned: pop_to(encoding, attrs, "_Unsigned") # XXX: Is this actually needed? Doesn't the backend handle this? - signed_dtype = np.dtype(f"i{dtype.itemsize}") - data = duck_array_ops.view( - duck_array_ops.astype(duck_array_ops.around(data), signed_dtype), dtype + signed_dtype = np.dtype(f"i{data.itemsize}") + data = duck_array_ops.astype( + duck_array_ops.astype(duck_array_ops.around(data), signed_dtype, copy=False), dtype, copy=False ) attrs["_FillValue"] = fill_value From dabed1da739269afd2791bd7ac43ba8434a5c9a4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 09:54:19 +0000 Subject: [PATCH 3/7] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- xarray/coding/variables.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xarray/coding/variables.py b/xarray/coding/variables.py index 52b8b0583b7..42e0a9f7edc 100644 --- a/xarray/coding/variables.py +++ b/xarray/coding/variables.py @@ -347,7 +347,11 @@ def encode(self, variable: Variable, name: T_Name = None): # XXX: Is this actually needed? Doesn't the backend handle this? signed_dtype = np.dtype(f"i{data.itemsize}") data = duck_array_ops.astype( - duck_array_ops.astype(duck_array_ops.around(data), signed_dtype, copy=False), dtype, copy=False + duck_array_ops.astype( + duck_array_ops.around(data), signed_dtype, copy=False + ), + dtype, + copy=False, ) attrs["_FillValue"] = fill_value From 22edc3b9378c1d62ea7cb324f86059465454a917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=BChlbauer?= Date: Mon, 2 Jun 2025 10:29:09 +0200 Subject: [PATCH 4/7] Update duck_array_ops.py --- xarray/core/duck_array_ops.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index c95831a292b..b689ba66f2e 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -265,18 +265,6 @@ def view(data, *args, **kwargs): return data.view(*args, **kwargs) -def asarray(data, xp=np, dtype=None): - converted = data if is_duck_array(data) else xp.asarray(data) - - if dtype is None or converted.dtype == dtype: - return converted - - if xp is np or not hasattr(xp, "astype"): - return converted.astype(dtype) - else: - return xp.astype(converted, dtype) - - def as_shared_dtype(scalars_or_arrays, xp=None): """Cast a arrays to a shared dtype using xarray's type promotion rules.""" if any(is_extension_array_dtype(x) for x in scalars_or_arrays): From d82300a1405a2d2c811cddb9338f1121a881690e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=BChlbauer?= Date: Mon, 2 Jun 2025 10:32:37 +0200 Subject: [PATCH 5/7] Update duck_array_ops.py --- xarray/core/duck_array_ops.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/xarray/core/duck_array_ops.py b/xarray/core/duck_array_ops.py index b689ba66f2e..48dc3b7627a 100644 --- a/xarray/core/duck_array_ops.py +++ b/xarray/core/duck_array_ops.py @@ -255,14 +255,16 @@ def astype(data, dtype, *, xp=None, **kwargs): return xp.astype(data, dtype, **kwargs) -def view(data, *args, **kwargs): - if hasattr(data, "__array_namespace__"): - xp = get_array_namespace(data) - if xp == np: - # numpy currently doesn't have a view: - return data.view(*args, **kwargs) - return xp.view(data, *args, **kwargs) - return data.view(*args, **kwargs) +def asarray(data, xp=np, dtype=None): + converted = data if is_duck_array(data) else xp.asarray(data) + + if dtype is None or converted.dtype == dtype: + return converted + + if xp is np or not hasattr(xp, "astype"): + return converted.astype(dtype) + else: + return xp.astype(converted, dtype) def as_shared_dtype(scalars_or_arrays, xp=None): From 89a50b6dfbb85af7d0966b1c352460c79f94daab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=BChlbauer?= Date: Mon, 2 Jun 2025 10:40:18 +0200 Subject: [PATCH 6/7] Update whats-new.rst --- doc/whats-new.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index bee4156f1e5..ee7a32bed6e 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -62,6 +62,8 @@ Bug fixes calendar of the datetimes from ``"proleptic_gregorian"`` to ``"gregorian"`` and prevents round-tripping them as :py:class:`numpy.datetime64` values (:pull:`10352`). By `Spencer Clark `_. +- Avoid unsafe casts from float to unsigned int in CFMaskCoder (:issue:`9815`, :pull:`9964`). + By ` Elliott Sales de Andrade `_. Performance ~~~~~~~~~~~ From 63e784e86893dace24823f76d8345707bf766244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=BChlbauer?= Date: Mon, 2 Jun 2025 10:46:40 +0200 Subject: [PATCH 7/7] Update variables.py add comment --- xarray/coding/variables.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xarray/coding/variables.py b/xarray/coding/variables.py index 42e0a9f7edc..96413da1e8f 100644 --- a/xarray/coding/variables.py +++ b/xarray/coding/variables.py @@ -345,6 +345,9 @@ def encode(self, variable: Variable, name: T_Name = None): if fill_value is not None and has_unsigned: pop_to(encoding, attrs, "_Unsigned") # XXX: Is this actually needed? Doesn't the backend handle this? + # two-stage casting to prevent undefined cast from float to unsigned int + # first float -> int with corresponding itemsize + # second int -> int/uint to final itemsize signed_dtype = np.dtype(f"i{data.itemsize}") data = duck_array_ops.astype( duck_array_ops.astype( pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy