Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-awkward for openSUSE:Factory 
checked in at 2023-06-21 22:39:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-awkward (Old)
 and      /work/SRC/openSUSE:Factory/.python-awkward.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-awkward"

Wed Jun 21 22:39:17 2023 rev:23 rq:1094142 version:2.2.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-awkward/python-awkward.changes    
2023-06-11 19:58:33.148343665 +0200
+++ /work/SRC/openSUSE:Factory/.python-awkward.new.15902/python-awkward.changes 
2023-06-21 22:40:16.106518960 +0200
@@ -1,0 +2,11 @@
+Tue Jun 20 16:41:07 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 2.2.3:
+  * feat!: deprecate to_NumpyForm's ``dtype` argument
+  * feat!: deprecate the time __unit__ parameter
+  * fix: don't project records during broadcasting; push index down
+  * fix: protect ak.to_parquet against memory explosion when args are swapped.
+  * fix: str of KeyError for <3.11
+  * fix: support axis != -1 for record reduction
+
+-------------------------------------------------------------------

Old:
----
  awkward-2.2.2.tar.gz

New:
----
  awkward-2.2.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-awkward.spec ++++++
--- /var/tmp/diff_new_pack.py76tX/_old  2023-06-21 22:40:16.730522715 +0200
+++ /var/tmp/diff_new_pack.py76tX/_new  2023-06-21 22:40:16.734522739 +0200
@@ -16,10 +16,10 @@
 #
 
 
-%define awkward_cpp_version 16
+%define awkward_cpp_version 17
 %{?sle15_python_module_pythons}
 Name:           python-awkward
-Version:        2.2.2
+Version:        2.2.3
 Release:        0
 Summary:        Manipulate arrays of complex data structures as easily as Numpy
 License:        BSD-3-Clause

++++++ awkward-2.2.2.tar.gz -> awkward-2.2.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/PKG-INFO new/awkward-2.2.3/PKG-INFO
--- old/awkward-2.2.2/PKG-INFO  2023-06-05 20:34:57.000000000 +0200
+++ new/awkward-2.2.3/PKG-INFO  2023-06-15 17:47:29.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: awkward
-Version: 2.2.2
+Version: 2.2.3
 Summary: Manipulate JSON-like data with NumPy-like idioms.
 Project-URL: Bug Tracker, https://github.com/scikit-hep/awkward-1.0/issues
 Project-URL: Chat, https://gitter.im/Scikit-HEP/awkward-array
@@ -36,7 +36,7 @@
 Classifier: Topic :: Software Development
 Classifier: Topic :: Utilities
 Requires-Python: >=3.7
-Requires-Dist: awkward-cpp==16
+Requires-Dist: awkward-cpp==17
 Requires-Dist: importlib-resources; python_version < '3.9'
 Requires-Dist: numpy>=1.17.0
 Requires-Dist: packaging
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/pyproject.toml 
new/awkward-2.2.3/pyproject.toml
--- old/awkward-2.2.2/pyproject.toml    2023-06-05 20:34:57.000000000 +0200
+++ new/awkward-2.2.3/pyproject.toml    2023-06-15 17:47:29.000000000 +0200
@@ -7,7 +7,7 @@
 
 [project]
 name = "awkward"
-version = "2.2.2"
+version = "2.2.3"
 description = "Manipulate JSON-like data with NumPy-like idioms."
 license = { text = "BSD-3-Clause" }
 requires-python = ">=3.7"
@@ -40,7 +40,7 @@
     "Topic :: Utilities",
 ]
 dependencies = [
-    "awkward_cpp==16",
+    "awkward_cpp==17",
     "importlib_resources;python_version < \"3.9\"",
     "numpy>=1.17.0",
     "packaging",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_backends/backend.py 
new/awkward-2.2.3/src/awkward/_backends/backend.py
--- old/awkward-2.2.2/src/awkward/_backends/backend.py  2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/_backends/backend.py  2023-06-15 
17:47:29.000000000 +0200
@@ -59,8 +59,6 @@
 
         message = error.str.decode(errors="surrogateescape")
 
-        assert not error.pass_through
-
         if error.attempt != ak._util.kSliceNone:
             message += f" while attempting to get index {error.attempt}"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_broadcasting.py 
new/awkward-2.2.3/src/awkward/_broadcasting.py
--- old/awkward-2.2.2/src/awkward/_broadcasting.py      2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/_broadcasting.py      2023-06-15 
17:47:29.000000000 +0200
@@ -934,7 +934,13 @@
         )
 
     def broadcast_any_indexed():
