gh-129107: make bytearray thread safe (#129108)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
Tomasz Pytel 2025-02-15 02:19:42 -05:00 committed by GitHub
parent d2e60d8e59
commit a05433f24a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 904 additions and 100 deletions

View file

@ -29,6 +29,10 @@ static inline char* PyByteArray_AS_STRING(PyObject *op)
static inline Py_ssize_t PyByteArray_GET_SIZE(PyObject *op) {
PyByteArrayObject *self = _PyByteArray_CAST(op);
#ifdef Py_GIL_DISABLED
return _Py_atomic_load_ssize_relaxed(&(_PyVarObject_CAST(self)->ob_size));
#else
return Py_SIZE(self);
#endif
}
#define PyByteArray_GET_SIZE(self) PyByteArray_GET_SIZE(_PyObject_CAST(self))

View file

@ -11,12 +11,16 @@ import sys
import copy
import functools
import pickle
import sysconfig
import tempfile
import textwrap
import threading
import unittest
import test.support
from test import support
from test.support import import_helper
from test.support import threading_helper
from test.support import warnings_helper
import test.string_tests
import test.list_tests
@ -2185,5 +2189,336 @@ class BytesSubclassTest(SubclassTest, unittest.TestCase):
type2test = BytesSubclass
class FreeThreadingTest(unittest.TestCase):
@unittest.skipUnless(support.Py_GIL_DISABLED, 'this test can only possibly fail with GIL disabled')
@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_free_threading_bytearray(self):
# Test pretty much everything that can break under free-threading.
# Non-deterministic, but at least one of these things will fail if
# bytearray module is not free-thread safe.
def clear(b, a, *args): # MODIFIES!
b.wait()
try: a.clear()
except BufferError: pass
def clear2(b, a, c): # MODIFIES c!
b.wait()
try: c.clear()
except BufferError: pass
def pop1(b, a): # MODIFIES!
b.wait()
try: a.pop()
except IndexError: pass
def append1(b, a): # MODIFIES!
b.wait()
a.append(0)
def insert1(b, a): # MODIFIES!
b.wait()
a.insert(0, 0)
def extend(b, a): # MODIFIES!
c = bytearray(b'0' * 0x400000)
b.wait()
a.extend(c)
def remove(b, a): # MODIFIES!
c = ord('0')
b.wait()
try: a.remove(c)
except ValueError: pass
def reverse(b, a): # modifies inplace
b.wait()
a.reverse()
def reduce(b, a):
b.wait()
a.__reduce__()
def reduceex2(b, a):
b.wait()
a.__reduce_ex__(2)
def reduceex3(b, a):
b.wait()
c = a.__reduce_ex__(3)
assert not c[1] or 0xdd not in c[1][0]
def count0(b, a):
b.wait()
a.count(0)
def decode(b, a):
b.wait()
a.decode()
def find(b, a):
c = bytearray(b'0' * 0x40000)
b.wait()
a.find(c)
def hex(b, a):
b.wait()
a.hex('_')
def join(b, a):
b.wait()
a.join([b'1', b'2', b'3'])
def replace(b, a):
b.wait()
a.replace(b'0', b'')
def maketrans(b, a, c):
b.wait()
try: a.maketrans(a, c)
except ValueError: pass
def translate(b, a, c):
b.wait()
a.translate(c)
def copy(b, a):
b.wait()
c = a.copy()
if c: assert c[0] == 48 # '0'
def endswith(b, a):
b.wait()
assert not a.endswith(b'\xdd')
def index(b, a):
b.wait()
try: a.index(b'\xdd')
except ValueError: return
assert False
def lstrip(b, a):
b.wait()
assert not a.lstrip(b'0')
def partition(b, a):
b.wait()
assert not a.partition(b'\xdd')[2]
def removeprefix(b, a):
b.wait()
assert not a.removeprefix(b'0')
def removesuffix(b, a):
b.wait()
assert not a.removesuffix(b'0')
def rfind(b, a):
b.wait()
assert a.rfind(b'\xdd') == -1
def rindex(b, a):
b.wait()
try: a.rindex(b'\xdd')
except ValueError: return
assert False
def rpartition(b, a):
b.wait()
assert not a.rpartition(b'\xdd')[0]
def rsplit(b, a):
b.wait()
assert len(a.rsplit(b'\xdd')) == 1
def rstrip(b, a):
b.wait()
assert not a.rstrip(b'0')
def split(b, a):
b.wait()
assert len(a.split(b'\xdd')) == 1
def splitlines(b, a):
b.wait()
l = len(a.splitlines())
assert l > 1 or l == 0
def startswith(b, a):
b.wait()
assert not a.startswith(b'\xdd')
def strip(b, a):
b.wait()
assert not a.strip(b'0')
def repeat(b, a):
b.wait()
a * 2
def contains(b, a):
b.wait()
assert 0xdd not in a
def iconcat(b, a): # MODIFIES!
c = bytearray(b'0' * 0x400000)
b.wait()
a += c
def irepeat(b, a): # MODIFIES!
b.wait()
a *= 2
def subscript(b, a):
b.wait()
try: assert a[0] != 0xdd
except IndexError: pass
def ass_subscript(b, a): # MODIFIES!
c = bytearray(b'0' * 0x400000)
b.wait()
a[:] = c
def mod(b, a):
c = tuple(range(4096))
b.wait()
try: a % c
except TypeError: pass
def repr_(b, a):
b.wait()
repr(a)
def capitalize(b, a):
b.wait()
c = a.capitalize()
assert not c or c[0] not in (0xdd, 0xcd)
def center(b, a):
b.wait()
c = a.center(0x60000)
assert not c or c[0x20000] not in (0xdd, 0xcd)
def expandtabs(b, a):
b.wait()
c = a.expandtabs()
assert not c or c[0] not in (0xdd, 0xcd)
def ljust(b, a):
b.wait()
c = a.ljust(0x600000)
assert not c or c[0] not in (0xdd, 0xcd)
def lower(b, a):
b.wait()
c = a.lower()
assert not c or c[0] not in (0xdd, 0xcd)
def rjust(b, a):
b.wait()
c = a.rjust(0x600000)
assert not c or c[-1] not in (0xdd, 0xcd)
def swapcase(b, a):
b.wait()
c = a.swapcase()
assert not c or c[-1] not in (0xdd, 0xcd)
def title(b, a):
b.wait()
c = a.title()
assert not c or c[-1] not in (0xdd, 0xcd)
def upper(b, a):
b.wait()
c = a.upper()
assert not c or c[-1] not in (0xdd, 0xcd)
def zfill(b, a):
b.wait()
c = a.zfill(0x400000)
assert not c or c[-1] not in (0xdd, 0xcd)
def check(funcs, a=None, *args):
if a is None:
a = bytearray(b'0' * 0x400000)
barrier = threading.Barrier(len(funcs))
threads = []
for func in funcs:
thread = threading.Thread(target=func, args=(barrier, a, *args))
threads.append(thread)
with threading_helper.start_threads(threads):
pass
for thread in threads:
threading_helper.join_thread(thread)
# hard errors
check([clear] + [reduce] * 10)
check([clear] + [reduceex2] * 10)
check([clear] + [append1] * 10)
check([clear] * 10)
check([clear] + [count0] * 10)
check([clear] + [decode] * 10)
check([clear] + [extend] * 10)
check([clear] + [find] * 10)
check([clear] + [hex] * 10)
check([clear] + [insert1] * 10)
check([clear] + [join] * 10)
check([clear] + [pop1] * 10)
check([clear] + [remove] * 10)
check([clear] + [replace] * 10)
check([clear] + [reverse] * 10)
check([clear, clear2] + [maketrans] * 10, bytearray(range(128)), bytearray(range(128)))
check([clear] + [translate] * 10, None, bytearray.maketrans(bytearray(range(128)), bytearray(range(128))))
check([clear] + [repeat] * 10)
check([clear] + [iconcat] * 10)
check([clear] + [irepeat] * 10)
check([clear] + [ass_subscript] * 10)
check([clear] + [repr_] * 10)
# value errors
check([clear] + [reduceex3] * 10, bytearray(b'a' * 0x40000))
check([clear] + [copy] * 10)
check([clear] + [endswith] * 10)
check([clear] + [index] * 10)
check([clear] + [lstrip] * 10)
check([clear] + [partition] * 10)
check([clear] + [removeprefix] * 10, bytearray(b'0'))
check([clear] + [removesuffix] * 10, bytearray(b'0'))
check([clear] + [rfind] * 10)
check([clear] + [rindex] * 10)
check([clear] + [rpartition] * 10)
check([clear] + [rsplit] * 10, bytearray(b'0' * 0x4000))
check([clear] + [rstrip] * 10)
check([clear] + [split] * 10, bytearray(b'0' * 0x4000))
check([clear] + [splitlines] * 10, bytearray(b'\n' * 0x400))
check([clear] + [startswith] * 10)
check([clear] + [strip] * 10)
check([clear] + [contains] * 10)
check([clear] + [subscript] * 10)
check([clear] + [mod] * 10, bytearray(b'%d' * 4096))
check([clear] + [capitalize] * 10, bytearray(b'a' * 0x40000))
check([clear] + [center] * 10, bytearray(b'a' * 0x40000))
check([clear] + [expandtabs] * 10, bytearray(b'0\t' * 4096))
check([clear] + [ljust] * 10, bytearray(b'0' * 0x400000))
check([clear] + [lower] * 10, bytearray(b'A' * 0x400000))
check([clear] + [rjust] * 10, bytearray(b'0' * 0x400000))
check([clear] + [swapcase] * 10, bytearray(b'aA' * 0x200000))
check([clear] + [title] * 10, bytearray(b'aA' * 0x200000))
check([clear] + [upper] * 10, bytearray(b'a' * 0x400000))
check([clear] + [zfill] * 10, bytearray(b'1' * 0x200000))
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1 @@
Make the :type:`bytearray` safe under :term:`free threading`.

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@ preserve
# include "pycore_runtime.h" // _Py_ID()
#endif
#include "pycore_abstract.h" // _PyNumber_Index()
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
static int
@ -147,7 +148,9 @@ bytearray_find(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_find_impl((PyByteArrayObject *)self, sub, start, end);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -196,7 +199,9 @@ bytearray_count(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_count_impl((PyByteArrayObject *)self, sub, start, end);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -235,7 +240,13 @@ bytearray_copy_impl(PyByteArrayObject *self);
static PyObject *
bytearray_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_copy_impl((PyByteArrayObject *)self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_copy_impl((PyByteArrayObject *)self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(bytearray_index__doc__,
@ -283,7 +294,9 @@ bytearray_index(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_index_impl((PyByteArrayObject *)self, sub, start, end);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -334,7 +347,9 @@ bytearray_rfind(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_rfind_impl((PyByteArrayObject *)self, sub, start, end);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -385,7 +400,9 @@ bytearray_rindex(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_rindex_impl((PyByteArrayObject *)self, sub, start, end);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -436,7 +453,9 @@ bytearray_startswith(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_startswith_impl((PyByteArrayObject *)self, subobj, start, end);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -487,7 +506,9 @@ bytearray_endswith(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_endswith_impl((PyByteArrayObject *)self, subobj, start, end);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -518,7 +539,9 @@ bytearray_removeprefix(PyObject *self, PyObject *arg)
if (PyObject_GetBuffer(arg, &prefix, PyBUF_SIMPLE) != 0) {
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_removeprefix_impl((PyByteArrayObject *)self, &prefix);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for prefix */
@ -554,7 +577,9 @@ bytearray_removesuffix(PyObject *self, PyObject *arg)
if (PyObject_GetBuffer(arg, &suffix, PyBUF_SIMPLE) != 0) {
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_removesuffix_impl((PyByteArrayObject *)self, &suffix);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for suffix */
@ -668,7 +693,9 @@ bytearray_translate(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyO
}
deletechars = args[1];
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_translate_impl((PyByteArrayObject *)self, table, deletechars);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -775,7 +802,9 @@ bytearray_replace(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
count = ival;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_replace_impl((PyByteArrayObject *)self, &old, &new, count);
Py_END_CRITICAL_SECTION();
exit:
/* Cleanup for old */
@ -872,7 +901,9 @@ bytearray_split(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
maxsplit = ival;
}
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_split_impl((PyByteArrayObject *)self, sep, maxsplit);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -894,6 +925,21 @@ PyDoc_STRVAR(bytearray_partition__doc__,
#define BYTEARRAY_PARTITION_METHODDEF \
{"partition", (PyCFunction)bytearray_partition, METH_O, bytearray_partition__doc__},
static PyObject *
bytearray_partition_impl(PyByteArrayObject *self, PyObject *sep);
static PyObject *
bytearray_partition(PyByteArrayObject *self, PyObject *sep)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_partition_impl((PyByteArrayObject *)self, sep);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(bytearray_rpartition__doc__,
"rpartition($self, sep, /)\n"
"--\n"
@ -911,6 +957,21 @@ PyDoc_STRVAR(bytearray_rpartition__doc__,
#define BYTEARRAY_RPARTITION_METHODDEF \
{"rpartition", (PyCFunction)bytearray_rpartition, METH_O, bytearray_rpartition__doc__},
static PyObject *
bytearray_rpartition_impl(PyByteArrayObject *self, PyObject *sep);
static PyObject *
bytearray_rpartition(PyByteArrayObject *self, PyObject *sep)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_rpartition_impl((PyByteArrayObject *)self, sep);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(bytearray_rsplit__doc__,
"rsplit($self, /, sep=None, maxsplit=-1)\n"
"--\n"
@ -995,7 +1056,9 @@ bytearray_rsplit(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
maxsplit = ival;
}
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_rsplit_impl((PyByteArrayObject *)self, sep, maxsplit);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1016,7 +1079,13 @@ bytearray_reverse_impl(PyByteArrayObject *self);
static PyObject *
bytearray_reverse(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_reverse_impl((PyByteArrayObject *)self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_reverse_impl((PyByteArrayObject *)self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(bytearray_insert__doc__,
@ -1061,7 +1130,9 @@ bytearray_insert(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
if (!_getbytevalue(args[1], &item)) {
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_insert_impl((PyByteArrayObject *)self, index, item);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1091,7 +1162,9 @@ bytearray_append(PyObject *self, PyObject *arg)
if (!_getbytevalue(arg, &item)) {
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_append_impl((PyByteArrayObject *)self, item);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1109,6 +1182,21 @@ PyDoc_STRVAR(bytearray_extend__doc__,
#define BYTEARRAY_EXTEND_METHODDEF \
{"extend", (PyCFunction)bytearray_extend, METH_O, bytearray_extend__doc__},
static PyObject *
bytearray_extend_impl(PyByteArrayObject *self, PyObject *iterable_of_ints);
static PyObject *
bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_extend_impl((PyByteArrayObject *)self, iterable_of_ints);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(bytearray_pop__doc__,
"pop($self, index=-1, /)\n"
"--\n"
@ -1152,7 +1240,9 @@ bytearray_pop(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
index = ival;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_pop_impl((PyByteArrayObject *)self, index);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1182,7 +1272,9 @@ bytearray_remove(PyObject *self, PyObject *arg)
if (!_getbytevalue(arg, &value)) {
goto exit;
}
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_remove_impl((PyByteArrayObject *)self, value);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1216,7 +1308,9 @@ bytearray_strip(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
bytes = args[0];
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_strip_impl((PyByteArrayObject *)self, bytes);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1250,7 +1344,9 @@ bytearray_lstrip(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
bytes = args[0];
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_lstrip_impl((PyByteArrayObject *)self, bytes);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1284,7 +1380,9 @@ bytearray_rstrip(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
bytes = args[0];
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_rstrip_impl((PyByteArrayObject *)self, bytes);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1386,7 +1484,9 @@ bytearray_decode(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObje
goto exit;
}
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_decode_impl((PyByteArrayObject *)self, encoding, errors);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1405,6 +1505,21 @@ PyDoc_STRVAR(bytearray_join__doc__,
#define BYTEARRAY_JOIN_METHODDEF \
{"join", (PyCFunction)bytearray_join, METH_O, bytearray_join__doc__},
static PyObject *
bytearray_join_impl(PyByteArrayObject *self, PyObject *iterable_of_bytes);
static PyObject *
bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_join_impl((PyByteArrayObject *)self, iterable_of_bytes);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(bytearray_splitlines__doc__,
"splitlines($self, /, keepends=False)\n"
"--\n"
@ -1466,7 +1581,9 @@ bytearray_splitlines(PyObject *self, PyObject *const *args, Py_ssize_t nargs, Py
goto exit;
}
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_splitlines_impl((PyByteArrayObject *)self, keepends);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1586,7 +1703,9 @@ bytearray_hex(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject
goto exit;
}
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_hex_impl((PyByteArrayObject *)self, sep, bytes_per_sep);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1607,7 +1726,13 @@ bytearray_reduce_impl(PyByteArrayObject *self);
static PyObject *
bytearray_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_reduce_impl((PyByteArrayObject *)self);
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_reduce_impl((PyByteArrayObject *)self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(bytearray_reduce_ex__doc__,
@ -1639,7 +1764,9 @@ bytearray_reduce_ex(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
goto exit;
}
skip_optional:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = bytearray_reduce_ex_impl((PyByteArrayObject *)self, proto);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -1662,4 +1789,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl((PyByteArrayObject *)self);
}
/*[clinic end generated code: output=41bb67a8a181e733 input=a9049054013a1b77]*/
/*[clinic end generated code: output=5e33422343b47af9 input=a9049054013a1b77]*/