From 1af66e57b5b6aaf9d9b25ac25498941edc5893b0 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 7 Nov 2025 06:40:24 -0800 Subject: [PATCH 1/4] Implement tobytes() method in dpnp.ndarray --- dpnp/dpnp_array.py | 37 +++++++++++++++++++++++++++++++- dpnp/dpnp_iface_arraycreation.py | 2 ++ dpnp/dpnp_iface_bitwise.py | 2 +- dpnp/dpnp_iface_indexing.py | 2 +- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/dpnp/dpnp_array.py b/dpnp/dpnp_array.py index 456cc84b5b26..b9c2ff6f3f91 100644 --- a/dpnp/dpnp_array.py +++ b/dpnp/dpnp_array.py @@ -2012,7 +2012,42 @@ def to_device(self, device, /, *, stream=None): usm_res = self._array_obj.to_device(device, stream=stream) return dpnp_array._create_from_usm_ndarray(usm_res) - # 'tobytes', + def tobytes(self, order="C"): + r""" + Constructs Python bytes containing the raw data bytes in the array. + + For full documentation refer to :obj:`numpy.ndarray.tobytes`. + + Parameters + ---------- + order : {None, "C", "F", "A", "K"}, optional + Controls the memory layout of the bytes object. + + Default: ``"C"``. + + Returns + ------- + out : bytes + Python bytes exhibiting a copy of array's raw data. + + See Also + -------- + :obj:`dpnp.frombuffer` : Construct a 1D array from Python bytes. + + Examples + -------- + >>> import dpnp as np + >>> x = np.array([[0, 1], [2, 3]], dtype='i2') + >>> x.tobytes() + b'\x00\x00\x01\x00\x02\x00\x03\x00' + >>> x.tobytes("C") == x.tobytes() + True + >>> x.tobytes("F") + b'\x00\x00\x02\x00\x01\x00\x03\x00' + + """ + + return self.asnumpy().tobytes(order=order) def tofile(self, fid, sep="", format=""): """ diff --git a/dpnp/dpnp_iface_arraycreation.py b/dpnp/dpnp_iface_arraycreation.py index d768a2f69a6f..e8f3edcd1e68 100644 --- a/dpnp/dpnp_iface_arraycreation.py +++ b/dpnp/dpnp_iface_arraycreation.py @@ -1705,6 +1705,8 @@ def frombuffer( :obj:`dpnp.fromfile` : Construct array from data in a text or binary file. :obj:`dpnp.fromiter` : Construct array from an iterable object. :obj:`dpnp.fromstring` : Construct array from the text data in a string. + :obj:`ndarray.tobytes` : Construct Python bytes from the raw data bytes + in the array. Examples -------- diff --git a/dpnp/dpnp_iface_bitwise.py b/dpnp/dpnp_iface_bitwise.py index e823863b43c7..b7fb83b12518 100644 --- a/dpnp/dpnp_iface_bitwise.py +++ b/dpnp/dpnp_iface_bitwise.py @@ -111,7 +111,7 @@ def binary_repr(num, width=None): Examples -------- - >>> import numpy as np + >>> import dpnp as np >>> np.binary_repr(3) '11' >>> np.binary_repr(-3) diff --git a/dpnp/dpnp_iface_indexing.py b/dpnp/dpnp_iface_indexing.py index 97f50a1c1489..7ed5f9c84397 100644 --- a/dpnp/dpnp_iface_indexing.py +++ b/dpnp/dpnp_iface_indexing.py @@ -396,7 +396,7 @@ def compress(condition, a, axis=None, out=None): Examples -------- - >>> import numpy as np + >>> import dpnp as np >>> a = np.array([[1, 2], [3, 4], [5, 6]]) >>> a array([[1, 2], From 2bbf9f3f037967523e2874719c2845740415cf13 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 7 Nov 2025 06:41:32 -0800 Subject: [PATCH 2/4] Enable third party tests --- .../third_party/cupy/core_tests/test_ndarray_conversion.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dpnp/tests/third_party/cupy/core_tests/test_ndarray_conversion.py b/dpnp/tests/third_party/cupy/core_tests/test_ndarray_conversion.py index 90961602eba1..efd888094c94 100644 --- a/dpnp/tests/third_party/cupy/core_tests/test_ndarray_conversion.py +++ b/dpnp/tests/third_party/cupy/core_tests/test_ndarray_conversion.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest import numpy @@ -42,7 +44,6 @@ def test_item(self): {"shape": (2, 3), "order": "C"}, {"shape": (2, 3), "order": "F"}, ) -@pytest.mark.skip("tobytes() method is not supported yet") class TestNdarrayToBytes(unittest.TestCase): @testing.for_all_dtypes() From d6c0cba5c1499a47ec2136c3a4050b0425fadf65 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 7 Nov 2025 06:52:11 -0800 Subject: [PATCH 3/4] Add more testing with different order values --- dpnp/tests/test_ndarray.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dpnp/tests/test_ndarray.py b/dpnp/tests/test_ndarray.py index 2aa6c0f49acc..28354ff74372 100644 --- a/dpnp/tests/test_ndarray.py +++ b/dpnp/tests/test_ndarray.py @@ -108,6 +108,18 @@ def test_strides(self): assert xp.full_like(a, fill_value=6) not in a +class TestToBytes: + @pytest.mark.parametrize("order", ["C", "F", "K", "A", None]) + def test_roundtrip_binary_str(self, order): + x = generate_random_numpy_array((2, 4, 3), dtype=complex) + x[0, :, 1] = [numpy.nan, numpy.inf, -numpy.inf, numpy.nan] + a = dpnp.array(x) + + s = a.tobytes(order=order) + b = dpnp.frombuffer(s, dtype=a.dtype) + assert_array_equal(b, a.asnumpy().flatten(order)) + + class TestToFile: def _create_data(self): x = generate_random_numpy_array((2, 4, 3), dtype=complex) From 7bc712ca23fe598a4fb7fb9de67b7a69af689fe3 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Fri, 7 Nov 2025 06:54:21 -0800 Subject: [PATCH 4/4] Add PR to the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5519ebb6774d..b49d90ee9dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Also, that release drops support for Python 3.9, making Python 3.10 the minimum * Added implementation of `dpnp.ndarray.tolist` method [#2652](https://github.com/IntelPython/dpnp/pull/2652) * Added implementation of `dpnp.frexp` [#2635](https://github.com/IntelPython/dpnp/pull/2635) * Added implementation of `dpnp.ndarray.tofile` method [#2635](https://github.com/IntelPython/dpnp/pull/2635) +* Added implementation of `dpnp.ndarray.tobytes` method [#2656](https://github.com/IntelPython/dpnp/pull/2656) ### Changed