-        nextinputs = [x.project() if isinstance(x, IndexedArray) else x for x 
in inputs]
+        # The `apply` function may exit at the level of a `RecordArray`. We 
can avoid projection
+        # of the record array in such cases, in favour of a deferred carry. 
This can be done by
+        # "pushing" the `IndexedArray` _into_ the record (i.e., wrapping each 
`content`).
+        nextinputs = [
+            x._push_inside_record_or_project() if isinstance(x, IndexedArray) 
else x
+            for x in inputs
+        ]
         return apply_step(
             backend,
             nextinputs,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_connect/cling.py 
new/awkward-2.2.3/src/awkward/_connect/cling.py
--- old/awkward-2.2.2/src/awkward/_connect/cling.py     2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/_connect/cling.py     2023-06-15 
17:47:29.000000000 +0200
@@ -446,7 +446,7 @@
 
 def togenerator(form, flatlist_as_rvec):
     if isinstance(form, ak.forms.EmptyForm):
-        return togenerator(form.to_NumpyForm(np.dtype(np.float64)), 
flatlist_as_rvec)
+        return togenerator(form.to_NumpyForm(primitive="float64"), 
flatlist_as_rvec)
 
     elif isinstance(form, ak.forms.NumpyForm):
         if len(form.inner_shape) == 0:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_connect/jax/reducers.py 
new/awkward-2.2.3/src/awkward/_connect/jax/reducers.py
--- old/awkward-2.2.2/src/awkward/_connect/jax/reducers.py      2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/_connect/jax/reducers.py      2023-06-15 
17:47:29.000000000 +0200
@@ -54,6 +54,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         raise RuntimeError("Cannot differentiate through argmin")
@@ -78,6 +80,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         raise RuntimeError("Cannot differentiate through argmax")
@@ -102,6 +106,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         raise RuntimeError("Cannot differentiate through count_zero")
@@ -126,6 +132,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         raise RuntimeError("Cannot differentiate through count_nonzero")
@@ -146,6 +154,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -179,6 +189,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -214,6 +226,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -242,6 +256,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -292,6 +308,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -351,6 +369,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/awkward-2.2.2/src/awkward/_connect/numba/arrayview.py 
new/awkward-2.2.3/src/awkward/_connect/numba/arrayview.py
--- old/awkward-2.2.2/src/awkward/_connect/numba/arrayview.py   2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/_connect/numba/arrayview.py   2023-06-15 
17:47:29.000000000 +0200
@@ -106,7 +106,7 @@
 
 def to_numbatype(form):
     if isinstance(form, ak.forms.EmptyForm):
-        return to_numbatype(form.to_NumpyForm(np.dtype(np.float64)))
+        return to_numbatype(form.to_NumpyForm(primitive="float64"))
 
     elif isinstance(form, ak.forms.NumpyForm):
         if len(form.inner_shape) == 0:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_errors.py 
new/awkward-2.2.3/src/awkward/_errors.py
--- old/awkward-2.2.2/src/awkward/_errors.py    2023-06-05 20:34:57.000000000 
+0200
+++ new/awkward-2.2.3/src/awkward/_errors.py    2023-06-15 17:47:29.000000000 
+0200
@@ -1,6 +1,7 @@
 # BSD 3-Clause License; see 
https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
 from __future__ import annotations
 
+import builtins
 import sys
 import threading
 import warnings
@@ -31,6 +32,11 @@
         return self.func(*self.args, **self.kwargs)
 
 
+class KeyError(builtins.KeyError):
+    def __str__(self):
+        return super(Exception, self).__str__()
+
+
 class ErrorContext:
     # Any other threads should get a completely independent _slate.
     _slate = threading.local()
@@ -87,6 +93,9 @@
                     + "\n\nSee if this has been reported at 
https://github.com/scikit-hep/awkward/issues";
                 )
                 new_exception.__cause__ = exception
+            elif issubclass(cls, builtins.KeyError):
+                new_exception = KeyError(self.format_exception(exception))
+                new_exception.__cause__ = exception
             else:
                 new_exception = cls(self.format_exception(exception))
                 new_exception.__cause__ = exception
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_kernels.py 
new/awkward-2.2.3/src/awkward/_kernels.py
--- old/awkward-2.2.2/src/awkward/_kernels.py   2023-06-05 20:34:57.000000000 
+0200
+++ new/awkward-2.2.3/src/awkward/_kernels.py   2023-06-15 17:47:29.000000000 
+0200
@@ -23,7 +23,6 @@
 class KernelError(Protocol):
     filename: str | None  # pylint: disable=E0602
     str: str | None
-    pass_through: bool
     attempt: int
     id: int
 
@@ -174,7 +173,6 @@
     def __init__(self):
         self.str = None
         self.filename = None
-        self.pass_through = False
         self.attempt = ak._util.kSliceNone
         self.id = ak._util.kSliceNone
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_reducers.py 
new/awkward-2.2.3/src/awkward/_reducers.py
--- old/awkward-2.2.2/src/awkward/_reducers.py  2023-06-05 20:34:57.000000000 
+0200
+++ new/awkward-2.2.3/src/awkward/_reducers.py  2023-06-15 17:47:29.000000000 
+0200
@@ -39,6 +39,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         ...
@@ -74,6 +76,53 @@
             return given_dtype
 
 
+def apply_positional_corrections(
+    reduced: ak.contents.NumpyArray,
+    parents: ak.index.Index,
+    starts: ak.index.Index,
+    shifts: ak.index.Index | None,
+):
+    if shifts is None:
+        assert (
+            parents.nplike is reduced.backend.index_nplike
+            and starts.nplike is reduced.backend.index_nplike
+        )
+        reduced.backend.maybe_kernel_error(
+            reduced.backend[
+                "awkward_NumpyArray_reduce_adjust_starts_64",
+                reduced.dtype.type,
+                parents.dtype.type,
+                starts.dtype.type,
+            ](
+                reduced.data,
+                reduced.length,
+                parents.data,
+                starts.data,
+            )
+        )
+    else:
+        assert (
+            parents.nplike is reduced.backend.index_nplike
+            and starts.nplike is reduced.backend.index_nplike
+            and shifts.nplike is reduced.backend.index_nplike
+        )
+        reduced.backend.maybe_kernel_error(
+            reduced._backend[
+                "awkward_NumpyArray_reduce_adjust_starts_shifts_64",
+                reduced.dtype.type,
+                parents.dtype.type,
+                starts.dtype.type,
+                shifts.dtype.type,
+            ](
+                reduced.data,
+                reduced.length,
+                parents.data,
+                starts.data,
+                shifts.data,
+            )
+        )
+
+
 class ArgMin(KernelReducer):
     name: Final = "argmin"
     preferred_dtype: Final = np.int64
@@ -83,6 +132,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -121,7 +172,9 @@
                     outlength,
                 )
             )
