From 631df6c3c8709a5caaf5ae1089429463a1585a1b Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 01/23] [mypyc] feat: new primitives for `bytes.rjust` and `bytes.ljust` --- mypyc/lib-rt/bytes_ops.c | 49 ++++++++++++++++++++++ mypyc/primitives/bytes_ops.py | 18 ++++++++ mypyc/test-data/irbuild-bytes.test | 66 ++++++++++++++++++++++++++++++ mypyc/test-data/run-bytes.test | 38 +++++++++++++++++ 4 files changed, 171 insertions(+) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index 6ff34b021a9a..6983ba18875f 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -4,6 +4,7 @@ #include #include "CPy.h" +#include // Returns -1 on error, 0 on inequality, 1 on equality. // @@ -162,3 +163,51 @@ CPyTagged CPyBytes_Ord(PyObject *obj) { PyErr_SetString(PyExc_TypeError, "ord() expects a character"); return CPY_INT_TAG; } + +PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { + if (!PyBytes_Check(self)) { + PyErr_SetString(PyExc_TypeError, "self must be bytes"); + return NULL; + } + if (!PyBytes_Check(fillbyte) || PyBytes_Size(fillbyte) != 1) { + PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); + return NULL; + } + Py_ssize_t len = PyBytes_Size(self); + if (width <= len) { + return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + } + char fill = PyBytes_AsString(fillbyte)[0]; + Py_ssize_t pad = width - len; + PyObject *result = PyBytes_FromStringAndSize(NULL, width); + if (!result) return NULL; + char *res_buf = PyBytes_AsString(result); + memset(res_buf, fill, pad); + memcpy(res_buf + pad, PyBytes_AsString(self), len); + return result; +} + +PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { + if (!PyBytes_Check(self)) { + PyErr_SetString(PyExc_TypeError, "self must be bytes"); + return NULL; + } + if (!PyBytes_Check(fillbyte) || PyBytes_Size(fillbyte) != 1) { + PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); + return NULL; + } + Py_ssize_t len = PyBytes_Size(self); + if (width <= len) { + return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + } + char fill = PyBytes_AsString(fillbyte)[0]; + Py_ssize_t pad = width - len; + PyObject *result = PyBytes_FromStringAndSize(NULL, width); + if (!result) return NULL; + char *res_buf = PyBytes_AsString(result); + memcpy(res_buf, PyBytes_AsString(self), len); + memset(res_buf + len, fill, pad); + return result; +} + +// ... existing code ... diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index c88e89d1a2ba..88155110fc2d 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -126,3 +126,21 @@ c_function_name="CPyBytes_Ord", error_kind=ERR_MAGIC, ) + +# bytes.rjust(width, fillbyte=b' ') +method_op( + name="rjust", + arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], + return_type=bytes_rprimitive, + c_function_name="CPyBytes_Rjust", + error_kind=ERR_MAGIC, +) + +# bytes.ljust(width, fillbyte=b' ') +method_op( + name="ljust", + arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], + return_type=bytes_rprimitive, + c_function_name="CPyBytes_Ljust", + error_kind=ERR_MAGIC, +) diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index 476c5ac59f48..f79dffa69809 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -185,3 +185,69 @@ L0: r10 = CPyBytes_Build(2, var, r9) b4 = r10 return 1 + +[case testBytesRjustDefault] +def f(b: bytes) -> bytes: + return b.rjust(6) +[out] +def f(b): + b :: bytes + r0 :: bytes +L0: + r0 = b.rjust(6, b' ') + return r0 + +[case testBytesRjustCustom] +def f(b: bytes) -> bytes: + return b.rjust(8, b'0') +[out] +def f(b): + b :: bytes + r0 :: bytes +L0: + r0 = b.rjust(8, b'0') + return r0 + +[case testBytesLjustDefault] +def f(b: bytes) -> bytes: + return b.ljust(7) +[out] +def f(b): + b :: bytes + r0 :: bytes +L0: + r0 = b.ljust(7, b' ') + return r0 + +[case testBytesLjustCustom] +def f(b: bytes) -> bytes: + return b.ljust(10, b'_') +[out] +def f(b): + b :: bytes + r0 :: bytes +L0: + r0 = b.ljust(10, b'_') + return r0 + +[case testBytesRjustNoPad] +def f(b: bytes) -> bytes: + return b.rjust(2) +[out] +def f(b): + b :: bytes + r0 :: bytes +L0: + r0 = b.rjust(2, b' ') + return r0 + +[case testBytesLjustNoPad] +def f(b: bytes) -> bytes: + return b.ljust(1) +[out] +def f(b): + b :: bytes + r0 :: bytes +L0: + r0 = b.ljust(1, b' ') + return r0 diff --git a/mypyc/test-data/run-bytes.test b/mypyc/test-data/run-bytes.test index 5a285320c849..5d53402d2e33 100644 --- a/mypyc/test-data/run-bytes.test +++ b/mypyc/test-data/run-bytes.test @@ -374,3 +374,41 @@ class subbytearray(bytearray): [file userdefinedbytes.py] class bytes: pass + +[case testBytesRjustLjust] +def rjust_bytes(b: bytes, width: int, fill: bytes = b' ') -> bytes: + return b.rjust(width, fill) + +def ljust_bytes(b: bytes, width: int, fill: bytes = b' ') -> bytes: + return b.ljust(width, fill) + +def test_rjust_with_default_fill() -> None: + assert rjust_bytes(b'abc', 6) == b' abc' + assert rjust_bytes(b'abc', 3) == b'abc' + assert rjust_bytes(b'abc', 2) == b'abc' + assert rjust_bytes(b'', 4) == b' ' + +def test_rjust_with_custom_fill() -> None: + assert rjust_bytes(b'abc', 6, b'0') == b'000abc' + assert rjust_bytes(b'abc', 5, b'_') == b'__abc' + assert rjust_bytes(b'abc', 3, b'X') == b'abc' + +def test_ljust_with_default_fill() -> None: + assert ljust_bytes(b'abc', 6) == b'abc ' + assert ljust_bytes(b'abc', 3) == b'abc' + assert ljust_bytes(b'abc', 2) == b'abc' + assert ljust_bytes(b'', 4) == b' ' + +def test_ljust_with_custom_fill() -> None: + assert ljust_bytes(b'abc', 6, b'0') == b'abc000' + assert ljust_bytes(b'abc', 5, b'_') == b'abc__' + assert ljust_bytes(b'abc', 3, b'X') == b'abc' + +def test_edge_cases() -> None: + assert rjust_bytes(b'abc', 0) == b'abc' + assert ljust_bytes(b'abc', 0) == b'abc' + # fillbyte must be length 1 + with assertRaises(TypeError): + rjust_bytes(b'abc', 5, b'') + with assertRaises(TypeError): + ljust_bytes(b'abc', 5, b'12') From d94b780278b5999c94f523aa33767b9998446fac Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 02/23] fix: tests --- mypyc/test-data/fixtures/ir.py | 2 ++ mypyc/test-data/run-bytes.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index c041c661741c..079e913d50e9 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -174,6 +174,8 @@ def __getitem__(self, i: slice) -> bytes: ... def join(self, x: Iterable[object]) -> bytes: ... def decode(self, encoding: str=..., errors: str=...) -> str: ... def __iter__(self) -> Iterator[int]: ... + def ljust(self, width: int, fillchar: bytes) -> bytes: ... + def rjust(self, width: int, fillchar: bytes) -> bytes: ... class bytearray: @overload diff --git a/mypyc/test-data/run-bytes.test b/mypyc/test-data/run-bytes.test index 5d53402d2e33..c327ff73c841 100644 --- a/mypyc/test-data/run-bytes.test +++ b/mypyc/test-data/run-bytes.test @@ -376,6 +376,8 @@ class bytes: pass [case testBytesRjustLjust] +from testutil import assertRaises + def rjust_bytes(b: bytes, width: int, fill: bytes = b' ') -> bytes: return b.rjust(width, fill) From 6bfb7d52192d663b409a5d34c504512fd7999af6 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 03/23] Update bytes_ops.c --- mypyc/lib-rt/bytes_ops.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index 6983ba18875f..554b9a58b6e1 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -209,5 +209,3 @@ PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { memset(res_buf + len, fill, pad); return result; } - -// ... existing code ... From affc1ba71966056035671b043673d32c44253c7c Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 04/23] fix: tests --- mypyc/test-data/fixtures/ir.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index 079e913d50e9..f90d15e24995 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -174,8 +174,8 @@ def __getitem__(self, i: slice) -> bytes: ... def join(self, x: Iterable[object]) -> bytes: ... def decode(self, encoding: str=..., errors: str=...) -> str: ... def __iter__(self) -> Iterator[int]: ... - def ljust(self, width: int, fillchar: bytes) -> bytes: ... - def rjust(self, width: int, fillchar: bytes) -> bytes: ... + def ljust(self, width: int, fillchar: bytes | bytearray = b" ") -> bytes: ... + def rjust(self, width: int, fillchar: bytes | bytearray = b" ") -> bytes: ... class bytearray: @overload From 9e75fe1d3c8d9e2441704e7169f21d313aa2fb90 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 05/23] add headers --- mypyc/lib-rt/CPy.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 8cd141545bbb..75dedcc88982 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -770,6 +770,8 @@ CPyTagged CPyBytes_GetItem(PyObject *o, CPyTagged index); PyObject *CPyBytes_Concat(PyObject *a, PyObject *b); PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter); CPyTagged CPyBytes_Ord(PyObject *obj); +PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte); +PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte); int CPyBytes_Compare(PyObject *left, PyObject *right); From fa8645d3acb012c1d9c63b4ac3dddabfea47c10d Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 06/23] deatil asserts --- mypyc/test-data/run-bytes.test | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/mypyc/test-data/run-bytes.test b/mypyc/test-data/run-bytes.test index c327ff73c841..3b81814d056d 100644 --- a/mypyc/test-data/run-bytes.test +++ b/mypyc/test-data/run-bytes.test @@ -385,30 +385,30 @@ def ljust_bytes(b: bytes, width: int, fill: bytes = b' ') -> bytes: return b.ljust(width, fill) def test_rjust_with_default_fill() -> None: - assert rjust_bytes(b'abc', 6) == b' abc' - assert rjust_bytes(b'abc', 3) == b'abc' - assert rjust_bytes(b'abc', 2) == b'abc' - assert rjust_bytes(b'', 4) == b' ' + assert rjust_bytes(b'abc', 6) == b' abc', rjust_bytes(b'abc', 6) + assert rjust_bytes(b'abc', 3) == b'abc', rjust_bytes(b'abc', 3) + assert rjust_bytes(b'abc', 2) == b'abc', rjust_bytes(b'abc', 2) + assert rjust_bytes(b'', 4) == b' ', rjust_bytes(b'', 4) def test_rjust_with_custom_fill() -> None: - assert rjust_bytes(b'abc', 6, b'0') == b'000abc' - assert rjust_bytes(b'abc', 5, b'_') == b'__abc' - assert rjust_bytes(b'abc', 3, b'X') == b'abc' + assert rjust_bytes(b'abc', 6, b'0') == b'000abc', rjust_bytes(b'abc', 6, b'0') + assert rjust_bytes(b'abc', 5, b'_') == b'__abc', rjust_bytes(b'abc', 5, b'_') + assert rjust_bytes(b'abc', 3, b'X') == b'abc', rjust_bytes(b'abc', 3, b'X') def test_ljust_with_default_fill() -> None: - assert ljust_bytes(b'abc', 6) == b'abc ' - assert ljust_bytes(b'abc', 3) == b'abc' - assert ljust_bytes(b'abc', 2) == b'abc' - assert ljust_bytes(b'', 4) == b' ' + assert ljust_bytes(b'abc', 6) == b'abc ', ljust_bytes(b'abc', 6) + assert ljust_bytes(b'abc', 3) == b'abc', ljust_bytes(b'abc', 3) + assert ljust_bytes(b'abc', 2) == b'abc', ljust_bytes(b'abc', 2) + assert ljust_bytes(b'', 4) == b' ', ljust_bytes(b'', 4) def test_ljust_with_custom_fill() -> None: - assert ljust_bytes(b'abc', 6, b'0') == b'abc000' - assert ljust_bytes(b'abc', 5, b'_') == b'abc__' - assert ljust_bytes(b'abc', 3, b'X') == b'abc' + assert ljust_bytes(b'abc', 6, b'0') == b'abc000', ljust_bytes(b'abc', 6, b'0') + assert ljust_bytes(b'abc', 5, b'_') == b'abc__', ljust_bytes(b'abc', 5, b'_') + assert ljust_bytes(b'abc', 3, b'X') == b'abc', ljust_bytes(b'abc', 3, b'X') def test_edge_cases() -> None: - assert rjust_bytes(b'abc', 0) == b'abc' - assert ljust_bytes(b'abc', 0) == b'abc' + assert rjust_bytes(b'abc', 0) == b'abc', rjust_bytes(b'abc', 0) + assert ljust_bytes(b'abc', 0) == b'abc', ljust_bytes(b'abc', 0) # fillbyte must be length 1 with assertRaises(TypeError): rjust_bytes(b'abc', 5, b'') From 143973cf51b83c000f6b9b8c32115d9047011850 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 07/23] fix ir --- mypyc/test-data/irbuild-bytes.test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index f79dffa69809..6acd2e8f0d65 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -202,11 +202,11 @@ def f(b: bytes) -> bytes: return b.rjust(8, b'0') [out] def f(b): - b :: bytes - r0 :: bytes + b, r0 :: bytes L0: - r0 = b.rjust(8, b'0') - return r0 + r0 = b'_' + r1 = CPyBytes_Rjust(b, 20, r0) + return r1 [case testBytesLjustDefault] def f(b: bytes) -> bytes: @@ -224,11 +224,11 @@ def f(b: bytes) -> bytes: return b.ljust(10, b'_') [out] def f(b): - b :: bytes - r0 :: bytes + b, r0 :: bytes L0: - r0 = b.ljust(10, b'_') - return r0 + r0 = b'_' + r1 = CPyBytes_Ljust(b, 20, r0) + return r1 [case testBytesRjustNoPad] def f(b: bytes) -> bytes: From 5bb57c332fb27b80558f5020ffe6d63e1fe5d928 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 08/23] fix run tests --- mypyc/lib-rt/bytes_ops.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index 554b9a58b6e1..9de71777c622 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -173,6 +173,7 @@ PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } + width = width << 1 Py_ssize_t len = PyBytes_Size(self); if (width <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); @@ -196,6 +197,7 @@ PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } + width = width << 1; Py_ssize_t len = PyBytes_Size(self); if (width <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); From 2d81bd8b6cbeb55e2c9435144dedcd80d22e38ae Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 09/23] Update bytes_ops.c --- mypyc/lib-rt/bytes_ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index 9de71777c622..d01fb164ecc9 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -173,7 +173,7 @@ PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } - width = width << 1 + width = width << 1; Py_ssize_t len = PyBytes_Size(self); if (width <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); From 25a35b3869286dbe013f6e4f6841befbb04af817 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 10/23] Update bytes_ops.py --- mypyc/primitives/bytes_ops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index 88155110fc2d..0c3eb4ed371e 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -130,7 +130,7 @@ # bytes.rjust(width, fillbyte=b' ') method_op( name="rjust", - arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], + arg_types=[bytes_rprimitive, c_pyssize_t_rprimitive, bytes_rprimitive], return_type=bytes_rprimitive, c_function_name="CPyBytes_Rjust", error_kind=ERR_MAGIC, @@ -139,7 +139,7 @@ # bytes.ljust(width, fillbyte=b' ') method_op( name="ljust", - arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], + arg_types=[bytes_rprimitive, c_pyssize_t_rprimitive, bytes_rprimitive], return_type=bytes_rprimitive, c_function_name="CPyBytes_Ljust", error_kind=ERR_MAGIC, From 595d9189bc9d9d9dee4e3a31ff749eaf74c444fe Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 11/23] Update bytes_ops.c --- mypyc/lib-rt/bytes_ops.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index d01fb164ecc9..554b9a58b6e1 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -173,7 +173,6 @@ PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } - width = width << 1; Py_ssize_t len = PyBytes_Size(self); if (width <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); @@ -197,7 +196,6 @@ PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } - width = width << 1; Py_ssize_t len = PyBytes_Size(self); if (width <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); From 28feb665077f2818aa1b6706f17a4adddd5c3bf5 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 12/23] fix pyssizet --- mypyc/lib-rt/bytes_ops.c | 18 ++++++++++-------- mypyc/primitives/bytes_ops.py | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index 554b9a58b6e1..b2182ccd9116 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -164,7 +164,7 @@ CPyTagged CPyBytes_Ord(PyObject *obj) { return CPY_INT_TAG; } -PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { +PyObject *CPyBytes_Rjust(PyObject *self, CPyTagged width, PyObject *fillbyte) { if (!PyBytes_Check(self)) { PyErr_SetString(PyExc_TypeError, "self must be bytes"); return NULL; @@ -173,13 +173,14 @@ PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } + Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width) Py_ssize_t len = PyBytes_Size(self); - if (width <= len) { + if (width_size_t <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); } char fill = PyBytes_AsString(fillbyte)[0]; - Py_ssize_t pad = width - len; - PyObject *result = PyBytes_FromStringAndSize(NULL, width); + Py_ssize_t pad = width_size_t - len; + PyObject *result = PyBytes_FromStringAndSize(NULL, width_size_t); if (!result) return NULL; char *res_buf = PyBytes_AsString(result); memset(res_buf, fill, pad); @@ -187,7 +188,7 @@ PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { return result; } -PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { +PyObject *CPyBytes_Ljust(PyObject *self, CPyTagged width, PyObject *fillbyte) { if (!PyBytes_Check(self)) { PyErr_SetString(PyExc_TypeError, "self must be bytes"); return NULL; @@ -196,13 +197,14 @@ PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } + Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width) Py_ssize_t len = PyBytes_Size(self); - if (width <= len) { + if (width_size_t <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); } char fill = PyBytes_AsString(fillbyte)[0]; - Py_ssize_t pad = width - len; - PyObject *result = PyBytes_FromStringAndSize(NULL, width); + Py_ssize_t pad = width_size_t - len; + PyObject *result = PyBytes_FromStringAndSize(NULL, width_size_t); if (!result) return NULL; char *res_buf = PyBytes_AsString(result); memcpy(res_buf, PyBytes_AsString(self), len); diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index 0c3eb4ed371e..88155110fc2d 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -130,7 +130,7 @@ # bytes.rjust(width, fillbyte=b' ') method_op( name="rjust", - arg_types=[bytes_rprimitive, c_pyssize_t_rprimitive, bytes_rprimitive], + arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], return_type=bytes_rprimitive, c_function_name="CPyBytes_Rjust", error_kind=ERR_MAGIC, @@ -139,7 +139,7 @@ # bytes.ljust(width, fillbyte=b' ') method_op( name="ljust", - arg_types=[bytes_rprimitive, c_pyssize_t_rprimitive, bytes_rprimitive], + arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], return_type=bytes_rprimitive, c_function_name="CPyBytes_Ljust", error_kind=ERR_MAGIC, From 47ab577cd08e3ac0134e03f293134a37ac2fd7e8 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 13/23] fix headers --- mypyc/lib-rt/CPy.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 75dedcc88982..74fb8d382330 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -770,8 +770,8 @@ CPyTagged CPyBytes_GetItem(PyObject *o, CPyTagged index); PyObject *CPyBytes_Concat(PyObject *a, PyObject *b); PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter); CPyTagged CPyBytes_Ord(PyObject *obj); -PyObject *CPyBytes_Ljust(PyObject *self, Py_ssize_t width, PyObject *fillbyte); -PyObject *CPyBytes_Rjust(PyObject *self, Py_ssize_t width, PyObject *fillbyte); +PyObject *CPyBytes_Ljust(PyObject *self, CPyTagged width, PyObject *fillbyte); +PyObject *CPyBytes_Rjust(PyObject *self, CPyTagged width, PyObject *fillbyte); int CPyBytes_Compare(PyObject *left, PyObject *right); From 8761402fbb6401c7d793427c5248d180fb45801b Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 14/23] fix: ; --- mypyc/lib-rt/bytes_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index b2182ccd9116..b2dacd596395 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -173,7 +173,7 @@ PyObject *CPyBytes_Rjust(PyObject *self, CPyTagged width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } - Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width) + Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); Py_ssize_t len = PyBytes_Size(self); if (width_size_t <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); @@ -197,7 +197,7 @@ PyObject *CPyBytes_Ljust(PyObject *self, CPyTagged width, PyObject *fillbyte) { PyErr_SetString(PyExc_TypeError, "fillbyte must be a single byte"); return NULL; } - Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width) + Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); Py_ssize_t len = PyBytes_Size(self); if (width_size_t <= len) { return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); From d982f3bab42197e77eaf1002363356dc96919504 Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 15/23] fix ir --- mypyc/test-data/irbuild-bytes.test | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index 6acd2e8f0d65..1d1dbd58890c 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -202,10 +202,10 @@ def f(b: bytes) -> bytes: return b.rjust(8, b'0') [out] def f(b): - b, r0 :: bytes + b, r0, r1 :: bytes L0: - r0 = b'_' - r1 = CPyBytes_Rjust(b, 20, r0) + r0 = b'0' + r1 = CPyBytes_Rjust(b, 16, r0) return r1 [case testBytesLjustDefault] @@ -224,7 +224,7 @@ def f(b: bytes) -> bytes: return b.ljust(10, b'_') [out] def f(b): - b, r0 :: bytes + b, r0, r1 :: bytes L0: r0 = b'_' r1 = CPyBytes_Ljust(b, 20, r0) From 3263499da4570ba099801c701d99e33aee23584f Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 16/23] drop dupe tests --- mypyc/test-data/irbuild-bytes.test | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index 1d1dbd58890c..58cc73b4b2e5 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -229,25 +229,3 @@ L0: r0 = b'_' r1 = CPyBytes_Ljust(b, 20, r0) return r1 - -[case testBytesRjustNoPad] -def f(b: bytes) -> bytes: - return b.rjust(2) -[out] -def f(b): - b :: bytes - r0 :: bytes -L0: - r0 = b.rjust(2, b' ') - return r0 - -[case testBytesLjustNoPad] -def f(b: bytes) -> bytes: - return b.ljust(1) -[out] -def f(b): - b :: bytes - r0 :: bytes -L0: - r0 = b.ljust(1, b' ') - return r0 From 5da71b4eca042be1456aba70b493d1f7ca180d96 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 17/23] Update bytes_ops.c --- mypyc/lib-rt/bytes_ops.c | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index b2dacd596395..652a859d057d 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -164,6 +164,31 @@ CPyTagged CPyBytes_Ord(PyObject *obj) { return CPY_INT_TAG; } + +PyObject *CPyBytes_RjustDefaultFill(PyObject *self, CPyTagged width) { + if (!PyBytes_Check(self)) { + PyErr_SetString(PyExc_TypeError, "self must be bytes"); + return NULL; + } + Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); + Py_ssize_t len = PyBytes_Size(self); + if (width_size_t <= len) { + return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + } + // should this be a constant? + PyObject *fillbyte = PyBytes_FromStringAndSize(" ", 1); + // can we optimize out the above line and the below line? + char fill = PyBytes_AsString(fillbyte)[0]; + Py_ssize_t pad = width_size_t - len; + PyObject *result = PyBytes_FromStringAndSize(NULL, width_size_t); + if (!result) return NULL; + char *res_buf = PyBytes_AsString(result); + memset(res_buf, fill, pad); + memcpy(res_buf + pad, PyBytes_AsString(self), len); + return result; +} + + PyObject *CPyBytes_Rjust(PyObject *self, CPyTagged width, PyObject *fillbyte) { if (!PyBytes_Check(self)) { PyErr_SetString(PyExc_TypeError, "self must be bytes"); @@ -188,6 +213,31 @@ PyObject *CPyBytes_Rjust(PyObject *self, CPyTagged width, PyObject *fillbyte) { return result; } + +PyObject *CPyBytes_LjustDefaultFill(PyObject *self, CPyTagged width) { + if (!PyBytes_Check(self)) { + PyErr_SetString(PyExc_TypeError, "self must be bytes"); + return NULL; + } + Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); + Py_ssize_t len = PyBytes_Size(self); + if (width_size_t <= len) { + return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + } + // should this be a constant? + PyObject *fillbyte = PyBytes_FromStringAndSize(" ", 1); + // can we optimize out the above line and the below line? + char fill = PyBytes_AsString(fillbyte)[0]; + Py_ssize_t pad = width_size_t - len; + PyObject *result = PyBytes_FromStringAndSize(NULL, width_size_t); + if (!result) return NULL; + char *res_buf = PyBytes_AsString(result); + memcpy(res_buf, PyBytes_AsString(self), len); + memset(res_buf + len, fill, pad); + return result; +} + + PyObject *CPyBytes_Ljust(PyObject *self, CPyTagged width, PyObject *fillbyte) { if (!PyBytes_Check(self)) { PyErr_SetString(PyExc_TypeError, "self must be bytes"); From 2dba0712177bfc44d264db3af937466d56440e52 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 18/23] Update CPy.h --- mypyc/lib-rt/CPy.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 74fb8d382330..dc6c588fb6aa 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -770,8 +770,10 @@ CPyTagged CPyBytes_GetItem(PyObject *o, CPyTagged index); PyObject *CPyBytes_Concat(PyObject *a, PyObject *b); PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter); CPyTagged CPyBytes_Ord(PyObject *obj); -PyObject *CPyBytes_Ljust(PyObject *self, CPyTagged width, PyObject *fillbyte); -PyObject *CPyBytes_Rjust(PyObject *self, CPyTagged width, PyObject *fillbyte); +PyObject *CPyBytes_LjustDefaultFill(PyObject *self, CPyTagged width); +PyObject *CPyBytes_RjustDefaultFill(PyObject *self, CPyTagged width); +PyObject *CPyBytes_LjustCustomFill(PyObject *self, CPyTagged width, PyObject *fillbyte); +PyObject *CPyBytes_RjustCustomFill(PyObject *self, CPyTagged width, PyObject *fillbyte); int CPyBytes_Compare(PyObject *left, PyObject *right); From 7e6cd379af787f2919bd9eee370917d269c69323 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 19/23] Update bytes_ops.py --- mypyc/primitives/bytes_ops.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/mypyc/primitives/bytes_ops.py b/mypyc/primitives/bytes_ops.py index 88155110fc2d..b4fe692fb4cd 100644 --- a/mypyc/primitives/bytes_ops.py +++ b/mypyc/primitives/bytes_ops.py @@ -127,20 +127,38 @@ error_kind=ERR_MAGIC, ) -# bytes.rjust(width, fillbyte=b' ') +# bytes.rjust(width) +method_op( + name="rjust", + arg_types=[bytes_rprimitive, int_rprimitive], + return_type=bytes_rprimitive, + c_function_name="CPyBytes_RjustDefaultFill", + error_kind=ERR_MAGIC, +) + +# bytes.rjust(width, fillbyte) method_op( name="rjust", arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], return_type=bytes_rprimitive, - c_function_name="CPyBytes_Rjust", + c_function_name="CPyBytes_RjustCustomFill", + error_kind=ERR_MAGIC, +) + +# bytes.ljust(width) +method_op( + name="ljust", + arg_types=[bytes_rprimitive, int_rprimitive], + return_type=bytes_rprimitive, + c_function_name="CPyBytes_LjustDefaultFill", error_kind=ERR_MAGIC, ) -# bytes.ljust(width, fillbyte=b' ') +# bytes.ljust(width, fillbyte) method_op( name="ljust", arg_types=[bytes_rprimitive, int_rprimitive, bytes_rprimitive], return_type=bytes_rprimitive, - c_function_name="CPyBytes_Ljust", + c_function_name="CPyBytes_LjustCustomFill", error_kind=ERR_MAGIC, ) From 1ec52cd65bfb6ca9f7fa2eb463759b22d7d733f1 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 20/23] Update bytes_ops.c --- mypyc/lib-rt/bytes_ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index 652a859d057d..f6414041f0af 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -189,7 +189,7 @@ PyObject *CPyBytes_RjustDefaultFill(PyObject *self, CPyTagged width) { } -PyObject *CPyBytes_Rjust(PyObject *self, CPyTagged width, PyObject *fillbyte) { +PyObject *CPyBytes_RjustCustomFill(PyObject *self, CPyTagged width, PyObject *fillbyte) { if (!PyBytes_Check(self)) { PyErr_SetString(PyExc_TypeError, "self must be bytes"); return NULL; @@ -238,7 +238,7 @@ PyObject *CPyBytes_LjustDefaultFill(PyObject *self, CPyTagged width) { } -PyObject *CPyBytes_Ljust(PyObject *self, CPyTagged width, PyObject *fillbyte) { +PyObject *CPyBytes_LjustCustomFill(PyObject *self, CPyTagged width, PyObject *fillbyte) { if (!PyBytes_Check(self)) { PyErr_SetString(PyExc_TypeError, "self must be bytes"); return NULL; From 1b34c8fe00b007c69aa1700ef4805bb7a91466c8 Mon Sep 17 00:00:00 2001 From: BobTheBuidler <70677534+BobTheBuidler@users.noreply.github.com> Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 21/23] Update irbuild-bytes.test --- mypyc/test-data/irbuild-bytes.test | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index 58cc73b4b2e5..935b4342722d 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -194,7 +194,7 @@ def f(b): b :: bytes r0 :: bytes L0: - r0 = b.rjust(6, b' ') + r0 = CPyBytes_RjustDefaultFill(b, 12) return r0 [case testBytesRjustCustom] @@ -205,7 +205,7 @@ def f(b): b, r0, r1 :: bytes L0: r0 = b'0' - r1 = CPyBytes_Rjust(b, 16, r0) + r1 = CPyBytes_RjustCustomFill(b, 16, r0) return r1 [case testBytesLjustDefault] @@ -216,7 +216,7 @@ def f(b): b :: bytes r0 :: bytes L0: - r0 = b.ljust(7, b' ') + r0 = CPyBytes_LjustDefaultFill(b, 14) return r0 [case testBytesLjustCustom] @@ -227,5 +227,5 @@ def f(b): b, r0, r1 :: bytes L0: r0 = b'_' - r1 = CPyBytes_Ljust(b, 20, r0) + r1 = CPyBytes_LjustCustomFill(b, 20, r0) return r1 From 284e368664c820c12641862c79b1ba58bb36ca1f Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 22/23] optimize c funcs --- mypyc/lib-rt/bytes_ops.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index f6414041f0af..7d1dd363203b 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -173,17 +173,14 @@ PyObject *CPyBytes_RjustDefaultFill(PyObject *self, CPyTagged width) { Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); Py_ssize_t len = PyBytes_Size(self); if (width_size_t <= len) { - return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + Py_INCREF(self); + return self; } - // should this be a constant? - PyObject *fillbyte = PyBytes_FromStringAndSize(" ", 1); - // can we optimize out the above line and the below line? - char fill = PyBytes_AsString(fillbyte)[0]; Py_ssize_t pad = width_size_t - len; PyObject *result = PyBytes_FromStringAndSize(NULL, width_size_t); if (!result) return NULL; char *res_buf = PyBytes_AsString(result); - memset(res_buf, fill, pad); + memset(res_buf, ' ', pad); memcpy(res_buf + pad, PyBytes_AsString(self), len); return result; } @@ -201,7 +198,8 @@ PyObject *CPyBytes_RjustCustomFill(PyObject *self, CPyTagged width, PyObject *fi Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); Py_ssize_t len = PyBytes_Size(self); if (width_size_t <= len) { - return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + Py_INCREF(self); + return self; } char fill = PyBytes_AsString(fillbyte)[0]; Py_ssize_t pad = width_size_t - len; @@ -222,18 +220,15 @@ PyObject *CPyBytes_LjustDefaultFill(PyObject *self, CPyTagged width) { Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); Py_ssize_t len = PyBytes_Size(self); if (width_size_t <= len) { - return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + Py_INCREF(self); + return self; } - // should this be a constant? - PyObject *fillbyte = PyBytes_FromStringAndSize(" ", 1); - // can we optimize out the above line and the below line? - char fill = PyBytes_AsString(fillbyte)[0]; Py_ssize_t pad = width_size_t - len; PyObject *result = PyBytes_FromStringAndSize(NULL, width_size_t); if (!result) return NULL; char *res_buf = PyBytes_AsString(result); memcpy(res_buf, PyBytes_AsString(self), len); - memset(res_buf + len, fill, pad); + memset(res_buf + len, ' ', pad); return result; } @@ -250,7 +245,8 @@ PyObject *CPyBytes_LjustCustomFill(PyObject *self, CPyTagged width, PyObject *fi Py_ssize_t width_size_t = CPyTagged_AsSsize_t(width); Py_ssize_t len = PyBytes_Size(self); if (width_size_t <= len) { - return PyBytes_FromStringAndSize(PyBytes_AsString(self), len); + Py_INCREF(self); + return self; } char fill = PyBytes_AsString(fillbyte)[0]; Py_ssize_t pad = width_size_t - len; From d4b42c528c7d99844a21463980842252e3e1e3ae Mon Sep 17 00:00:00 2001 From: BobTheBuidler Date: Wed, 20 Aug 2025 21:15:15 +0000 Subject: [PATCH 23/23] fix ir --- mypyc/test-data/irbuild-bytes.test | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mypyc/test-data/irbuild-bytes.test b/mypyc/test-data/irbuild-bytes.test index 935b4342722d..e5ef0d6cb004 100644 --- a/mypyc/test-data/irbuild-bytes.test +++ b/mypyc/test-data/irbuild-bytes.test @@ -191,8 +191,7 @@ def f(b: bytes) -> bytes: return b.rjust(6) [out] def f(b): - b :: bytes - r0 :: bytes + b, r0 :: bytes L0: r0 = CPyBytes_RjustDefaultFill(b, 12) return r0 @@ -213,8 +212,7 @@ def f(b: bytes) -> bytes: return b.ljust(7) [out] def f(b): - b :: bytes - r0 :: bytes + b, r0 :: bytes L0: r0 = CPyBytes_LjustDefaultFill(b, 14) return r0