Repository: scikit-hep/awkward

Issue:
`from_numpy` fails for string dtypes (v2)
### Version of Awkward Array

314efeee9e17626f363dffc6010ccc6ab6002bea

### Description and code to reproduce

```pycon
>>> import awkward._v2 as ak
>>> import numpy as np
>>> ak.from_numpy(np.array(["this", "that"]))
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [1], in <cell line: 3>()
      1 import awkward._v2 as ak
      2 import numpy as np
----> 3 ak.from_numpy(np.array(["this", "that"]))

File ~/Git/awkward-1.0/awkward/_v2/operations/convert/ak_from_numpy.py:53, in from_numpy(array, regulararray, recordarray, highlevel, behavior)
     12 """
     13 Args:
     14     array (np.ndarray): The NumPy array to convert into an Awkward Array.
   (...)
     41 See also #ak.to_numpy and #ak.from_cupy.
     42 """
     43 with ak._v2._util.OperationErrorContext(
     44     "ak._v2.from_numpy",
     45     dict(
   (...)
     51     ),
     52 ):
---> 53     return _impl(array, regulararray, recordarray, highlevel, behavior)

File ~/Git/awkward-1.0/awkward/_v2/operations/convert/ak_from_numpy.py:142, in _impl(array, regulararray, recordarray, highlevel, behavior)
    139     mask = None
    141 if not recordarray or array.dtype.names is None:
--> 142     layout = recurse(array, mask)
    144 else:
    145     contents = []

File ~/Git/awkward-1.0/awkward/_v2/operations/convert/ak_from_numpy.py:91, in _impl.<locals>.recurse(array, mask)
     89 starts = numpy.arange(0, len(asbytes) * itemsize, itemsize, dtype=np.int64)
     90 stops = starts + numpy.char.str_len(asbytes)
---> 91 data = ak._v2.contents.ListArray64(
     92     ak._v2.index.Index64(starts),
     93     ak._v2.index.Index64(stops),
     94     ak._v2.contents.NumpyArray(
     95         asbytes.view("u1"), parameters={"__array__": "char"}, nplike=numpy
     96     ),
     97     parameters={"__array__": "string"},
     98 )
     99 for i in range(len(array.shape) - 1, 0, -1):
    100     data = ak._v2.contents.RegularArray(
    101         data, array.shape[i], array.shape[i - 1]
    102     )

AttributeError: module 'awkward._v2.contents' has no attribute 'ListArray64'
```


Discussion:

Resolving patch:
diff --git a/src/awkward/_v2/operations/convert/ak_from_numpy.py b/src/awkward/_v2/operations/convert/ak_from_numpy.py
--- a/src/awkward/_v2/operations/convert/ak_from_numpy.py
+++ b/src/awkward/_v2/operations/convert/ak_from_numpy.py
@@ -70,7 +70,7 @@ def recurse(array, mask):
             itemsize = asbytes.dtype.itemsize
             starts = numpy.arange(0, len(asbytes) * itemsize, itemsize, dtype=np.int64)
             stops = starts + numpy.char.str_len(asbytes)
-            data = ak._v2.contents.ListArray64(
+            data = ak._v2.contents.ListArray(
                 ak._v2.index.Index64(starts),
                 ak._v2.index.Index64(stops),
                 ak._v2.contents.NumpyArray(
@@ -88,7 +88,7 @@ def recurse(array, mask):
             itemsize = asbytes.dtype.itemsize
             starts = numpy.arange(0, len(asbytes) * itemsize, itemsize, dtype=np.int64)
             stops = starts + numpy.char.str_len(asbytes)
-            data = ak._v2.contents.ListArray64(
+            data = ak._v2.contents.ListArray(
                 ak._v2.index.Index64(starts),
                 ak._v2.index.Index64(stops),
                 ak._v2.contents.NumpyArray(


Test patch:
diff --git a/tests/v2/test_1403-from_numpy-strings.py b/tests/v2/test_1403-from_numpy-strings.py
new file mode 100644
--- /dev/null
+++ b/tests/v2/test_1403-from_numpy-strings.py
@@ -0,0 +1,17 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import pytest  # noqa: F401
+import awkward as ak  # noqa: F401
+import numpy as np
+
+
+def test_unicode():
+    data = np.array(["this", "that"])
+    array = ak._v2.from_numpy(data)
+    assert array.to_list() == ["this", "that"]
+
+
+def test_bytes():
+    data = np.array([b"this", b"that"], dtype="S")
+    array = ak._v2.from_numpy(data)
+    assert array.to_list() == [b"this", b"that"]