-        return ak.contents.NumpyArray(result, backend=array.backend)
+        result_array = ak.contents.NumpyArray(result, backend=array.backend)
+        apply_positional_corrections(result_array, parents, starts, shifts)
+        return result_array
 
 
 class ArgMax(KernelReducer):
@@ -133,6 +186,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -171,7 +226,9 @@
                     outlength,
                 )
             )
-        return ak.contents.NumpyArray(result, backend=array.backend)
+        result_array = ak.contents.NumpyArray(result, backend=array.backend)
+        apply_positional_corrections(result_array, parents, starts, shifts)
+        return result_array
 
 
 class Count(KernelReducer):
@@ -183,6 +240,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -210,6 +269,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -261,6 +322,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -363,6 +426,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -452,6 +517,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -503,6 +570,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -584,6 +653,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
@@ -690,6 +761,8 @@
         self,
         array: ak.contents.NumpyArray,
         parents: ak.index.Index,
+        starts: ak.index.Index,
+        shifts: ak.index.Index | None,
         outlength: ShapeItem,
     ) -> ak.contents.NumpyArray:
         assert isinstance(array, ak.contents.NumpyArray)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/_regularize.py 
new/awkward-2.2.3/src/awkward/_regularize.py
--- old/awkward-2.2.2/src/awkward/_regularize.py        2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/_regularize.py        2023-06-15 
17:47:29.000000000 +0200
@@ -50,30 +50,6 @@
     return not isinstance(obj, (str, bytes)) and isinstance(obj, Sequence)
 
 
-def regularize_path(path):
-    """
-    Converts pathlib Paths into plain string paths (for all versions of 
Python).
-    """
-    is_path = False
-
-    if isinstance(path, getattr(os, "PathLike", ())):
-        is_path = True
-        path = os.fspath(path)
-
-    elif hasattr(path, "__fspath__"):
-        is_path = True
-        path = path.__fspath__()
-
-    elif path.__class__.__module__ == "pathlib":
-        import pathlib
-
-        if isinstance(path, pathlib.Path):
-            is_path = True
-            path = str(path)
-
-    return is_path, path
-
-
 def regularize_axis(axis: SupportsInt | None) -> AxisMaybeNone:
     if axis is None:
         return None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/contents/indexedarray.py 
new/awkward-2.2.3/src/awkward/contents/indexedarray.py
--- old/awkward-2.2.2/src/awkward/contents/indexedarray.py      2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/contents/indexedarray.py      2023-06-15 
17:47:29.000000000 +0200
@@ -1136,3 +1136,18 @@
         return self.index.is_equal_to(
             other.index, index_dtype, numpyarray
         ) and self.content.is_equal_to(other.content, index_dtype, numpyarray)
+
+    def _push_inside_record_or_project(self) -> Self | ak.contents.RecordArray:
+        if self.content.is_record:
+            return ak.contents.RecordArray(
+                contents=[
+                    ak.contents.IndexedArray.simplified(self._index, c)
+                    for c in self.content.contents
+                ],
+                fields=self.content._fields,
+                length=self.length,
+                backend=self._backend,
+                parameters=parameters_union(self.content._parameters, 
self._parameters),
+            )
+        else:
+            return self.project()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/awkward-2.2.2/src/awkward/contents/listoffsetarray.py 
new/awkward-2.2.3/src/awkward/contents/listoffsetarray.py
--- old/awkward-2.2.2/src/awkward/contents/listoffsetarray.py   2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/contents/listoffsetarray.py   2023-06-15 
17:47:29.000000000 +0200
@@ -1577,6 +1577,8 @@
             )
             nextparents = Index64.empty(nextlen, index_nplike)
 
+            # n.b. awkward_ListOffsetArray_reduce_local_nextparents_64 always 
returns parents that are
+            # monotonically increasing (because it is local)
             assert (
                 nextparents.nplike is index_nplike
                 and self._offsets.nplike is index_nplike
@@ -1704,6 +1706,7 @@
                 maxcount,
             )
         )
+
         maxnextparents = index_nplike.index_as_shape_item(_maxnextparents[0])
         nextstarts = Index64.empty(maxnextparents + 1, index_nplike)
         assert nextstarts.nplike is index_nplike and nextparents.nplike is 
index_nplike
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/contents/numpyarray.py 
new/awkward-2.2.3/src/awkward/contents/numpyarray.py
--- old/awkward-2.2.2/src/awkward/contents/numpyarray.py        2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/contents/numpyarray.py        2023-06-15 
17:47:29.000000000 +0200
@@ -1128,48 +1128,7 @@
         assert self.is_contiguous
         assert self._data.ndim == 1
 
-        out = reducer.apply(self, parents, outlength)
-
-        if reducer.needs_position:
-            if shifts is None:
-                assert (
-                    parents.nplike is self._backend.index_nplike
-                    and starts.nplike is self._backend.index_nplike
-                )
-                self._backend.maybe_kernel_error(
-                    self._backend[
-                        "awkward_NumpyArray_reduce_adjust_starts_64",
-                        out.data.dtype.type,
-                        parents.dtype.type,
-                        starts.dtype.type,
-                    ](
-                        out.data,
-                        outlength,
-                        parents.data,
-                        starts.data,
-                    )
-                )
-            else:
-                assert (
-                    parents.nplike is self._backend.index_nplike
-                    and starts.nplike is self._backend.index_nplike
-                    and shifts.nplike is self._backend.index_nplike
-                )
-                self._backend.maybe_kernel_error(
-                    self._backend[
-                        "awkward_NumpyArray_reduce_adjust_starts_shifts_64",
-                        out.data.dtype.type,
-                        parents.dtype.type,
-                        starts.dtype.type,
-                        shifts.dtype.type,
-                    ](
-                        out.data,
-                        outlength,
-                        parents.data,
-                        starts.data,
-                        shifts.data,
-                    )
-                )
+        out = reducer.apply(self, parents, starts, shifts, outlength)
 
         if mask:
             outmask = ak.index.Index8.empty(outlength, 
self._backend.index_nplike)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/contents/recordarray.py 
new/awkward-2.2.3/src/awkward/contents/recordarray.py
--- old/awkward-2.2.2/src/awkward/contents/recordarray.py       2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/contents/recordarray.py       2023-06-15 
17:47:29.000000000 +0200
@@ -906,35 +906,46 @@
                 )
             )
         else:
