mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Finish source-less bytearray initialization after clearing
Preserve option validation and initial export rejection, then avoid a redundant resize guard and storage swap when no source was provided. Keep zero-count callback behavior and all existing regressions. Assisted-by: OpenAI Codex:model identifier unavailable
This commit is contained in:
1 parent
f163e13710
commit
108171daa2
2 files changed
+55
-4
No files matched your search
@@ -23,7 +23,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
convert::{ToPyObject, ToPyResult},
|
convert::{ToPyObject, ToPyResult},
|
||||||
function::{ArgBytesLike, FuncArgs, PyComparisonValue, PySsize},
|
function::{ArgBytesLike, FuncArgs, OptionalArg, PyComparisonValue, PySsize},
|
||||||
protocol::{
|
protocol::{
|
||||||
BufferDescriptor, BufferFlags, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn,
|
BufferDescriptor, BufferFlags, BufferMethods, BufferResizeGuard, PyBuffer, PyIterReturn,
|
||||||
PyMappingMethods, PyNumberMethods, PySequenceMethods,
|
PyMappingMethods, PyNumberMethods, PySequenceMethods,
|
||||||
@@ -924,15 +924,17 @@ impl Initializer for PyByteArray {
|
|||||||
type Args = ByteInnerNewOptions;
|
type Args = ByteInnerNewOptions;
|
||||||
|
|
||||||
fn init(zelf: &Py<Self>, options: Self::Args, vm: &VirtualMachine) -> PyResult<()> {
|
fn init(zelf: &Py<Self>, options: Self::Args, vm: &VirtualMachine) -> PyResult<()> {
|
||||||
|
let source_is_missing = matches!(&options.source, OptionalArg::Missing);
|
||||||
// Reject exports and clear existing contents before converting source.
|
// Reject exports and clear existing contents before converting source.
|
||||||
zelf.try_resizable(vm)?.elements = Vec::new();
|
zelf.try_resizable(vm)?.elements = Vec::new();
|
||||||
// Conversion can call Python, so do not hold the lock across it and
|
// Conversion can call Python, so do not hold the lock across it and
|
||||||
// check again for exports acquired by a callback or another thread.
|
// check again for exports acquired by a callback or another thread.
|
||||||
let (mut inner, zero_count) =
|
let (mut inner, zero_count) =
|
||||||
options.get_inner_with_zero_count(bytearray_from_object, vm)?;
|
options.get_inner_with_zero_count(bytearray_from_object, vm)?;
|
||||||
// A zero integer count performs no further writes, including when its
|
// Missing sources and zero integer counts perform no further writes.
|
||||||
// __index__ callback changed this bytearray or acquired an export.
|
// Argument validation above still rejects encoding/errors without a
|
||||||
if zero_count {
|
// source; a zero __index__ callback may have changed or exported self.
|
||||||
|
if source_is_missing || zero_count {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
core::mem::swap(&mut *zelf.try_resizable(vm)?, &mut inner);
|
core::mem::swap(&mut *zelf.try_resizable(vm)?, &mut inner);
|
||||||
|
|||||||
@@ -1504,3 +1504,52 @@ def test_bytearray_callback_exports():
|
|||||||
|
|
||||||
|
|
||||||
test_bytearray_callback_exports()
|
test_bytearray_callback_exports()
|
||||||
|
|
||||||
|
|
||||||
|
def test_bytearray_missing_source_init():
|
||||||
|
from testutils import assert_raises
|
||||||
|
|
||||||
|
for initial in (b"", b"previous contents"):
|
||||||
|
value = bytearray(initial)
|
||||||
|
assert value.__init__() is None
|
||||||
|
assert value == b""
|
||||||
|
assert value.__alloc__() == 0
|
||||||
|
|
||||||
|
for kwargs, message in (
|
||||||
|
({"encoding": "utf-8"}, "encoding without a string argument"),
|
||||||
|
({"errors": "strict"}, "errors without a string argument"),
|
||||||
|
(
|
||||||
|
{"encoding": "utf-8", "errors": "strict"},
|
||||||
|
"encoding without a string argument",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
value = bytearray(initial)
|
||||||
|
with assert_raises(TypeError) as caught:
|
||||||
|
value.__init__(**kwargs)
|
||||||
|
assert str(caught.exception) == message
|
||||||
|
assert value == b""
|
||||||
|
assert value.__alloc__() == 0
|
||||||
|
|
||||||
|
for kwargs in (
|
||||||
|
{},
|
||||||
|
{"encoding": "utf-8"},
|
||||||
|
{"errors": "strict"},
|
||||||
|
{"encoding": "utf-8", "errors": "strict"},
|
||||||
|
):
|
||||||
|
value = bytearray(initial)
|
||||||
|
with memoryview(value) as view:
|
||||||
|
with assert_raises(BufferError):
|
||||||
|
value.__init__(**kwargs)
|
||||||
|
assert value == initial
|
||||||
|
assert view.tobytes() == initial
|
||||||
|
assert value.__init__() is None
|
||||||
|
assert value == b""
|
||||||
|
|
||||||
|
# Explicit None is a source and must still go through conversion.
|
||||||
|
value = bytearray(initial)
|
||||||
|
with assert_raises(TypeError):
|
||||||
|
value.__init__(None)
|
||||||
|
assert value == b""
|
||||||
|
|
||||||
|
|
||||||
|
test_bytearray_missing_source_init()
|
||||||
Reference in new issue
Block a user