From 27fe2f67b7e6d65d59440558fd52c606e9b52faf Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 8 Jan 2026 17:27:11 +0000 Subject: [PATCH 01/10] [mypyc] Add primitive type for bytearray --- mypyc/codegen/emit.py | 11 +++++++++++ mypyc/ir/rtypes.py | 8 ++++++++ mypyc/irbuild/mapper.py | 3 +++ mypyc/primitives/bytes_ops.py | 3 ++- mypyc/test-data/irbuild-bytes.test | 18 +++++++++++------- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/mypyc/codegen/emit.py b/mypyc/codegen/emit.py index 236da808c038..bcaf0963af6f 100644 --- a/mypyc/codegen/emit.py +++ b/mypyc/codegen/emit.py @@ -33,6 +33,7 @@ RUnion, int_rprimitive, is_bool_or_bit_rprimitive, + is_bytearray_rprimitive, is_bytes_rprimitive, is_dict_rprimitive, is_fixed_width_rtype, @@ -664,6 +665,16 @@ def emit_cast( self.emit_lines(f" {dest} = {src};", "else {") self.emit_cast_error_handler(error, src, dest, typ, raise_exception) self.emit_line("}") + elif is_bytearray_rprimitive(typ): + if declare_dest: + self.emit_line(f"PyObject *{dest};") + check = "(PyByteArray_Check({}))" + if likely: + check = f"(likely{check})" + self.emit_arg_check(src, dest, typ, check.format(src, src), optional) + self.emit_lines(f" {dest} = {src};", "else {") + self.emit_cast_error_handler(error, src, dest, typ, raise_exception) + self.emit_line("}") elif is_tuple_rprimitive(typ): if declare_dest: self.emit_line(f"{self.ctype(typ)} {dest};") diff --git a/mypyc/ir/rtypes.py b/mypyc/ir/rtypes.py index 1335f818bebc..047690267b34 100644 --- a/mypyc/ir/rtypes.py +++ b/mypyc/ir/rtypes.py @@ -504,6 +504,9 @@ def __hash__(self) -> int: # Python bytes object. bytes_rprimitive: Final = RPrimitive("builtins.bytes", is_unboxed=False, is_refcounted=True) +# Python bytearray object. +bytearray_rprimitive: Final = RPrimitive("builtins.bytearray", is_unboxed=False, is_refcounted=True) + # Tuple of an arbitrary length (corresponds to Tuple[t, ...], with # explicit '...'). tuple_rprimitive: Final = RPrimitive("builtins.tuple", is_unboxed=False, is_refcounted=True) @@ -632,6 +635,10 @@ def is_bytes_rprimitive(rtype: RType) -> TypeGuard[RPrimitive]: return isinstance(rtype, RPrimitive) and rtype.name == "builtins.bytes" +def is_bytearray_rprimitive(rtype: RType) -> TypeGuard[RPrimitive]: + return isinstance(rtype, RPrimitive) and rtype.name == "builtins.bytearray" + + def is_tuple_rprimitive(rtype: RType) -> TypeGuard[RPrimitive]: return isinstance(rtype, RPrimitive) and rtype.name == "builtins.tuple" @@ -646,6 +653,7 @@ def is_sequence_rprimitive(rtype: RType) -> TypeGuard[RPrimitive]: or is_tuple_rprimitive(rtype) or is_str_rprimitive(rtype) or is_bytes_rprimitive(rtype) + or is_bytearray_rprimitive(rtype) ) diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index c986499b6f65..550dc6e42c9e 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -31,6 +31,7 @@ RType, RUnion, bool_rprimitive, + bytearray_rprimitive, bytes_rprimitive, dict_rprimitive, float_rprimitive, @@ -88,6 +89,8 @@ def type_to_rtype(self, typ: Type | None) -> RType: return str_rprimitive elif typ.type.fullname == "builtins.bytes": return bytes_rprimitive + elif typ.type.fullname == "builtins.bytearray": + return bytearray_rprimitive elif typ.type.fullname == "builtins.list": return list_rprimitive # Dict subclasses are at least somewhat common and we diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index 2268acd80aa5..d9700ae4abd1 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -8,6 +8,7 @@ RUnion, bit_rprimitive, bool_rprimitive, + bytearray_rprimitive, bytes_rprimitive, c_int_rprimitive, c_pyssize_t_rprimitive, @@ -51,7 +52,7 @@ function_op( name="builtins.bytearray", arg_types=[object_rprimitive], - return_type=object_rprimitive, + return_type=bytearray_rprimitive, c_function_name="PyByteArray_FromObject", error_kind=ERR_MAGIC, ) diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index 613ba4e46eee..0caec05a3ea8 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -50,18 +50,22 @@ def f(s, num): num :: int r0 :: object r1 :: str - r2, r3, a, r4, b, r5, r6, c :: object + r2, r3 :: object + r4, a, r5, b :: bytearray + r6 :: object + r7, c :: bytearray L0: r0 = builtins :: module r1 = 'bytearray' r2 = CPyObject_GetAttr(r0, r1) r3 = PyObject_Vectorcall(r2, 0, 0, 0) - a = r3 - r4 = PyByteArray_FromObject(s) - b = r4 - r5 = box(int, num) - r6 = PyByteArray_FromObject(r5) - c = r6 + r4 = cast(bytearray, r3) + a = r4 + r5 = PyByteArray_FromObject(s) + b = r5 + r6 = box(int, num) + r7 = PyByteArray_FromObject(r6) + c = r7 return 1 [case testBytesEquality] From 116dd820f6bb7b0d0f96911e94f5fc54cddc49fb Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 8 Jan 2026 17:34:24 +0000 Subject: [PATCH 02/10] Add primitive for bytearray type object --- mypyc/primitives/bytes_ops.py | 5 ++++- mypyc/test-data/irbuild-bytes.test | 30 +++++++++++++----------------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index d9700ae4abd1..79601b857ec6 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -1,4 +1,4 @@ -"""Primitive bytes ops.""" +"""Primitive bytes and bytearray ops.""" from __future__ import annotations @@ -30,6 +30,9 @@ # Get the 'bytes' type object. load_address_op(name="builtins.bytes", type=object_rprimitive, src="PyBytes_Type") +# Get the 'bytearray' type object. +load_address_op(name="builtins.bytearray", type=object_rprimitive, src="PyByteArray_Type") + # bytes(obj) function_op( name="builtins.bytes", diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index 0caec05a3ea8..b10eceaa9584 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -48,24 +48,20 @@ def f(s: str, num: int) -> None: def f(s, num): s :: str num :: int - r0 :: object - r1 :: str - r2, r3 :: object - r4, a, r5, b :: bytearray - r6 :: object - r7, c :: bytearray + r0, r1 :: object + r2, a, r3, b :: bytearray + r4 :: object + r5, c :: bytearray L0: - r0 = builtins :: module - r1 = 'bytearray' - r2 = CPyObject_GetAttr(r0, r1) - r3 = PyObject_Vectorcall(r2, 0, 0, 0) - r4 = cast(bytearray, r3) - a = r4 - r5 = PyByteArray_FromObject(s) - b = r5 - r6 = box(int, num) - r7 = PyByteArray_FromObject(r6) - c = r7 + r0 = load_address PyByteArray_Type + r1 = PyObject_Vectorcall(r0, 0, 0, 0) + r2 = cast(bytearray, r1) + a = r2 + r3 = PyByteArray_FromObject(s) + b = r3 + r4 = box(int, num) + r5 = PyByteArray_FromObject(r4) + c = r5 return 1 [case testBytesEquality] From b6b7c7bda41fc25d9252693bae1c0921e7a28010 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 8 Jan 2026 17:39:05 +0000 Subject: [PATCH 03/10] Add test --- mypyc/test-data/run-bytes.test | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/mypyc/test-data/run-bytes.test b/mypyc/test-data/run-bytes.test index f5eb6abfe234..b6bff560988e 100644 --- a/mypyc/test-data/run-bytes.test +++ b/mypyc/test-data/run-bytes.test @@ -276,16 +276,30 @@ def test_basics() -> None: assert len(brr1) == 3 assert len(brr2) == 4 -def f(b: bytes) -> str: +def test_bytearray_type_object() -> None: + b = bytearray() + assert type(b) is bytearray + +def fb(b: bytes) -> str: return "xy" def test_bytearray_passed_into_bytes() -> None: brr1: Any = bytearray() with assertRaises(TypeError, "bytes object expected; got bytearray"): - f(brr1) + fb(brr1) with assertRaises(TypeError, "bytes object expected; got bytearray"): b: bytes = brr1 +def fba(brr: bytearray) -> str: + return "xy" + +def test_bytes_passed_into_bytearray() -> None: + b: Any = b"foo" + with assertRaises(TypeError, "bytearray object expected; got bytes"): + fba(b) + with assertRaises(TypeError, "bytearray object expected; got bytes"): + brr: bytearray = b + [case testBytearraySlicing] def test_bytearray_slicing() -> None: b = bytearray(b'abcdefg') From 264bb55b0b0f1771015a08db2788f4500841b7e3 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Thu, 8 Jan 2026 17:51:07 +0000 Subject: [PATCH 04/10] Update docs --- mypyc/doc/bytearray_operations.rst | 13 +++++++++++++ mypyc/doc/index.rst | 1 + mypyc/doc/using_type_annotations.rst | 3 +++ 3 files changed, 17 insertions(+) create mode 100644 mypyc/doc/bytearray_operations.rst diff --git a/mypyc/doc/bytearray_operations.rst b/mypyc/doc/bytearray_operations.rst new file mode 100644 index 000000000000..3ee242b5648b --- /dev/null +++ b/mypyc/doc/bytearray_operations.rst @@ -0,0 +1,13 @@ +.. _bytearray-ops: + +Native bytearray operations +============================ + +These ``bytearray`` operations have fast, optimized implementations. Other +bytearray operations use generic implementations that are often slower. + +Construction +------------ + +* ``bytearray()`` +* ``bytearray(x)`` diff --git a/mypyc/doc/index.rst b/mypyc/doc/index.rst index 094e0f8cd9b8..004ead0f4791 100644 --- a/mypyc/doc/index.rst +++ b/mypyc/doc/index.rst @@ -37,6 +37,7 @@ generate fast code. float_operations str_operations bytes_operations + bytearray_operations list_operations dict_operations set_operations diff --git a/mypyc/doc/using_type_annotations.rst b/mypyc/doc/using_type_annotations.rst index dc0b04a974fd..d010292805fc 100644 --- a/mypyc/doc/using_type_annotations.rst +++ b/mypyc/doc/using_type_annotations.rst @@ -37,11 +37,14 @@ implementations: * ``float`` (:ref:`native operations `) * ``bool`` (:ref:`native operations `) * ``str`` (:ref:`native operations `) +* ``bytes`` (:ref:`native operations `) +* ``bytearray`` (:ref:`native operations `) * ``list[T]`` (:ref:`native operations `) * ``dict[K, V]`` (:ref:`native operations `) * ``set[T]`` (:ref:`native operations `) * ``tuple[T, ...]`` (variable-length tuple; :ref:`native operations `) * ``None`` +* ``range`` The link after each type lists all supported native, optimized operations for the type. You can use all operations supported by From a5548e9d5b84fc720fd9b59d96ce4afd4b90b9a4 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 9 Jan 2026 10:10:49 +0000 Subject: [PATCH 05/10] Move bytearray primitives to a separate file --- mypyc/irbuild/specialize.py | 3 ++- mypyc/primitives/bytearray_ops.py | 28 ++++++++++++++++++++++++++++ mypyc/primitives/bytes_ops.py | 24 +----------------------- mypyc/primitives/registry.py | 1 + 4 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 mypyc/primitives/bytearray_ops.py diff --git a/mypyc/irbuild/specialize.py b/mypyc/irbuild/specialize.py index c0ed5f9f69da..785a0a7ac61f 100644 --- a/mypyc/irbuild/specialize.py +++ b/mypyc/irbuild/specialize.py @@ -94,7 +94,8 @@ join_formatted_strings, tokenizer_format_call, ) -from mypyc.primitives.bytes_ops import isinstance_bytearray, isinstance_bytes +from mypyc.primitives.bytearray_ops import isinstance_bytearray +from mypyc.primitives.bytes_ops import isinstance_bytes from mypyc.primitives.dict_ops import ( dict_items_op, dict_keys_op, diff --git a/mypyc/primitives/bytearray_ops.py b/mypyc/primitives/bytearray_ops.py new file mode 100644 index 000000000000..14ad190167b4 --- /dev/null +++ b/mypyc/primitives/bytearray_ops.py @@ -0,0 +1,28 @@ +"""Primitive bytearray ops.""" + +from __future__ import annotations + +from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER +from mypyc.ir.rtypes import bit_rprimitive, bytearray_rprimitive, object_rprimitive +from mypyc.primitives.registry import function_op, load_address_op + +# Get the 'bytearray' type object. +load_address_op(name="builtins.bytearray", type=object_rprimitive, src="PyByteArray_Type") + +# bytearray(obj) +function_op( + name="builtins.bytearray", + arg_types=[object_rprimitive], + return_type=bytearray_rprimitive, + c_function_name="PyByteArray_FromObject", + error_kind=ERR_MAGIC, +) + +# translate isinstance(obj, bytearray) +isinstance_bytearray = function_op( + name="builtins.isinstance", + arg_types=[object_rprimitive], + return_type=bit_rprimitive, + c_function_name="PyByteArray_Check", + error_kind=ERR_NEVER, +) diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index 79601b857ec6..53e7832c3998 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -1,4 +1,4 @@ -"""Primitive bytes and bytearray ops.""" +"""Primitive bytes ops.""" from __future__ import annotations @@ -8,7 +8,6 @@ RUnion, bit_rprimitive, bool_rprimitive, - bytearray_rprimitive, bytes_rprimitive, c_int_rprimitive, c_pyssize_t_rprimitive, @@ -30,9 +29,6 @@ # Get the 'bytes' type object. load_address_op(name="builtins.bytes", type=object_rprimitive, src="PyBytes_Type") -# Get the 'bytearray' type object. -load_address_op(name="builtins.bytearray", type=object_rprimitive, src="PyByteArray_Type") - # bytes(obj) function_op( name="builtins.bytes", @@ -51,24 +47,6 @@ error_kind=ERR_NEVER, ) -# bytearray(obj) -function_op( - name="builtins.bytearray", - arg_types=[object_rprimitive], - return_type=bytearray_rprimitive, - c_function_name="PyByteArray_FromObject", - error_kind=ERR_MAGIC, -) - -# translate isinstance(obj, bytearray) -isinstance_bytearray = function_op( - name="builtins.isinstance", - arg_types=[object_rprimitive], - return_type=bit_rprimitive, - c_function_name="PyByteArray_Check", - error_kind=ERR_NEVER, -) - # bytes ==/!= (return -1/0/1) bytes_compare = custom_op( arg_types=[bytes_rprimitive, bytes_rprimitive], diff --git a/mypyc/primitives/registry.py b/mypyc/primitives/registry.py index a59599f693c4..0e3032719ca1 100644 --- a/mypyc/primitives/registry.py +++ b/mypyc/primitives/registry.py @@ -388,6 +388,7 @@ def load_address_op(name: str, type: RType, src: str) -> LoadAddressDescription: # Import various modules that set up global state. +import mypyc.primitives.bytearray_ops import mypyc.primitives.bytes_ops import mypyc.primitives.dict_ops import mypyc.primitives.float_ops From f99065e50e5487132af5a3af347d2ff785a73f45 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 9 Jan 2026 10:20:41 +0000 Subject: [PATCH 06/10] Add primitive for BytesWriter write with bytearray arg --- mypyc/primitives/librt_strings_ops.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mypyc/primitives/librt_strings_ops.py b/mypyc/primitives/librt_strings_ops.py index ac1aa7da1fbe..a00189e1cc8d 100644 --- a/mypyc/primitives/librt_strings_ops.py +++ b/mypyc/primitives/librt_strings_ops.py @@ -3,6 +3,7 @@ from mypyc.ir.rtypes import ( bool_rprimitive, bytes_rprimitive, + bytearray_rprimitive, bytes_writer_rprimitive, int64_rprimitive, none_rprimitive, @@ -42,6 +43,16 @@ dependencies=[LIBRT_STRINGS, BYTES_WRITER_EXTRA_OPS], ) +method_op( + name="write", + arg_types=[bytes_writer_rprimitive, bytearray_rprimitive], + return_type=none_rprimitive, + c_function_name="CPyBytesWriter_Write", + error_kind=ERR_MAGIC, + experimental=True, + dependencies=[LIBRT_STRINGS, BYTES_WRITER_EXTRA_OPS], +) + method_op( name="append", arg_types=[bytes_writer_rprimitive, uint8_rprimitive], From 16f4b2cb9e9db74c7c30aed2ccb71f3159c287f1 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 9 Jan 2026 10:21:25 +0000 Subject: [PATCH 07/10] Add primitive for bytearray() --- mypyc/ir/deps.py | 1 + mypyc/lib-rt/bytearray_extra_ops.c | 5 +++++ mypyc/lib-rt/bytearray_extra_ops.h | 10 ++++++++++ mypyc/primitives/bytearray_ops.py | 24 ++++++++++++++++++++---- mypyc/test-data/irbuild-bytes.test | 23 ++++++++++------------- mypyc/test-data/run-bytes.test | 4 ++++ 6 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 mypyc/lib-rt/bytearray_extra_ops.c create mode 100644 mypyc/lib-rt/bytearray_extra_ops.h diff --git a/mypyc/ir/deps.py b/mypyc/ir/deps.py index 9aee5d1b33e4..249b456e2c85 100644 --- a/mypyc/ir/deps.py +++ b/mypyc/ir/deps.py @@ -51,3 +51,4 @@ def get_header(self) -> str: BYTES_EXTRA_OPS: Final = SourceDep("bytes_extra_ops.c") BYTES_WRITER_EXTRA_OPS: Final = SourceDep("byteswriter_extra_ops.c") +BYTEARRAY_EXTRA_OPS: Final = SourceDep("bytearray_extra_ops.c") diff --git a/mypyc/lib-rt/bytearray_extra_ops.c b/mypyc/lib-rt/bytearray_extra_ops.c new file mode 100644 index 000000000000..a956f8c76f1f --- /dev/null +++ b/mypyc/lib-rt/bytearray_extra_ops.c @@ -0,0 +1,5 @@ +#include "bytearray_extra_ops.h" + +PyObject *CPyByteArray_New(void) { + return PyByteArray_FromStringAndSize(NULL, 0); +} diff --git a/mypyc/lib-rt/bytearray_extra_ops.h b/mypyc/lib-rt/bytearray_extra_ops.h new file mode 100644 index 000000000000..41f17be3ab96 --- /dev/null +++ b/mypyc/lib-rt/bytearray_extra_ops.h @@ -0,0 +1,10 @@ +#ifndef MYPYC_BYTEARRAY_EXTRA_OPS_H +#define MYPYC_BYTEARRAY_EXTRA_OPS_H + +#include +#include "CPy.h" + +// Construct empty bytearray +PyObject *CPyByteArray_New(void); + +#endif diff --git a/mypyc/primitives/bytearray_ops.py b/mypyc/primitives/bytearray_ops.py index 14ad190167b4..873730f2a7ee 100644 --- a/mypyc/primitives/bytearray_ops.py +++ b/mypyc/primitives/bytearray_ops.py @@ -1,10 +1,16 @@ -"""Primitive bytearray ops.""" +"""Primitive bytearray ops. + +NOTE: Most of these should be added to bytearray_extra_ops.c, which requires the + BYTEARRAY_EXTRA_OPS primitive dependency, since these are used relatively rarely and we + don't want to compile them unless needed. +""" from __future__ import annotations +from mypyc.ir.deps import BYTEARRAY_EXTRA_OPS from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER from mypyc.ir.rtypes import bit_rprimitive, bytearray_rprimitive, object_rprimitive -from mypyc.primitives.registry import function_op, load_address_op +from mypyc.primitives.registry import function_op, load_address_op, custom_primitive_op # Get the 'bytearray' type object. load_address_op(name="builtins.bytearray", type=object_rprimitive, src="PyByteArray_Type") @@ -16,10 +22,20 @@ return_type=bytearray_rprimitive, c_function_name="PyByteArray_FromObject", error_kind=ERR_MAGIC, + dependencies=[BYTEARRAY_EXTRA_OPS], +) + +# bytearray() -- construct empty bytearray +function_op( + name="builtins.bytearray", + arg_types=[], + return_type=bytearray_rprimitive, + c_function_name="CPyByteArray_New", + error_kind=ERR_MAGIC, ) -# translate isinstance(obj, bytearray) -isinstance_bytearray = function_op( +# isinstance(obj, bytearray) +isinstance_bytearray = custom_primitive_op( name="builtins.isinstance", arg_types=[object_rprimitive], return_type=bit_rprimitive, diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index b10eceaa9584..6ec09bedad48 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -48,20 +48,17 @@ def f(s: str, num: int) -> None: def f(s, num): s :: str num :: int - r0, r1 :: object - r2, a, r3, b :: bytearray - r4 :: object - r5, c :: bytearray + r0, a, r1, b :: bytearray + r2 :: object + r3, c :: bytearray L0: - r0 = load_address PyByteArray_Type - r1 = PyObject_Vectorcall(r0, 0, 0, 0) - r2 = cast(bytearray, r1) - a = r2 - r3 = PyByteArray_FromObject(s) - b = r3 - r4 = box(int, num) - r5 = PyByteArray_FromObject(r4) - c = r5 + r0 = CPyByteArray_New() + a = r0 + r1 = PyByteArray_FromObject(s) + b = r1 + r2 = box(int, num) + r3 = PyByteArray_FromObject(r2) + c = r3 return 1 [case testBytesEquality] diff --git a/mypyc/test-data/run-bytes.test b/mypyc/test-data/run-bytes.test index b6bff560988e..89ccfd66d288 100644 --- a/mypyc/test-data/run-bytes.test +++ b/mypyc/test-data/run-bytes.test @@ -260,6 +260,10 @@ from typing import Any from testutil import assertRaises def test_basics() -> None: + brr0 = bytearray() + assert brr0 == bytearray(b'') + assert brr0 == b'' + assert len(brr0) == 0 brr1 = bytearray(3) assert brr1 == bytearray(b'\x00\x00\x00') assert brr1 == b'\x00\x00\x00' From a9728b4a3d967e95e3fc5a07988de829fe17e733 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 9 Jan 2026 10:23:11 +0000 Subject: [PATCH 08/10] Fix doc link --- mypyc/doc/using_type_annotations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/doc/using_type_annotations.rst b/mypyc/doc/using_type_annotations.rst index d010292805fc..4ecc77ab6669 100644 --- a/mypyc/doc/using_type_annotations.rst +++ b/mypyc/doc/using_type_annotations.rst @@ -38,7 +38,7 @@ implementations: * ``bool`` (:ref:`native operations `) * ``str`` (:ref:`native operations `) * ``bytes`` (:ref:`native operations `) -* ``bytearray`` (:ref:`native operations `) +* ``bytearray`` (:ref:`native operations `) * ``list[T]`` (:ref:`native operations `) * ``dict[K, V]`` (:ref:`native operations `) * ``set[T]`` (:ref:`native operations `) From e924ee99f9cfc0186fe860a20e403d1fdcb958ad Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 9 Jan 2026 10:23:26 +0000 Subject: [PATCH 09/10] Lint --- mypyc/ir/rtypes.py | 4 +++- mypyc/primitives/bytearray_ops.py | 2 +- mypyc/primitives/librt_strings_ops.py | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mypyc/ir/rtypes.py b/mypyc/ir/rtypes.py index 047690267b34..20845a10177f 100644 --- a/mypyc/ir/rtypes.py +++ b/mypyc/ir/rtypes.py @@ -505,7 +505,9 @@ def __hash__(self) -> int: bytes_rprimitive: Final = RPrimitive("builtins.bytes", is_unboxed=False, is_refcounted=True) # Python bytearray object. -bytearray_rprimitive: Final = RPrimitive("builtins.bytearray", is_unboxed=False, is_refcounted=True) +bytearray_rprimitive: Final = RPrimitive( + "builtins.bytearray", is_unboxed=False, is_refcounted=True +) # Tuple of an arbitrary length (corresponds to Tuple[t, ...], with # explicit '...'). diff --git a/mypyc/primitives/bytearray_ops.py b/mypyc/primitives/bytearray_ops.py index 873730f2a7ee..3870b0ffbb46 100644 --- a/mypyc/primitives/bytearray_ops.py +++ b/mypyc/primitives/bytearray_ops.py @@ -10,7 +10,7 @@ from mypyc.ir.deps import BYTEARRAY_EXTRA_OPS from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER from mypyc.ir.rtypes import bit_rprimitive, bytearray_rprimitive, object_rprimitive -from mypyc.primitives.registry import function_op, load_address_op, custom_primitive_op +from mypyc.primitives.registry import custom_primitive_op, function_op, load_address_op # Get the 'bytearray' type object. load_address_op(name="builtins.bytearray", type=object_rprimitive, src="PyByteArray_Type") diff --git a/mypyc/primitives/librt_strings_ops.py b/mypyc/primitives/librt_strings_ops.py index a00189e1cc8d..ffe37b5c099a 100644 --- a/mypyc/primitives/librt_strings_ops.py +++ b/mypyc/primitives/librt_strings_ops.py @@ -2,8 +2,8 @@ from mypyc.ir.ops import ERR_MAGIC, ERR_NEVER from mypyc.ir.rtypes import ( bool_rprimitive, - bytes_rprimitive, bytearray_rprimitive, + bytes_rprimitive, bytes_writer_rprimitive, int64_rprimitive, none_rprimitive, From f34a1d360fe482aa43542f630f7439f4861cfecc Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 9 Jan 2026 11:50:59 +0000 Subject: [PATCH 10/10] Fix op dependencies --- mypyc/primitives/bytearray_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/primitives/bytearray_ops.py b/mypyc/primitives/bytearray_ops.py index 3870b0ffbb46..2128a6d48d5c 100644 --- a/mypyc/primitives/bytearray_ops.py +++ b/mypyc/primitives/bytearray_ops.py @@ -22,7 +22,6 @@ return_type=bytearray_rprimitive, c_function_name="PyByteArray_FromObject", error_kind=ERR_MAGIC, - dependencies=[BYTEARRAY_EXTRA_OPS], ) # bytearray() -- construct empty bytearray @@ -32,6 +31,7 @@ return_type=bytearray_rprimitive, c_function_name="CPyByteArray_New", error_kind=ERR_MAGIC, + dependencies=[BYTEARRAY_EXTRA_OPS], ) # isinstance(obj, bytearray)