+            # Positional reducers ultimately need to do more work when 
rebuilding the result
+            # so asking for a mask doesn't help us!
+            reducer_should_mask = mask and not reducer.needs_position
+
             # Convert parents into offsets to build a list for axis=1 reduction
             offsets = ak.index.Index64.empty(outlength + 1, 
self._backend.index_nplike)
             assert (
                 offsets.nplike is self._backend.index_nplike
                 and parents.nplike is self._backend.index_nplike
             )
+            # `parents` are possibly non monotonic increasing, so we must 
re-order the result
+            # This happens naturally for the `NumpyArray` reducers.
+            carry = ak.index.Index64.empty(outlength, 
self._backend.index_nplike)
+
+            # Note: if we knew that `negaxis == depth` exclusively for this 
layout, we could use
+            # the simpler `ListOffsetArray_reduce_local_outoffsets_64`. 
However, if our parent was reduced,
+            # we would still see `negaxis == depth`, so this kernel has to be 
used instead.
+            assert carry.nplike is self._backend.index_nplike
             self._backend.maybe_kernel_error(
                 self._backend[
-                    "awkward_ListOffsetArray_reduce_local_outoffsets_64",
+                    "awkward_RecordArray_reduce_nonlocal_outoffsets_64",
                     offsets.dtype.type,
+                    carry.dtype.type,
                     parents.dtype.type,
                 ](
                     offsets.data,
+                    carry.data,
                     parents.data,
                     parents.length,
                     outlength,
                 )
             )
-            layout_to_reduce = ak.contents.ListOffsetArray(offsets, self)
-
-            # Positional reducers ultimately need to do more work when 
rebuilding the result
-            # so asking for a mask doesn't help us!
-            reducer_should_mask = mask and not reducer.needs_position
             out = _apply_record_reducer(
                 reducer_recordclass,
-                layout_to_reduce,
+                ak.contents.ListOffsetArray(offsets, self),
                 reducer_should_mask,
                 behavior,
             )
+            out = out._carry(carry, allow_lazy=True)
+
             if out.is_option and not reducer_should_mask:
                 reason = (
                     "reducer is positional"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/forms/emptyform.py 
new/awkward-2.2.3/src/awkward/forms/emptyform.py
--- old/awkward-2.2.2/src/awkward/forms/emptyform.py    2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/forms/emptyform.py    2023-06-15 
17:47:29.000000000 +0200
@@ -1,6 +1,8 @@
 # BSD 3-Clause License; see 
https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
 from __future__ import annotations
 
+from inspect import signature
+
 import awkward as ak
 from awkward._errors import deprecate
 from awkward._nplikes.shape import ShapeItem
@@ -53,8 +55,34 @@
     def __eq__(self, other) -> bool:
         return isinstance(other, EmptyForm) and self._form_key == 
other._form_key
 
-    def to_NumpyForm(self, dtype):
-        return ak.forms.numpyform.from_dtype(dtype, 
parameters=self._parameters)
+    def to_NumpyForm(self, *args, **kwargs):
+        def legacy_impl(dtype):
+            deprecate(
+                f"the `dtype` parameter in {type(self).__name__}.to_NumpyForm 
is deprecated, "
+                f"in favour of a new `primitive` argument. Pass `primitive` by 
keyword to opt-in to the new behavior.",
+                version="2.4.0",
+            )
+            return ak.forms.numpyform.from_dtype(dtype, 
parameters=self._parameters)
+
+        def new_impl(*, primitive):
+            return ak.forms.numpyform.NumpyForm(primitive, 
parameters=self._parameters)
+
+        dispatch_table = [
+            new_impl,
+            legacy_impl,
+        ]
+        for func in dispatch_table:
+            sig = signature(func)
+            try:
+                bound_arguments = sig.bind(*args, **kwargs)
+            except TypeError:
+                continue
+            else:
+                return func(*bound_arguments.args, **bound_arguments.kwargs)
+        raise AssertionError(
+            f"{type(self).__name__}.to_NumpyForm accepts either the new 
`primitive` argument as a keyword-only "
+            f"argument, or the legacy `dtype` argument as positional or 
keyword"
+        )
 
     def purelist_parameter(self, key):
         if self._parameters is None or key not in self._parameters:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/forms/numpyform.py 
new/awkward-2.2.3/src/awkward/forms/numpyform.py
--- old/awkward-2.2.2/src/awkward/forms/numpyform.py    2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/forms/numpyform.py    2023-06-15 
17:47:29.000000000 +0200
@@ -2,6 +2,7 @@
 from collections.abc import Iterable
 
 import awkward as ak
+from awkward._errors import deprecate
 from awkward._nplikes.numpylike import NumpyMetadata
 from awkward._parameters import type_parameters_equal
 from awkward._typing import final
@@ -11,14 +12,26 @@
 np = NumpyMetadata.instance()
 
 
-def from_dtype(dtype, parameters=None):
+def from_dtype(dtype, parameters=None, *, time_units_as_parameter: bool = 
UNSET):
     if dtype.subdtype is None:
         inner_shape = ()
     else:
         inner_shape = dtype.shape
         dtype = dtype.subdtype[0]
 
-    if issubclass(dtype.type, (np.datetime64, np.timedelta64)):
+    if time_units_as_parameter is UNSET:
+        time_units_as_parameter = True
+
+    if time_units_as_parameter:
+        deprecate(
+            "from_dtype conversion of temporal units to generic `datetime64` 
and `timedelta64` types is deprecated, "
+            "pass `time_units_as_parameter=False` to disable this warning.",
+            version="2.4.0",
+        )
+
+    if time_units_as_parameter and issubclass(
+        dtype.type, (np.datetime64, np.timedelta64)
+    ):
         unit, step = np.datetime_data(dtype)
         if unit != "generic":
             unitstr = ("" if step == 1 else str(step)) + unit
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/awkward-2.2.2/src/awkward/operations/ak_from_avro_file.py 
new/awkward-2.2.3/src/awkward/operations/ak_from_avro_file.py
--- old/awkward-2.2.2/src/awkward/operations/ak_from_avro_file.py       
2023-06-05 20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/operations/ak_from_avro_file.py       
2023-06-15 17:47:29.000000000 +0200
@@ -1,8 +1,7 @@
 # BSD 3-Clause License; see 
https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
 __all__ = ("from_avro_file",)
 
-# from awkward._typing import Type
-import pathlib
+from os import PathLike, fsdecode
 
 import awkward as ak
 from awkward._nplikes.numpylike import NumpyMetadata
@@ -15,7 +14,7 @@
 ):
     """
     Args:
-        file (string or file-like object): Avro file to be read as Awkward 
Array.
+        file (path-like or file-like object): Avro file to be read as Awkward 
Array.
         limit_entries (int): The number of rows of the Avro file to be read 
into the Awkward Array.
         debug_forth (bool): If True, prints the generated Forth code for 
debugging.
         highlevel (bool): If True, return an #ak.Array; otherwise, return
@@ -40,8 +39,8 @@
             "debug_forth": debug_forth,
         },
     ):
-        if isinstance(file, pathlib.Path):
-            file = str(file)
+        if isinstance(file, (str, bytes, PathLike)):
+            file = fsdecode(file)
 
         if isinstance(file, str):
             with open(file, "rb") as opened_file:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/operations/ak_from_json.py 
new/awkward-2.2.3/src/awkward/operations/ak_from_json.py
--- old/awkward-2.2.2/src/awkward/operations/ak_from_json.py    2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/operations/ak_from_json.py    2023-06-15 
17:47:29.000000000 +0200
@@ -399,7 +399,7 @@
 
 
 def _get_reader(source):
-    if not isinstance(source, pathlib.Path) and isinstance(source, str):
+    if isinstance(source, str):
         source = source.encode("utf8", errors="surrogateescape")
 
     if isinstance(source, bytes):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/src/awkward/operations/ak_to_json.py 
new/awkward-2.2.3/src/awkward/operations/ak_to_json.py
--- old/awkward-2.2.2/src/awkward/operations/ak_to_json.py      2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/operations/ak_to_json.py      2023-06-15 
17:47:29.000000000 +0200
@@ -1,8 +1,8 @@
 # BSD 3-Clause License; see 
https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
 __all__ = ("to_json",)
 import json
-import pathlib
 from numbers import Number
+from os import PathLike, fsdecode
 from urllib.parse import urlparse
 
 from awkward_cpp.lib import _ext
@@ -33,7 +33,7 @@
     """
     Args:
         array: Array-like data (anything #ak.to_layout recognizes).
-        file (None, str/pathlib.Path, or file-like object): If None, this 
function returns
+        file (None, path-like, or file-like object): If None, this function 
returns
             JSON-encoded bytes. Otherwise, this function has no return value.
             If a string/pathlib.Path, this function opens a file with that 
name, writes JSON
             data, and closes the file. If that path has a URI protocol (like
@@ -205,8 +205,8 @@
     )
 
     if file is not None:
-        if isinstance(file, (str, pathlib.Path)):
-            parsed_url = urlparse(file)
+        if isinstance(file, (str, bytes, PathLike)):
+            parsed_url = urlparse(fsdecode(file))
             if parsed_url.scheme == "" or parsed_url.netloc == "":
 
                 def opener():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/awkward-2.2.2/src/awkward/operations/ak_to_parquet.py 
new/awkward-2.2.3/src/awkward/operations/ak_to_parquet.py
--- old/awkward-2.2.2/src/awkward/operations/ak_to_parquet.py   2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/src/awkward/operations/ak_to_parquet.py   2023-06-15 
17:47:29.000000000 +0200
@@ -2,6 +2,7 @@
 __all__ = ("to_parquet",)
 
 from collections.abc import Mapping, Sequence
+from os import fsdecode
 
 import awkward as ak
 from awkward._nplikes.numpylike import NumpyMetadata
@@ -39,8 +40,8 @@
     """
     Args:
         array: Array-like data (anything #ak.to_layout recognizes).
-        destination (str): Name of the output file, file path, or remote URL 
passed to
-            
[fsspec.core.url_to_fs](https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.core.url_to_fs)
+        destination (path-like): Name of the output file, file path, or
+            remote URL passed to 
[fsspec.core.url_to_fs](https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.core.url_to_fs)
             for remote writing.
         list_to32 (bool): If True, convert Awkward lists into 32-bit Arrow 
lists
             if they're small enough, even if it means an extra conversion. 
Otherwise,
@@ -291,6 +292,13 @@
     if parquet_extra_options is None:
         parquet_extra_options = {}
 
+    try:
+        destination = fsdecode(destination)
+    except TypeError:
+        raise TypeError(
+            f"'destination' argument of 'ak.to_parquet' must be a path-like, 
not {type(destination).__name__} ('array' argument is first; 'destination' 
second)"
+        ) from None
+
     fs, destination = fsspec.core.url_to_fs(destination, **(storage_options or 
{}))
     metalist = []
     with pyarrow_parquet.ParquetWriter(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/tests/test_0914_types_and_forms.py 
new/awkward-2.2.3/tests/test_0914_types_and_forms.py
--- old/awkward-2.2.2/tests/test_0914_types_and_forms.py        2023-06-05 
20:34:57.000000000 +0200
+++ new/awkward-2.2.3/tests/test_0914_types_and_forms.py        2023-06-15 
17:47:29.000000000 +0200
@@ -1554,132 +1554,197 @@
         "parameters": {"__unit__": "s", "x": 123},
     }
 
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("bool")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "bool",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("int8")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "int8",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("uint8")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "uint8",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("int16")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "int16",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("uint16")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "uint16",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("int32")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "int32",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("uint32")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "uint32",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("int64")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "int64",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("uint64")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "uint64",
-    }
-    if hasattr(np, "float16"):
-        assert ak.forms.numpyform.from_dtype(np.dtype("float16")).to_dict(
+    with pytest.warns(DeprecationWarning):
+        assert ak.forms.numpyform.from_dtype(np.dtype("bool")).to_dict(
             verbose=False
         ) == {
             "class": "NumpyArray",
-            "primitive": "float16",
+            "primitive": "bool",
         }
-    assert ak.forms.numpyform.from_dtype(np.dtype("float32")).to_dict(
-        verbose=False
-    ) == {
-        "class": "NumpyArray",
-        "primitive": "float32",
-    }
-    assert ak.forms.numpyform.from_dtype(np.dtype("float64")).to_dict(
-        verbose=False
-    ) == {
-        "class": "NumpyArray",
-        "primitive": "float64",
-    }
-    if hasattr(np, "float128"):
-        assert ak.forms.numpyform.from_dtype(np.dtype("float128")).to_dict(
+        assert ak.forms.numpyform.from_dtype(np.dtype("int8")).to_dict(
             verbose=False
         ) == {
             "class": "NumpyArray",
-            "primitive": "float128",
+            "primitive": "int8",
         }
-    assert ak.forms.numpyform.from_dtype(np.dtype("complex64")).to_dict(
-        verbose=False
-    ) == {
-        "class": "NumpyArray",
-        "primitive": "complex64",
-    }
-    assert ak.forms.numpyform.from_dtype(np.dtype("complex128")).to_dict(
-        verbose=False
-    ) == {
-        "class": "NumpyArray",
-        "primitive": "complex128",
-    }
-    if hasattr(np, "complex256"):
-        assert ak.forms.numpyform.from_dtype(np.dtype("complex256")).to_dict(
+        assert ak.forms.numpyform.from_dtype(np.dtype("uint8")).to_dict(
             verbose=False
         ) == {
             "class": "NumpyArray",
-            "primitive": "complex256",
+            "primitive": "uint8",
         }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("M8")).to_dict(verbose=False) == {
-        "class": "NumpyArray",
-        "primitive": "datetime64",
-    }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("M8[s]")).to_dict(verbose=False) == {
+        assert ak.forms.numpyform.from_dtype(np.dtype("int16")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "int16",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("uint16")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "uint16",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("int32")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "int32",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("uint32")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "uint32",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("int64")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "int64",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("uint64")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "uint64",
+        }
+        if hasattr(np, "float16"):
+            assert ak.forms.numpyform.from_dtype(np.dtype("float16")).to_dict(
+                verbose=False
+            ) == {
+                "class": "NumpyArray",
+                "primitive": "float16",
+            }
+        assert ak.forms.numpyform.from_dtype(np.dtype("float32")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "float32",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("float64")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "float64",
+        }
+        if hasattr(np, "float128"):
+            assert ak.forms.numpyform.from_dtype(np.dtype("float128")).to_dict(
+                verbose=False
+            ) == {
+                "class": "NumpyArray",
+                "primitive": "float128",
+            }
+        assert ak.forms.numpyform.from_dtype(np.dtype("complex64")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "complex64",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("complex128")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "complex128",
+        }
+        if hasattr(np, "complex256"):
+            assert 
ak.forms.numpyform.from_dtype(np.dtype("complex256")).to_dict(
+                verbose=False
+            ) == {
+                "class": "NumpyArray",
+                "primitive": "complex256",
+            }
+        assert 
ak.forms.numpyform.from_dtype(np.dtype("M8")).to_dict(verbose=False) == {
+            "class": "NumpyArray",
+            "primitive": "datetime64",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("M8[s]")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "datetime64",
+            "parameters": {"__unit__": "s"},
+        }
+        assert ak.forms.numpyform.from_dtype(
+            np.dtype("M8[s]"), parameters={"x": 123}
+        ).to_dict(verbose=False) == {
+            "class": "NumpyArray",
+            "primitive": "datetime64",
+            "parameters": {"__unit__": "s", "x": 123},
+        }
+        assert 
ak.forms.numpyform.from_dtype(np.dtype("m8")).to_dict(verbose=False) == {
+            "class": "NumpyArray",
+            "primitive": "timedelta64",
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype("m8[s]")).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "timedelta64",
+            "parameters": {"__unit__": "s"},
+        }
+        assert ak.forms.numpyform.from_dtype(
+            np.dtype("m8[s]"), parameters={"x": 123}
+        ).to_dict(verbose=False) == {
+            "class": "NumpyArray",
+            "primitive": "timedelta64",
+            "parameters": {"__unit__": "s", "x": 123},
+        }
+        assert ak.forms.numpyform.from_dtype(np.dtype(("bool", (1, 2, 
3)))).to_dict(
+            verbose=False
+        ) == {
+            "class": "NumpyArray",
+            "primitive": "bool",
+            "inner_shape": [1, 2, 3],
+        }
+
+    assert ak.forms.numpyform.from_dtype(
+        np.dtype("M8"), time_units_as_parameter=False
+    ).to_dict(verbose=False) == {
         "class": "NumpyArray",
         "primitive": "datetime64",
-        "parameters": {"__unit__": "s"},
     }
     assert ak.forms.numpyform.from_dtype(
-        np.dtype("M8[s]"), parameters={"x": 123}
+        np.dtype("M8[s]"), time_units_as_parameter=False
     ).to_dict(verbose=False) == {
         "class": "NumpyArray",
-        "primitive": "datetime64",
-        "parameters": {"__unit__": "s", "x": 123},
+        "primitive": "datetime64[s]",
     }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("m8")).to_dict(verbose=False) == {
+    assert ak.forms.numpyform.from_dtype(
+        np.dtype("M8[s]"), time_units_as_parameter=False, parameters={"x": 123}
+    ).to_dict(verbose=False) == {
         "class": "NumpyArray",
-        "primitive": "timedelta64",
+        "primitive": "datetime64[s]",
+        "parameters": {"x": 123},
     }
-    assert 
ak.forms.numpyform.from_dtype(np.dtype("m8[s]")).to_dict(verbose=False) == {
+    assert ak.forms.numpyform.from_dtype(
+        np.dtype("m8"), time_units_as_parameter=False
+    ).to_dict(verbose=False) == {
         "class": "NumpyArray",
         "primitive": "timedelta64",
-        "parameters": {"__unit__": "s"},
     }
     assert ak.forms.numpyform.from_dtype(
-        np.dtype("m8[s]"), parameters={"x": 123}
+        np.dtype("m8[s]"), time_units_as_parameter=False
     ).to_dict(verbose=False) == {
         "class": "NumpyArray",
-        "primitive": "timedelta64",
-        "parameters": {"__unit__": "s", "x": 123},
+        "primitive": "timedelta64[s]",
     }
-    assert ak.forms.numpyform.from_dtype(np.dtype(("bool", (1, 2, 
3)))).to_dict(
-        verbose=False
-    ) == {
+    assert ak.forms.numpyform.from_dtype(
+        np.dtype("m8[s]"), parameters={"x": 123}, time_units_as_parameter=False
+    ).to_dict(verbose=False) == {
         "class": "NumpyArray",
-        "primitive": "bool",
-        "inner_shape": [1, 2, 3],
+        "primitive": "timedelta64[s]",
+        "parameters": {"x": 123},
     }
     with pytest.raises(TypeError):
-        ak.forms.from_dtype(np.dtype("O")).to_dict(verbose=False)
-    with pytest.raises(TypeError):
-        ak.forms.from_dtype(np.dtype([("one", np.int64), ("two", 
np.float64)])).to_dict(
+        ak.forms.from_dtype(np.dtype("O"), 
time_units_as_parameter=False).to_dict(
             verbose=False
         )
+    with pytest.raises(TypeError):
+        ak.forms.from_dtype(
+            np.dtype([("one", np.int64), ("two", np.float64)]),
+            time_units_as_parameter=False,
+        ).to_dict(verbose=False)
     assert ak.forms.from_dict("bool").to_dict(verbose=False) == {
         "class": "NumpyArray",
         "primitive": "bool",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/awkward-2.2.2/tests/test_2503_deprecate_to_numpyform.py 
new/awkward-2.2.3/tests/test_2503_deprecate_to_numpyform.py
--- old/awkward-2.2.2/tests/test_2503_deprecate_to_numpyform.py 1970-01-01 
01:00:00.000000000 +0100
+++ new/awkward-2.2.3/tests/test_2503_deprecate_to_numpyform.py 2023-06-15 
17:47:29.000000000 +0200
@@ -0,0 +1,22 @@
+# BSD 3-Clause License; see 
https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import numpy as np
+import pytest
+
+import awkward as ak
+
+
+def test_dtype_deprecated():
+    form = ak.forms.EmptyForm()
+    with pytest.warns(
+        DeprecationWarning,
+        match=r"the `dtype` parameter in EmptyForm\.to_NumpyForm is 
deprecated",
+    ):
+        next_form = form.to_NumpyForm(dtype=np.dtype(np.int64))
+    assert next_form.primitive == "int64"
+
+
+def test_primitive():
+    form = ak.forms.EmptyForm()
+    next_form = form.to_NumpyForm(primitive="int64")
+    assert next_form.primitive == "int64"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/awkward-2.2.2/tests/test_2512_record_array_carry.py 
new/awkward-2.2.3/tests/test_2512_record_array_carry.py
--- old/awkward-2.2.2/tests/test_2512_record_array_carry.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/awkward-2.2.3/tests/test_2512_record_array_carry.py     2023-06-15 
17:47:29.000000000 +0200
@@ -0,0 +1,160 @@
+# BSD 3-Clause License; see 
https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import numpy as np
+
+import awkward as ak
+
+
+def _reduce_max_masked(array, mask):
+    assert mask
+    j = ak.from_regular(
+        ak.argmax(array["1"], axis=1, keepdims=True, mask_identity=True)
+    )
+    return ak.flatten(array[j], axis=1)
+
+
+behavior = {}
+behavior[ak.max, "pair"] = _reduce_max_masked
+
+
+def test_axis_0():
+    content = ak.contents.ListArray(
+        ak.index.Index64([0, 2]),
+        ak.index.Index64([2, 4]),
+        ak.contents.ListOffsetArray(
+            ak.index.Index64([0, 3, 6, 9, 11]),
+            ak.contents.RecordArray(
+                [
+                    ak.contents.NumpyArray(np.arange(11, dtype=np.int64)),
+                    ak.contents.NumpyArray(
+                        np.array(
+                            [
+                                0.0,
+                                2.0,
+                                4.0,
+                                6.0,
+                                8.0,
+                                10.0,
+                                1.0,
+                                14.0,
+                                16.0,
+                                18.0,
+                                20.0,
+                            ],
+                            dtype=np.float64,
+                        )
+                    ),
+                ],
+                fields=None,
+                parameters={"__record__": "pair"},
+            ),
+        ),
+    )
+
+    result = ak.max(
+        content,
+        axis=0,
+        keepdims=True,
+        mask_identity=True,
+        behavior=behavior,
+        highlevel=False,
+    )
+
+    expected_result = ak.contents.ListArray(
+        ak.index.Index64([0]),
+        ak.index.Index64([2]),
+        ak.contents.ListArray(
+            ak.index.Index64([0, 3]),
+            ak.index.Index64([3, 6]),
+            ak.contents.IndexedOptionArray(
+                ak.index.Index64([1, 5, 9, 3, 7, 10]),
+                ak.contents.RecordArray(
+                    [
+                        ak.contents.NumpyArray(
+                            np.array([0, 6, 3, 9, 1, 7, 4, 10, 2, 8, 5], 
dtype=np.int64)
+                        ),
+                        ak.contents.NumpyArray(
+                            np.array(
+                                [0, 1, 6, 18, 2, 14, 8, 20, 4, 16, 10],
+                                dtype=np.float64,
+                            )
+                        ),
+                    ],
+                    fields=None,
+                    parameters={"__record__": "pair"},
+                ),
+            ),
+        ),
+    )
+    assert result.is_equal_to(expected_result)
+
+
+def test_axis_1():
+    content = ak.contents.ListArray(
+        ak.index.Index64([0, 2]),
+        ak.index.Index64([2, 4]),
+        ak.contents.ListOffsetArray(
+            ak.index.Index64([0, 3, 6, 9, 11]),
+            ak.contents.RecordArray(
+                [
+                    ak.contents.NumpyArray(np.arange(11, dtype=np.int64)),
+                    ak.contents.NumpyArray(
+                        np.array(
+                            [
+                                0.0,
+                                2.0,
+                                4.0,
+                                6.0,
+                                8.0,
+                                10.0,
+                                1.0,
+                                14.0,
+                                16.0,
+                                18.0,
+                                20.0,
+                            ],
+                            dtype=np.float64,
+                        )
+                    ),
+                ],
+                fields=None,
+                parameters={"__record__": "pair"},
+            ),
+        ),
+    )
+
+    result = ak.max(
+        content,
+        axis=1,
+        keepdims=True,
+        mask_identity=True,
+        behavior=behavior,
+        highlevel=False,
+    )
+
+    expected_result = ak.contents.RegularArray(
+        ak.contents.ListArray(
+            ak.index.Index64([0, 3]),
+            ak.index.Index64([3, 6]),
+            ak.contents.IndexedOptionArray(
+                ak.index.Index64([1, 5, 9, 3, 7, 10]),
+                ak.contents.RecordArray(
+                    [
+                        ak.contents.NumpyArray(
+                            np.array([0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8], 
dtype=np.int64)
+                        ),
+                        ak.contents.NumpyArray(
+                            np.array(
+                                [0, 6, 1, 18, 2, 8, 14, 20, 4, 10, 16],
+                                dtype=np.float64,
+                            )
+                        ),
+                    ],
+                    fields=None,
+                    parameters={"__record__": "pair"},
+                ),
+            ),
+        ),
+        size=1,
+    )
+    assert result.is_equal_to(expected_result)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/awkward-2.2.2/tests/test_2518_datetime_units_as_parameter.py 
new/awkward-2.2.3/tests/test_2518_datetime_units_as_parameter.py
--- old/awkward-2.2.2/tests/test_2518_datetime_units_as_parameter.py    
1970-01-01 01:00:00.000000000 +0100
+++ new/awkward-2.2.3/tests/test_2518_datetime_units_as_parameter.py    
2023-06-15 17:47:29.000000000 +0200
@@ -0,0 +1,32 @@
+# BSD 3-Clause License; see 
https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import numpy as np
+import pytest
+
+import awkward as ak
+
+
+def test_no_parameter():
+    dtype = np.dtype("datetime64[15us]")
+    with pytest.warns(
+        DeprecationWarning, match=r"from_dtype conversion of temporal units"
+    ):
+        form = ak.forms.numpyform.from_dtype(dtype)
+    assert form.primitive == "datetime64"
+    assert form.parameters == {"__unit__": "15us"}
+
+
+def test_true_parameter():
+    dtype = np.dtype("datetime64[15us]")
+    with pytest.warns(
+        DeprecationWarning, match=r"from_dtype conversion of temporal units"
+    ):
+        form = ak.forms.numpyform.from_dtype(dtype, 
time_units_as_parameter=True)
+    assert form.primitive == "datetime64"
+    assert form.parameters == {"__unit__": "15us"}
+
+
+def test_false_parameter():
+    dtype = np.dtype("datetime64[15us]")
+    form = ak.forms.numpyform.from_dtype(dtype, time_units_as_parameter=False)
+    assert form.primitive == "datetime64[15us]"

Reply via email to