File numpy22.patch of Package python-numba

From 1e2fb1d1c81880a645345991eb48e39b578e119d Mon Sep 17 00:00:00 2001
From: kc611 <ckaustubhm06@gmail.com>
Date: Tue, 4 Mar 2025 13:44:28 +0530
Subject: [PATCH 01/19] Added support for NumPy 2.2

---
 azure-pipelines.yml                           | 20 +++++++++----------
 buildscripts/azure/azure-windows.yml          |  4 ++--
 .../tests/cudadrv/test_cuda_array_slicing.py  |  5 +++--
 numba/np/arrayobj.py                          |  8 +++++++-
 numba/np/npdatetime.py                        |  4 ++++
 numba/np/old_arraymath.py                     | 14 +++++++------
 numba/tests/test_conditions_as_predicates.py  | 19 ++++++++++++------
 numba/tests/test_hashing.py                   | 17 +++++++++-------
 numba/tests/test_np_functions.py              |  8 ++++++--
 numba/tests/test_npdatetime.py                | 12 ++++++++++-
 10 files changed, 74 insertions(+), 37 deletions(-)

Index: numba-0.61.0/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py
===================================================================
--- numba-0.61.0.orig/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py
+++ numba-0.61.0/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py
@@ -186,7 +186,7 @@ class CudaArraySlicing(CUDATestCase):
         for i in range(darr.shape[0]):
             np.testing.assert_array_equal(darr[i:i].copy_to_host(), arr[i:i])
         # empty slice of empty slice
-        self.assertFalse(darr[:0][:0].copy_to_host())
+        np.testing.assert_array_equal(darr[:0][:0].copy_to_host(), np.empty(0))
         # out-of-bound slice just produces empty slices
         np.testing.assert_array_equal(darr[:0][:1].copy_to_host(),
                                       arr[:0][:1])
@@ -199,7 +199,8 @@ class CudaArraySlicing(CUDATestCase):
         np.testing.assert_array_equal(darr[:0].copy_to_host(), arr[:0])
         np.testing.assert_array_equal(darr[3, :0].copy_to_host(), arr[3, :0])
         # empty slice of empty slice
-        self.assertFalse(darr[:0][:0].copy_to_host())
+        np.testing.assert_array_equal(darr[:0][:0].copy_to_host(),
+                                      np.empty((0, 7)))
         # out-of-bound slice just produces empty slices
         np.testing.assert_array_equal(darr[:0][:1].copy_to_host(), arr[:0][:1])
         np.testing.assert_array_equal(darr[:0][-1:].copy_to_host(),
Index: numba-0.61.0/numba/np/arrayobj.py
===================================================================
--- numba-0.61.0.orig/numba/np/arrayobj.py
+++ numba-0.61.0/numba/np/arrayobj.py
@@ -6782,13 +6782,18 @@ def ol_bool(arr):
     if isinstance(arr, types.Array):
         def impl(arr):
             if arr.size == 0:
-                return False # this is deprecated
+                if numpy_version < (2, 2):
+                    return False # this is deprecated
+                else:
+                    raise ValueError(("The truth value of an empty array is "
+                                      "ambiguous. Use `array.size > 0` to "
+                                      "check that an array is not empty."))
             elif arr.size == 1:
                 return bool(arr.take(0))
             else:
-                msg = ("The truth value of an array with more than one element "
-                       "is ambiguous. Use a.any() or a.all()")
-                raise ValueError(msg)
+                raise ValueError(("The truth value of an array with more than"
+                                  " one element is ambiguous. Use a.any() or"
+                                  " a.all()"))
         return impl
 
 
Index: numba-0.61.0/numba/np/npdatetime.py
===================================================================
--- numba-0.61.0.orig/numba/np/npdatetime.py
+++ numba-0.61.0/numba/np/npdatetime.py
@@ -810,6 +810,10 @@ def _cast_npdatetime_int64(context, buil
 @overload_method(types.NPTimedelta, '__hash__')
 @overload_method(types.NPDatetime, '__hash__')
 def ol_hash_npdatetime(x):
+    if numpy_support.numpy_version >= (2, 2)\
+          and isinstance(x, types.NPTimedelta) and not x.unit:
+        raise ValueError("Can't hash generic timedelta64")
+
     if IS_32BITS:
         def impl(x):
             x = np.int64(x)
Index: numba-0.61.0/numba/np/old_arraymath.py
===================================================================
--- numba-0.61.0.orig/numba/np/old_arraymath.py
+++ numba-0.61.0/numba/np/old_arraymath.py
@@ -4818,23 +4818,25 @@ def np_trim_zeros(filt, trim='fb'):
     if not isinstance(trim, (str, types.UnicodeType)):
         raise NumbaTypeError('The second argument must be a string')
 
+    trim_escapes = numpy_version >= (2, 2)
+
     def impl(filt, trim='fb'):
         a_ = np.asarray(filt)
         first = 0
         trim = trim.lower()
         if 'f' in trim:
             for i in a_:
-                if i != 0:
-                    break
-                else:
+                if i == 0 or (trim_escapes and i == ''):
                     first = first + 1
+                else:
+                    break
         last = len(filt)
         if 'b' in trim:
             for i in a_[::-1]:
-                if i != 0:
-                    break
-                else:
+                if i == 0 or (trim_escapes and i == ''):
                     last = last - 1
+                else:
+                    break
         return a_[first:last]
 
     return impl
Index: numba-0.61.0/numba/tests/test_conditions_as_predicates.py
===================================================================
--- numba-0.61.0.orig/numba/tests/test_conditions_as_predicates.py
+++ numba-0.61.0/numba/tests/test_conditions_as_predicates.py
@@ -1,4 +1,4 @@
-from numba.tests.support import TestCase
+from numba.tests.support import TestCase, numpy_support
 from numba import njit, types
 from numba.typed import List, Dict
 import numpy as np
@@ -178,16 +178,23 @@ class TestConditionsAsPredicates(TestCas
 
         # various problems:
 
-        # empty, NumPy warns
+        # empty, NumPy warns or raises if NumPy >= 2.2
         z = np.empty(0)
-        self.assertEqual(foo(z), foo.py_func(z))
-        self.assertEqual(foo.py_func(z), 20)
+        if numpy_support.numpy_version >= (2, 2):
+            with self.assertRaises(ValueError) as raises:
+                foo(z)
+            msg = ("The truth value of an empty array is ambiguous."
+                   " Use `array.size > 0` to check that an array is not empty.")
+            self.assertIn(msg, str(raises.exception))
+        else:
+            self.assertEqual(foo(z), foo.py_func(z))
+            self.assertEqual(foo.py_func(z), 20)
 
         # nd, NumPy raises
         z = np.array([1, 2])
         with self.assertRaises(ValueError) as raises:
             foo(z)
 
-        msg = ("The truth value of an array with more than one element is "
-               "ambiguous. Use a.any() or a.all()")
+        msg = ("The truth value of an array with more than one element "
+               "is ambiguous. Use a.any() or a.all()")
         self.assertIn(msg, str(raises.exception))
Index: numba-0.61.0/numba/tests/test_hashing.py
===================================================================
--- numba-0.61.0.orig/numba/tests/test_hashing.py
+++ numba-0.61.0/numba/tests/test_hashing.py
@@ -186,6 +186,9 @@ class BaseTest(TestCase):
             yield range(start, start + 128 * n, 128)
             yield [-1]
 
+    def safe_construct(self, typ, value):
+        return getattr(np, 'int' + str(np.iinfo(typ).bits))(value).view(typ)
+
     def float_samples(self, typ):
         info = np.finfo(typ)
 
@@ -228,7 +231,7 @@ class TestNumberHashing(BaseTest):
     """
 
     def setUp(self):
-        if numpy_version >= (2, 0):
+        if numpy_version >= (2, 0) and numpy_version <= (2, 1):
             # Temporarily set promotions state to legacy,
             # to ensure overflow logic works
             self.initial_state = np._get_promotion_state()
@@ -237,7 +240,7 @@ class TestNumberHashing(BaseTest):
         return super().setUp()
 
     def tearDown(self) -> None:
-        if numpy_version >= (2, 0):
+        if numpy_version >= (2, 0) and numpy_version <= (2, 1):
             # Reset numpy promotion state to initial state
             # since the setting is global
             np._set_promotion_state(self.initial_state)
@@ -275,7 +278,7 @@ class TestNumberHashing(BaseTest):
             info = np.iinfo(ty)
             # check hash(-1) = -2
             # check hash(0) = 0
-            self.check_hash_values([ty(-1)])
+            self.check_hash_values([self.safe_construct(ty, -1)])
             self.check_hash_values([ty(0)])
             signed = 'uint' not in str(ty)
             # check bit shifting patterns from min through to max
@@ -340,7 +343,7 @@ class TestTupleHashing(BaseTest):
     """
 
     def setUp(self):
-        if numpy_version >= (2, 0):
+        if numpy_version >= (2, 0) and numpy_version <= (2, 1):
             # Temporarily set promotions state to legacy,
             # to ensure overflow logic works
             self.initial_state = np._get_promotion_state()
@@ -349,7 +352,7 @@ class TestTupleHashing(BaseTest):
         return super().setUp()
 
     def tearDown(self) -> None:
-        if numpy_version >= (2, 0):
+        if numpy_version >= (2, 0) and numpy_version <= (2, 1):
             # Reset numpy promotion state to initial state
             # since the setting is global
             np._set_promotion_state(self.initial_state)
@@ -368,7 +371,7 @@ class TestTupleHashing(BaseTest):
             """
             Split i's bits into 2 integers.
             """
-            i = typ(i)
+            i = self.safe_construct(typ, i)
             return (i & typ(0x5555555555555555),
                     i & typ(0xaaaaaaaaaaaaaaaa),
                     )
@@ -377,7 +380,7 @@ class TestTupleHashing(BaseTest):
             """
             Split i's bits into 3 integers.
             """
-            i = typ(i)
+            i = self.safe_construct(typ, i)
             return (i & typ(0x2492492492492492),
                     i & typ(0x4924924924924924),
                     i & typ(0x9249249249249249),
Index: numba-0.61.0/numba/tests/test_np_functions.py
===================================================================
--- numba-0.61.0.orig/numba/tests/test_np_functions.py
+++ numba-0.61.0/numba/tests/test_np_functions.py
@@ -5694,8 +5694,11 @@ class TestNPFunctions(MemoryLeakMixin, T
             yield np.array([0, 1, 2]), 'B'
             yield np.array([np.nan, 0., 1.2, 2.3, 0.]), 'b'
             yield np.array([0, 0, 1, 2, 5]), 'f'
-            yield np.array([0, 1, 2, 0]), 'abf'
-            yield np.array([0, 4, 0]), 'd'
+            if numpy_version < (2, 2):
+                # abf and d are not supported in numpy >= 2.2
+                yield np.array([0, 1, 2, 0]), 'abf'
+                yield np.array([0, 4, 0]), 'd'
+
             yield np.array(['\0', '1', '2']), 'f'
 
         pyfunc = np_trim_zeros
Index: numba-0.61.0/numba/tests/test_npdatetime.py
===================================================================
--- numba-0.61.0.orig/numba/tests/test_npdatetime.py
+++ numba-0.61.0/numba/tests/test_npdatetime.py
@@ -541,7 +541,23 @@ class TestTimedeltaArithmetic(TestCase):
     def test_hash(self):
         f = self.jit(hash_usecase)
         def check(a):
-            self.assertPreciseEqual(f(a), hash(a))
+            if numpy_version >= (2, 2):
+                # Generic timedeltas (those without a unit)
+                # are no longer hashable beyond NumPy 2.2
+                # Non-generic timedeltas will have dtype name
+                # as timedelta64[<unit>]
+                if a.dtype.name == 'timedelta64':
+                    return
+
+                # If the function is not being compiled in objmode
+                # then the hash should be equal to the hash of the
+                # integer representation of the timedelta
+                if self.jitargs.get('nopython', False):
+                    self.assertPreciseEqual(f(a), a.astype(int))
+                else:
+                    self.assertPreciseEqual(f(a), hash(a))
+            else:
+                self.assertPreciseEqual(f(a), hash(a))
 
         TD_CASES = ((3,), (-4,), (3, 'ms'), (-4, 'ms'), (27, 'D'),
                     (2, 'D'), (2, 'W'), (2, 'Y'), (3, 'W'),
@@ -558,6 +574,11 @@ class TestTimedeltaArithmetic(TestCase):
                              (TD,) * len(TD_CASES) + (DT,) * len(TD_CASES)):
             check(typ(*case))
 
+        if numpy_version >= (2, 2):
+            with self.assertRaises(ValueError) as raises:
+                f(TD(3))
+            self.assertIn("Can't hash generic timedelta64", str(raises.exception))
+
     def _test_min_max(self, usecase):
         f = self.jit(usecase)
         def check(a, b):
Index: numba-0.61.0/docs/upcoming_changes/9919.highlight.rst
===================================================================
--- /dev/null
+++ numba-0.61.0/docs/upcoming_changes/9919.highlight.rst
@@ -0,0 +1,26 @@
+Support for NumPy 2.2
+---------------------
+
+Numba now supports NumPy 2.2. following are some notable changes:
+
+- ``np.empty(0)`` cannot be treated as a boolean value anymore. This is a
+  breaking change for code that relies on this behavior. The following code
+  will raise a ``ValueError``:
+
+  .. code-block:: python
+
+      import numpy as np
+      if np.empty(0):
+          print("This will not be printed")
+
+- Generic timedeltas can no longer be hashed due to undefined time units.
+
+- From NumPy 2.2 onwards, hash values for ``numpy.timedelta64`` and
+  ``numpy.datetime64`` instances computed in Numba compiled code do not match
+  the NumPy hash values of the same. Prior to NumPy 2.2, NumPy hash values for
+  ``numpy.timedelta64`` and ``numpy.datetime64`` instances were equivalent to
+  their integer value representation. From NumPy 2.2 onwards, their hash value
+  is the same as the hash of the equivalent type from the built-in ``datetime``
+  module, Numba does not replicate this behaviour.
+
+- ``np.trimzeros`` now also trims ``\0`` values.
Index: numba-0.61.0/docs/source/reference/pysupported.rst
===================================================================
--- numba-0.61.0.orig/docs/source/reference/pysupported.rst
+++ numba-0.61.0/docs/source/reference/pysupported.rst
@@ -968,6 +968,14 @@ in CPython under the condition that the
 The ``PYTHONHASHSEED`` environment variable influences the hashing behavior in
 precisely the manner described in the CPython documentation.
 
+.. note:: From NumPy 2.2 onwards, hash values for ``numpy.timedelta64`` and
+          ``numpy.datetime64`` instances computed in Numba compiled code do not
+          match the NumPy hash values of the same. Prior to NumPy 2.2, NumPy
+          hash values for ``numpy.timedelta64`` and ``numpy.datetime64``
+          instances were equivalent to their integer value representation. From
+          NumPy 2.2 onwards, their hash value is the same as the hash of the
+          equivalent type from the ``datetime`` module, Numba does not replicate
+          this behaviour.
 
 Standard library modules
 ========================
Index: numba-0.61.0/setup.py
===================================================================
--- numba-0.61.0.orig/setup.py
+++ numba-0.61.0/setup.py
@@ -23,7 +23,7 @@ min_python_version = "3.10"
 max_python_version = "3.14"  # exclusive
 min_numpy_build_version = "2.0.0rc1"
 min_numpy_run_version = "1.24"
-max_numpy_run_version = "2.2"
+max_numpy_run_version = "2.3"
 min_llvmlite_version = "0.44.0dev0"
 max_llvmlite_version = "0.45"
 
Index: numba-0.61.0/numba/__init__.py
===================================================================
--- numba-0.61.0.orig/numba/__init__.py
+++ numba-0.61.0/numba/__init__.py
@@ -39,8 +39,8 @@ def _ensure_critical_deps():
                f"{numpy_version[0]}.{numpy_version[1]}.")
         raise ImportError(msg)
 
-    if numpy_version > (2, 1):
-        msg = (f"Numba needs NumPy 2.1 or less. Got NumPy "
+    if numpy_version > (2, 2):
+        msg = (f"Numba needs NumPy 2.2 or less. Got NumPy "
                f"{numpy_version[0]}.{numpy_version[1]}.")
         raise ImportError(msg)
 
openSUSE Build Service is sponsored by