public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Filipe Rosset <rosset.filipe@gmail.com>
To: git-commits@fedoraproject.org
Subject: [rpms/python-xarray] rawhide: [PATCH] Fix Upstream CI NaT issues (#11340) - backported from upstream
Date: Sat, 01 Aug 2026 18:39:57 GMT	[thread overview]
Message-ID: <178560959724.1.5594343360485081622.rpms-python-xarray-25498ff2a462@fedoraproject.org> (raw)

A new commit has been pushed.

Repo   : rpms/python-xarray
Branch : rawhide
Commit : 25498ff2a462035683d0fced0a4d963aae1e8ce7
Author : Filipe Rosset <rosset.filipe@gmail.com>
Date   : 2026-07-31T00:36:05-03:00
Stats  : +108/-24 in 3 file(s)
URL    : https://src.fedoraproject.org/rpms/python-xarray/c/25498ff2a462035683d0fced0a4d963aae1e8ce7?branch=rawhide

Log:
[PATCH] Fix Upstream CI NaT issues (#11340) - backported from upstream

---
diff --git a/0003-xarray-numpy2-overflow.patch b/0003-xarray-numpy2-overflow.patch
deleted file mode 100644
index 2969d0c..0000000
--- a/0003-xarray-numpy2-overflow.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-Fix OverflowError under NumPy 2.0+ when multiplying np.iinfo(int64).min with timedelta64
-
---- a/xarray/coding/times.py
-+++ b/xarray/coding/times.py
-@@ -390,6 +390,8 @@
-     date, unit: NPDatetimeUnitOptions, ref_date: pd.Timestamp
- ) -> pd.Timestamp:
-     # check for out-of-bounds floats and raise
-+    if date == np.iinfo("int64").min:
-+        return pd.Timestamp("NaT")
-     if date > np.iinfo("int64").max or date < np.iinfo("int64").min:
-         raise OutOfBoundsTimedelta(
-             f"Value {date} can't be represented as Datetime/Timedelta."
-@@ -411,6 +413,8 @@
- 
- 
- def _check_timedelta_range(value, data_unit, time_unit):
-+    if value == np.iinfo("int64").min:
-+        return
-     if value > np.iinfo("int64").max or value < np.iinfo("int64").min:
-         OutOfBoundsTimedelta(f"Value {value} can't be represented as Timedelta.")
-     # on windows multiplying nan leads to RuntimeWarning

diff --git a/c3a398e856f7fcff1c18bc72bfd1ab9c64d5a2e7.patch b/c3a398e856f7fcff1c18bc72bfd1ab9c64d5a2e7.patch
new file mode 100644
index 0000000..f5e4816
--- /dev/null
+++ b/c3a398e856f7fcff1c18bc72bfd1ab9c64d5a2e7.patch
@@ -0,0 +1,105 @@
+From c3a398e856f7fcff1c18bc72bfd1ab9c64d5a2e7 Mon Sep 17 00:00:00 2001
+From: Ian Hunt-Isaak <ianhuntisaak@gmail.com>
+Date: Wed, 3 Jun 2026 12:22:49 -0400
+Subject: [PATCH] Fix Upstream CI NaT issues (#11340)
+
+* Handle int64 NaT sentinel before timedelta64 multiplication
+
+numpy >= 2.5 (numpy/numpy#31378, merged 2026-05-11) turns
+int64.min * timedelta64 from a silent NaT into a hard OverflowError.
+The CF time decode path relied on the silent NaT and now raises through
+_check_date_for_units_since_refdate and _check_timedelta_range, surfacing
+as `ValueError: unable to decode time units '...'` from decode_cf.
+
+Detect the sentinel (and float NaN) up front so the multiplication path
+only sees real numeric inputs. Regression coverage already exists via
+the existing int64.min parametrizations of test_cf_timedelta and
+test_roundtrip_timedelta64_nanosecond_precision.
+
+---
+ xarray/coding/times.py | 64 ++++++++++++++---------------
+ 1 file changed, 32 insertions(+), 32 deletions(-)
+
+diff --git a/xarray/coding/times.py b/xarray/coding/times.py
+index f0a4c195263..f1e27a0245d 100644
+--- a/xarray/coding/times.py
++++ b/xarray/coding/times.py
+@@ -386,45 +386,45 @@ def _decode_datetime_with_cftime(
+         return np.array([], dtype=object)
+ 
+ 
++def _decode_to_timedelta(value, unit: NPDatetimeUnitOptions) -> np.timedelta64:
++    """Decode a single CF-encoded scalar to ``np.timedelta64``.
++
++    Returns NaT for encoded NaT inputs. Raises ``OutOfBoundsTimedelta`` if the
++    value is not representable.
++    """
++    # Integer arrays encode NaT as int64.min (numpy/pandas's NaT bit pattern);
++    # float arrays encode it as NaN. Detect both before the multiplication
++    # below. In numpy >= 2.5 (numpy/numpy#31378) int64.min * timedelta64
++    # raises OverflowError instead of silently producing NaT.
++    if (value.dtype.kind == "i" and int(value) == np.iinfo("int64").min) or (
++        value.dtype.kind == "f" and np.isnan(value)
++    ):
++        return np.timedelta64("NaT", unit)
++    if value > np.iinfo("int64").max or value < np.iinfo("int64").min:
++        raise OutOfBoundsTimedelta(
++            f"Value {value} can't be represented as Datetime/Timedelta."
++        )
++    delta = value * np.timedelta64(1, unit)
++    # uint overflow during the multiplication above
++    if value.dtype.kind in "u" and not np.int64(delta) == value:
++        raise OutOfBoundsTimedelta("DType overflow in Datetime/Timedelta calculation.")
++    return delta
++
++
+ def _check_date_for_units_since_refdate(
+     date, unit: NPDatetimeUnitOptions, ref_date: pd.Timestamp
+ ) -> pd.Timestamp:
+-    # check for out-of-bounds floats and raise
+-    if date > np.iinfo("int64").max or date < np.iinfo("int64").min:
+-        raise OutOfBoundsTimedelta(
+-            f"Value {date} can't be represented as Datetime/Timedelta."
+-        )
+-    delta = date * np.timedelta64(1, unit)
+-    if not np.isnan(delta):
+-        # this will raise on dtype overflow for integer dtypes
+-        if date.dtype.kind in "u" and not np.int64(delta) == date:
+-            raise OutOfBoundsTimedelta(
+-                "DType overflow in Datetime/Timedelta calculation."
+-            )
+-        # this will raise on overflow if ref_date + delta
+-        # can't be represented in the current ref_date resolution
+-        return timestamp_as_unit(ref_date + delta, ref_date.unit)
+-    else:
+-        # if date is exactly NaT (np.iinfo("int64").min) return NaT
+-        # to make follow-up checks work
+-        return pd.Timestamp("NaT")
++    delta = _decode_to_timedelta(date, unit)
++    if np.isnat(delta):
++        return pd.Timestamp("NaT")
++    # this will raise on overflow if ref_date + delta can't be represented in
++    # the current ref_date resolution
++    return timestamp_as_unit(ref_date + delta, ref_date.unit)
+ 
+ 
+ def _check_timedelta_range(value, data_unit, time_unit):
+-    if value > np.iinfo("int64").max or value < np.iinfo("int64").min:
+-        OutOfBoundsTimedelta(f"Value {value} can't be represented as Timedelta.")
+-    # on windows multiplying nan leads to RuntimeWarning
+-    with warnings.catch_warnings():
+-        warnings.filterwarnings(
+-            "ignore", "invalid value encountered in multiply", RuntimeWarning
+-        )
+-        delta = value * np.timedelta64(1, data_unit)
+-    if not np.isnan(delta):
+-        # this will raise on dtype overflow for integer dtypes
+-        if value.dtype.kind in "u" and not np.int64(delta) == value:
+-            raise OutOfBoundsTimedelta(
+-                "DType overflow in Datetime/Timedelta calculation."
+-            )
++    delta = _decode_to_timedelta(value, data_unit)
++    if not np.isnat(delta):
+         # this will raise on overflow if delta cannot be represented with the
+         # resolutions supported by pandas.
+         pd.to_timedelta(delta)

diff --git a/python-xarray.spec b/python-xarray.spec
index c4cd7dd..33dccd8 100644
--- a/python-xarray.spec
+++ b/python-xarray.spec
@@ -19,8 +19,9 @@ Source:         %pypi_source %{srcname}
 Patch:          0001-Drop-pydap-from-dependencies.patch
 # Fix failures with latest dependencies.
 Patch:          https://github.com/pydata/xarray/pull/11204.patch
-# Fix OverflowError under NumPy 2.0+ when date is np.iinfo(int64).min
-Patch:          0003-xarray-numpy2-overflow.patch
+# [PATCH] Fix Upstream CI NaT issues (#11340) - backported from upstream
+# https://github.com/pydata/xarray/commit/c3a398e856f7fcff1c18bc72bfd1ab9c64d5a2e7.patch
+Patch:          c3a398e856f7fcff1c18bc72bfd1ab9c64d5a2e7.patch
 
 BuildArch:      noarch
 

                 reply	other threads:[~2026-08-01 18:39 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178560959724.1.5594343360485081622.rpms-python-xarray-25498ff2a462@fedoraproject.org \
    --to=rosset.filipe@gmail.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox