internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: scikit-hep/awkward

Issue:
Requests from review of #1776 (merging docs into main).
### Which documentation?

Tutorials site

### What needs to be documented?

This is a follow-up of https://github.com/scikit-hep/awkward/pull/1776#pullrequestreview-1144743439, which is an approval of merging the `docs` branch into `main` as-is, but with some to-do items to be picked up later. This issue copies those into a bulleted list.

  - [ ] Vertical margin around the badges/buttons on the front page so that they are still distinct when the window is narrow or someone is looking at it on their phone.
  - [ ] Helpful messages on the "Try it in your browser" page (see below).
  - [ ] Better sizing of Retrolite on small screens
  - [x] All of the sections containing `ak.*` functions (everything defined in `src/awkward/operations/`) should be contiguous, before the section on "Low-level layouts". This is so that someone searching for an operation they can't quite remember the name of is less likely to miss it. The "Converting between backends", "Indexing and grouping", and "Copying and packing arrays" belong to this category.
  - [x] Remove the "Additional documentation" section (which is unnecessary and out of date, including the diagram).
  - [x] The kernel specification should be generated and included.
  - [x] The AwkwardForth sub-sections may be suppressed on `reference/index.html` and the kernel specification sub-sections _have to_ be suppressed. They would flood that page.

That's it!


Discussion:
Yes, I'd like to improve the buttons. Ideally, I'd prefer to use something like the `sphinx-design` buttons, but they don't support the dynamicism that the shields.io badges do. We can just add a CSS margin to the icon class.
~The kernel specification _is_ being generated, at least locally. I'm not sure why it's not appearing in the built docs~

Ah, it's the change I made to use `runpy`. I'll fix this in the PR that closes this issue.

Resolving patch:
diff --git a/docs-sphinx/conf.py b/docs-sphinx/conf.py
--- a/docs-sphinx/conf.py
+++ b/docs-sphinx/conf.py
@@ -160,3 +160,15 @@
 
 # Generate kernel docs
 runpy.run_path(HERE.parent / "dev" / "generate-kerneldocs.py", run_name="__main__")
+
+
+# Sphinx doesn't usually want content to fit the screen, so we hack the styles for this page
+def install_jupyterlite_styles(app, pagename, templatename, context, event_arg) -> None:
+    if pagename != "getting-started/try-awkward-array":
+        return
+
+    app.add_css_file("css/try-awkward-array.css")
+
+
+def setup(app):
+    app.connect('html-page-context', install_jupyterlite_styles)


Test patch:
Repository: scikit-hep/awkward

Issue:
Awkward v2 mixins not propagated upwards
### Version of Awkward Array

2.0.0rc1

### Description and code to reproduce

Coffea tests with awkwardv2 fail with: `E   AttributeError: module 'awkward.behaviors' has no attribute 'mixin_class'`

`awkward.mixin_class` has moved to `awkward.behaviors.mixins.mixin_class`, along with all other mixin decorators.


Discussion:

Resolving patch:
diff --git a/src/awkward/__init__.py b/src/awkward/__init__.py
--- a/src/awkward/__init__.py
+++ b/src/awkward/__init__.py
@@ -39,8 +39,8 @@
 
 # behaviors
 import awkward.behaviors.categorical
-import awkward.behaviors.mixins
 import awkward.behaviors.string
+from awkward.behaviors.mixins import mixin_class, mixin_class_method
 
 behavior = {}
 awkward.behaviors.string.register(behavior)  # noqa: F405


Test patch:
Repository: scikit-hep/awkward

Issue:
Bad error message for decimal type
### Version of Awkward Array

main

### Description and code to reproduce

If you attempt to load a parquet file containing decimal columns, you get a ValueError, which is expected, but the message is:
```
"Arrow arrays containing pickled Python objects can't be converted into Awkward Arrays"
```
which looks like it's been copied from somewhere else.

https://github.com/scikit-hep/awkward/blob/main/src/awkward/_connect/pyarrow.py#L476


Discussion:

Resolving patch:
diff --git a/src/awkward/_connect/pyarrow.py b/src/awkward/_connect/pyarrow.py
--- a/src/awkward/_connect/pyarrow.py
+++ b/src/awkward/_connect/pyarrow.py
@@ -473,7 +473,7 @@ def popbuffers(paarray, awkwardarrow_type, storage_type, buffers, generate_bitma
         # NumPy doesn't support decimal: https://github.com/numpy/numpy/issues/9789
         raise ak._errors.wrap_error(
             ValueError(
-                "Arrow arrays containing pickled Python objects can't be converted into Awkward Arrays"
+                "Arrow arrays containing pyarrow.decimal128 or pyarrow.decimal256 types can't be converted into Awkward Arrays"
             )
         )
 
@@ -746,7 +746,7 @@ def form_popbuffers(awkwardarrow_type, storage_type):
         # NumPy doesn't support decimal: https://github.com/numpy/numpy/issues/9789
         raise ak._errors.wrap_error(
             ValueError(
-                "Arrow arrays containing pickled Python objects can't be converted into Awkward Arrays"
+                "Arrow arrays containing pyarrow.decimal128 or pyarrow.decimal256 types can't be converted into Awkward Arrays"
             )
         )
 


Test patch:
Repository: scikit-hep/awkward

Issue:
Remove unused `num` kernels
### Version of Awkward Array

main

### Description and code to reproduce

...


Discussion:

Resolving patch:
diff --git a/dev/generate-kernel-signatures.py b/dev/generate-kernel-signatures.py
--- a/dev/generate-kernel-signatures.py
+++ b/dev/generate-kernel-signatures.py
@@ -11,8 +11,6 @@
 
 
 cuda_kernels_impl = [
-    "awkward_ListArray_num",
-    "awkward_RegularArray_num",
     "awkward_ListArray_validity",
     "awkward_BitMaskedArray_to_ByteMaskedArray",
     "awkward_ListArray_compact_offsets",
diff --git a/dev/generate-tests.py b/dev/generate-tests.py
--- a/dev/generate-tests.py
+++ b/dev/generate-tests.py
@@ -541,8 +541,6 @@ def gencpukerneltests(specdict):
 
 
 cuda_kernels_tests = [
-    "awkward_ListArray_num",
-    "awkward_RegularArray_num",
     "awkward_ListArray_validity",
     "awkward_BitMaskedArray_to_ByteMaskedArray",
     "awkward_ListArray_compact_offsets",


Test patch:
Repository: scikit-hep/awkward

Issue:
`ak.type` does not accept "anything `ak.to_layout` recognizes"
### Version of Awkward Array

main

### Description and code to reproduce

```python
>>> import awkward as ak
>>> ak.type([1,2,3])

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 1
----> 1 ak.type([1,2,3])

File /lib/python3.10/site-packages/awkward/operations/ak_type.py:77, in type(array)
     15 """
     16 Args:
     17     array: Array-like data (anything #ak.to_layout recognizes).
   (...)
     71 to the language.)
     72 """
     73 with ak._errors.OperationErrorContext(
     74     "ak.type",
     75     dict(array=array),
     76 ):
---> 77     return _impl(array)

File /lib/python3.10/site-packages/awkward/operations/ak_type.py:144, in _impl(array)
    141     return array.form.type
    143 else:
--> 144     raise ak._errors.wrap_error(TypeError(f"unrecognized array type: {array!r}"))

TypeError: while calling

    ak.type(
        array = [1, 2, 3]
    )

Error details: unrecognized array type: [1, 2, 3]
```


Discussion:

Resolving patch:
diff --git a/src/awkward/operations/ak_type.py b/src/awkward/operations/ak_type.py
--- a/src/awkward/operations/ak_type.py
+++ b/src/awkward/operations/ak_type.py
@@ -141,4 +141,5 @@ def _impl(array):
         return array.form.type
 
     else:
-        raise ak._errors.wrap_error(TypeError(f"unrecognized array type: {array!r}"))
+        layout = ak.to_layout(array, allow_other=False)
+        return _impl(ak._util.wrap(layout))


Test patch:
diff --git a/tests/test_2008-ak-type-layout.py b/tests/test_2008-ak-type-layout.py
new file mode 100644
--- /dev/null
+++ b/tests/test_2008-ak-type-layout.py
@@ -0,0 +1,16 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import re
+
+import awkward as ak
+
+
+def test_simple():
+    assert re.match(r"3 \* u?int\d+", str(ak.type([1, 2, 3])))
+
+
+def test_complex():
+    assert re.match(
+        r"2 \* \{x: union\[var \* \?u?int\d+, float\d+\]\}",
+        str(ak.type([{"x": [None, 10]}, {"x": 40.0}])),
+    )
Repository: scikit-hep/awkward

Issue:
`ak.to_numpy()` fails cryptically for `ak.Array([{}])`
### Version of Awkward Array

main

### Description and code to reproduce

This raises
```pytb
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In [10], line 1
----> 1 ak.to_numpy(x)

File ~/Git/awkward/src/awkward/operations/ak_to_numpy.py:39, in to_numpy(array, allow_missing)
      9 """
     10 Converts `array` (many types supported, including all Awkward Arrays and
     11 Records) into a NumPy array, if possible.
   (...)
     33 See also #ak.from_numpy and #ak.to_cupy.
     34 """
     35 with ak._errors.OperationErrorContext(
     36     "ak.to_numpy",
     37     dict(array=array, allow_missing=allow_missing),
     38 ):
---> 39     return ak._util.to_arraylib(numpy, array, allow_missing)

File ~/Git/awkward/src/awkward/_util.py:806, in to_arraylib(module, array, allow_missing)
    803 layout = ak.operations.to_layout(array, allow_record=True, allow_other=True)
    805 if isinstance(layout, (ak.contents.Content, ak.record.Record)):
--> 806     return layout.to_numpy(allow_missing=allow_missing)
    807 else:
    808     return module.asarray(array)

File ~/Git/awkward/src/awkward/contents/content.py:1561, in Content.to_numpy(self, allow_missing)
   1560 def to_numpy(self, allow_missing: bool):
-> 1561     return self._to_numpy(allow_missing)

File ~/Git/awkward/src/awkward/contents/recordarray.py:922, in RecordArray._to_numpy(self, allow_missing)
    917 if any(len(x.shape) != 1 for x in contents):
    918     raise ak._errors.wrap_error(
    919         ValueError(f"cannot convert {self} into np.ndarray")
    920     )
    921 out = self._backend.nplike.empty(
--> 922     contents[0].shape[0],
    923     dtype=[(str(n), x.dtype) for n, x in zip(self.fields, contents)],
    924 )
    925 mask = None
    926 for n, x in zip(self.fields, contents):

IndexError: list index out of range
```

Clearly we're assuming that a `RecordArray` always has contents. This should be a simple fix.


Discussion:

Resolving patch:
diff --git a/src/awkward/contents/recordarray.py b/src/awkward/contents/recordarray.py
--- a/src/awkward/contents/recordarray.py
+++ b/src/awkward/contents/recordarray.py
@@ -868,7 +868,7 @@ def _to_numpy(self, allow_missing):
                 ValueError(f"cannot convert {self} into np.ndarray")
             )
         out = self._backend.nplike.empty(
-            contents[0].shape[0],
+            self.length,
             dtype=[(str(n), x.dtype) for n, x in zip(self.fields, contents)],
         )
         mask = None


Test patch:
diff --git a/tests/test_1944-to-numpy-empty-record-array.py b/tests/test_1944-to-numpy-empty-record-array.py
new file mode 100644
--- /dev/null
+++ b/tests/test_1944-to-numpy-empty-record-array.py
@@ -0,0 +1,7 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import awkward as ak
+
+
+def test():
+    assert ak.to_numpy(ak.Array([{}, {}])).tolist() == [(), ()]
Repository: scikit-hep/awkward

Issue:
Typetracers with unknown length can't print their type
### Version of Awkward Array

HEAD

### Description and code to reproduce

```python
>>> import awkward as ak
>>> typetracer = ak.Array([[1, 2, 3], [], [4, 5]]).layout.typetracer
>>> typetracer.offsets.data.shape = (ak._typetracer.UnknownLength,)
>>> ak.Array(typetracer).type
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jpivarski/irishep/awkward/src/awkward/highlevel.py", line 463, in type
    self._layout.form.type_from_behavior(self._behavior), len(self._layout)
TypeError: 'UnknownLengthType' object cannot be interpreted as an integer
```

This should be easy: replacing `len(self._layout)` with `self._layout.length` and using the string `"??"` in case of `ak._typetracer.UnknownLength`.

Cc: @douglasdavis


Discussion:

Resolving patch:
diff --git a/src/awkward/highlevel.py b/src/awkward/highlevel.py
--- a/src/awkward/highlevel.py
+++ b/src/awkward/highlevel.py
@@ -442,7 +442,7 @@ def type(self):
         wrapped by an #ak.types.ArrayType.
         """
         return ak.types.ArrayType(
-            self._layout.form.type_from_behavior(self._behavior), len(self._layout)
+            self._layout.form.type_from_behavior(self._behavior), self._layout.length
         )
 
     @property
@@ -468,7 +468,7 @@ def __len__(self):
 
         is `3`, not `5`.
         """
-        return len(self._layout)
+        return self._layout.length
 
     def __iter__(self):
         """
diff --git a/src/awkward/types/arraytype.py b/src/awkward/types/arraytype.py
--- a/src/awkward/types/arraytype.py
+++ b/src/awkward/types/arraytype.py
@@ -3,7 +3,6 @@
 import sys
 
 import awkward as ak
-import awkward.types.type
 
 
 class ArrayType:
@@ -16,10 +15,13 @@ def __init__(self, content, length):
                     )
                 )
             )
-        if not ak._util.is_integer(length) or length < 0:
+        if not (
+            (ak._util.is_integer(length) and length >= 0)
+            or length is ak._typetracer.UnknownLength
+        ):
             raise ak._errors.wrap_error(
                 ValueError(
-                    "{} 'length' must be of a positive integer, not {}".format(
+                    "{} 'length' must be a non-negative integer or unknown length, not {}".format(
                         type(self).__name__, repr(length)
                     )
                 )


Test patch:
Repository: scikit-hep/awkward

Issue:
`ak.unzip(record)` fails with exception
### Version of Awkward Array

main

### Description and code to reproduce

```python3
record = ak.Record({'x': 1, 'y': 2})
print(ak.unzip(record))
```


Discussion:

Resolving patch:
diff --git a/src/awkward/_util.py b/src/awkward/_util.py
--- a/src/awkward/_util.py
+++ b/src/awkward/_util.py
@@ -427,9 +427,11 @@ def behavior_of(*arrays, **kwargs):
     return behavior
 
 
-def wrap(content, behavior=None, highlevel=True, like=None):
-    assert content is None or isinstance(
-        content, (ak.contents.Content, ak.record.Record)
+def wrap(content, behavior=None, highlevel=True, like=None, allow_other=False):
+    assert (
+        content is None
+        or isinstance(content, (ak.contents.Content, ak.record.Record))
+        or allow_other
     )
     assert behavior is None or isinstance(behavior, Mapping)
     assert isinstance(highlevel, bool)
diff --git a/src/awkward/operations/ak_unzip.py b/src/awkward/operations/ak_unzip.py
--- a/src/awkward/operations/ak_unzip.py
+++ b/src/awkward/operations/ak_unzip.py
@@ -60,6 +60,9 @@ def check_for_union(layout, **kwargs):
     ak._do.recursively_apply(layout, check_for_union, behavior, return_array=False)
 
     if len(fields) == 0:
-        return (ak._util.wrap(layout, behavior, highlevel),)
+        return (ak._util.wrap(layout, behavior, highlevel, allow_other=True),)
     else:
-        return tuple(ak._util.wrap(layout[n], behavior, highlevel) for n in fields)
+        return tuple(
+            ak._util.wrap(layout[n], behavior, highlevel, allow_other=True)
+            for n in fields
+        )


Test patch:
diff --git a/tests/test_2076_ak_unzip_record.py b/tests/test_2076_ak_unzip_record.py
new file mode 100644
--- /dev/null
+++ b/tests/test_2076_ak_unzip_record.py
@@ -0,0 +1,11 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import pytest  # noqa: F401
+
+import awkward as ak
+
+
+def test():
+    record = ak.Record({"x": 1, "y": 2, "z": 3})
+    assert ak.fields(record) == ["x", "y", "z"]
+    assert ak.unzip(record) == (1, 2, 3)
Repository: scikit-hep/awkward

Issue:
`np.broadcast_arrays` array function overload has unknown result type
### Version of Awkward Array

main

### Description and code to reproduce

Our generic dispatch for array function always tries to wrap the result as a layout. For overloads that awkward defines, we should trust that the result is already a layout.


Discussion:

Resolving patch:
diff --git a/src/awkward/_connect/numpy.py b/src/awkward/_connect/numpy.py
--- a/src/awkward/_connect/numpy.py
+++ b/src/awkward/_connect/numpy.py
@@ -50,15 +50,13 @@ def array_function(func, types, args, kwargs, behavior):
         rectilinear_args = tuple(_to_rectilinear(x) for x in args)
         rectilinear_kwargs = {k: _to_rectilinear(v) for k, v in kwargs.items()}
         result = func(*rectilinear_args, **rectilinear_kwargs)
+        # We want the result to be a layout (this will fail for functions returning non-array convertibles)
+        out = ak.operations.ak_to_layout._impl(
+            result, allow_record=True, allow_other=True
+        )
+        return ak._util.wrap(out, behavior=behavior, allow_other=True)
     else:
-        result = function(*args, **kwargs)
-
-    # We want the result to be a layout
-    out = ak.operations.ak_to_layout._impl(result, allow_record=True, allow_other=True)
-    if isinstance(out, (ak.contents.Content, ak.record.Record)):
-        return ak._util.wrap(out, behavior=behavior)
-    else:
-        return out
+        return function(*args, **kwargs)
 
 
 def implements(numpy_function):


Test patch:
diff --git a/tests/test_2078_array_function_wrap.py b/tests/test_2078_array_function_wrap.py
new file mode 100644
--- /dev/null
+++ b/tests/test_2078_array_function_wrap.py
@@ -0,0 +1,17 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import numpy as np
+import pytest  # noqa: F401
+
+import awkward as ak
+
+
+def test():
+    left = ak.Array([1, 2, 3])
+    right = ak.Array([[1, 2], [4, 5, 6], [None]])
+    result = np.broadcast_arrays(left, right)
+    assert isinstance(result, list)
+    assert isinstance(result[0], ak.Array)
+    assert isinstance(result[1], ak.Array)
+    assert result[0].to_list() == [[1, 1], [2, 2, 2], [None]]
+    assert result[1].to_list() == [[1, 2], [4, 5, 6], [None]]
Repository: scikit-hep/awkward

Issue:
`NumpyArray` merging is broken with option types
### Version of Awkward Array

main

### Description and code to reproduce

This was probably caused by #2063

```python
>>> import awkward as ak
>> ak.concatenate([
...    ak.Array([1,2,3]),
...    ak.Array([1,2,None])
... ])
[1,
 2,
 3,
 1,
 2,
 None]
----------------
type: 6 * union[
    int64,
    ?int64
]


Discussion:

Resolving patch:
diff --git a/src/awkward/contents/numpyarray.py b/src/awkward/contents/numpyarray.py
--- a/src/awkward/contents/numpyarray.py
+++ b/src/awkward/contents/numpyarray.py
@@ -342,10 +342,21 @@ def _offsets_and_flattened(self, axis, depth):
             )
 
     def _mergeable_next(self, other, mergebool):
-
         if len(self.shape) > 1:
             return self._to_regular_primitive()._mergeable(other, mergebool)
 
+        if isinstance(
+            other,
+            (
+                ak.contents.IndexedArray,
+                ak.contents.IndexedOptionArray,
+                ak.contents.ByteMaskedArray,
+                ak.contents.BitMaskedArray,
+                ak.contents.UnmaskedArray,
+            ),
+        ):
+            return self._mergeable(other._content, mergebool)
+
         elif isinstance(other, ak.contents.NumpyArray):
             if self._data.ndim != other._data.ndim:
                 return False


Test patch:
diff --git a/tests/test_2104_numpy_merge_option.py b/tests/test_2104_numpy_merge_option.py
new file mode 100644
--- /dev/null
+++ b/tests/test_2104_numpy_merge_option.py
@@ -0,0 +1,17 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import numpy as np
+import pytest  # noqa: F401
+
+import awkward as ak
+
+
+def test():
+    assert ak._util.arrays_approx_equal(
+        ak.concatenate([ak.Array([1, 2, 3]), ak.Array([1, 2, None])]),
+        ak.contents.ByteMaskedArray(
+            ak.index.Index8(np.array([False, False, False, False, False, True])),
+            ak.contents.NumpyArray(np.array([1, 2, 3, 1, 2, 3], dtype=np.int64)),
+            valid_when=False,
+        ),
+    )
Repository: scikit-hep/awkward

Issue:
`fill_none` doesn't move through indexed types
### Version of Awkward Array

main

### Description and code to reproduce

The failure mode here is where we have a lazy carryd `RecordArray`, which then contains an option. Our existing logic returns early if it doesn't see an option, union, or record.


Discussion:

Resolving patch:
diff --git a/src/awkward/operations/ak_fill_none.py b/src/awkward/operations/ak_fill_none.py
--- a/src/awkward/operations/ak_fill_none.py
+++ b/src/awkward/operations/ak_fill_none.py
@@ -117,10 +117,10 @@ def action(layout, continuation, **kwargs):
         def action(layout, depth, **kwargs):
             posaxis = ak._util.maybe_posaxis(layout, axis, depth)
             if posaxis is not None and posaxis + 1 == depth:
-                if layout.is_union or layout.is_record:
-                    return None
-                elif layout.is_option:
+                if layout.is_option:
                     return ak._do.fill_none(layout, valuelayout)
+                elif layout.is_union or layout.is_record or layout.is_indexed:
+                    return None
                 else:
                     return layout
 


Test patch:
diff --git a/tests/test_2108_fill_none_indexed.py b/tests/test_2108_fill_none_indexed.py
new file mode 100644
--- /dev/null
+++ b/tests/test_2108_fill_none_indexed.py
@@ -0,0 +1,26 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import numpy as np
+import pytest  # noqa: F401
+
+import awkward as ak
+
+
+def test():
+    layout = ak.contents.IndexedArray(
+        ak.index.Index64(np.arange(10)),
+        ak.contents.RecordArray(
+            [
+                ak.contents.IndexedOptionArray(
+                    ak.index.Index64(
+                        np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, -1], dtype=np.int64)
+                    ),
+                    ak.contents.NumpyArray(np.arange(10)),
+                )
+            ],
+            ["x"],
+        ),
+    )
+    assert ak._util.arrays_approx_equal(
+        ak.fill_none(layout, 9, axis=0), ak.zip({"x": np.arange(10)})
+    )
Repository: scikit-hep/awkward

Issue:
NEP-18 sort kind translation is incorrect
### Version of Awkward Array

main

### Description and code to reproduce

We only support "stable", so we should just coerce the algorithms into a `stable` flag.


Discussion:

Resolving patch:
diff --git a/src/awkward/operations/ak_argsort.py b/src/awkward/operations/ak_argsort.py
--- a/src/awkward/operations/ak_argsort.py
+++ b/src/awkward/operations/ak_argsort.py
@@ -70,9 +70,9 @@ def _impl(array, axis, ascending, stable, highlevel, behavior):
 def _nep_18_impl(a, axis=-1, kind=None, order=unsupported):
     if kind is None:
         stable = False
-    elif kind == "stable":
+    elif kind in ("stable", "mergesort"):
         stable = True
-    elif kind == "heapsort":
+    elif kind in ("heapsort", "quicksort"):
         stable = False
     else:
         raise ak._errors.wrap_error(
diff --git a/src/awkward/operations/ak_sort.py b/src/awkward/operations/ak_sort.py
--- a/src/awkward/operations/ak_sort.py
+++ b/src/awkward/operations/ak_sort.py
@@ -57,9 +57,9 @@ def _impl(array, axis, ascending, stable, highlevel, behavior):
 def _nep_18_impl(a, axis=-1, kind=None, order=unsupported):
     if kind is None:
         stable = False
-    elif kind == "stable":
+    elif kind in ("stable", "mergesort"):
         stable = True
-    elif kind == "heapsort":
+    elif kind in ("heapsort", "quicksort"):
         stable = False
     else:
         raise ak._errors.wrap_error(


Test patch: