mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Fix bytes constructor
This commit is contained in:
1 parent
3a54105e2c
commit
44d312419a
2 files changed
+40
-19
No files matched your search
Vendored
-2
@@ -209,8 +209,6 @@ class BaseBytesTest:
|
||||
except (OverflowError, MemoryError):
|
||||
pass
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_constructor_exceptions(self):
|
||||
# Issue #34974: bytes and bytearray constructors replace unexpected
|
||||
# exceptions.
|
||||
|
||||
+40
-17
@@ -21,6 +21,9 @@ use itertools::Itertools;
|
||||
use malachite_bigint::BigInt;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
const STRING_WITHOUT_ENCODING: &str = "string argument without an encoding";
|
||||
const ENCODING_WITHOUT_STRING: &str = "encoding without a string argument";
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct PyBytesInner {
|
||||
pub(super) elements: Vec<u8>,
|
||||
@@ -75,6 +78,18 @@ impl ByteInnerNewOptions {
|
||||
Ok(vec![0; size].into())
|
||||
}
|
||||
|
||||
fn handle_object_fallback(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyBytesInner> {
|
||||
match_class!(match obj {
|
||||
i @ PyInt => {
|
||||
Self::get_value_from_size(i, vm)
|
||||
}
|
||||
_s @ PyStr => Err(vm.new_type_error(STRING_WITHOUT_ENCODING.to_owned())),
|
||||
obj => {
|
||||
Self::get_value_from_source(obj, vm)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_bytes(self, cls: PyTypeRef, vm: &VirtualMachine) -> PyResult<PyBytesRef> {
|
||||
let inner = match (&self.source, &self.encoding, &self.errors) {
|
||||
(OptionalArg::Present(obj), OptionalArg::Missing, OptionalArg::Missing) => {
|
||||
@@ -113,40 +128,48 @@ impl ByteInnerNewOptions {
|
||||
}
|
||||
|
||||
pub fn get_bytearray_inner(self, vm: &VirtualMachine) -> PyResult<PyBytesInner> {
|
||||
const STRING_WITHOUT_ENCODING: &str = "string argument without an encoding";
|
||||
const ENCODING_WITHOUT_STRING: &str = "encoding without a string argument";
|
||||
|
||||
match (self.source, self.encoding, self.errors) {
|
||||
(OptionalArg::Present(obj), OptionalArg::Missing, OptionalArg::Missing) => {
|
||||
match_class!(match obj {
|
||||
i @ PyInt => {
|
||||
Ok(Self::get_value_from_size(i, vm)?)
|
||||
// Try __index__ first to handle int-like objects that might raise custom exceptions
|
||||
if let Some(index_result) = obj.try_index_opt(vm) {
|
||||
match index_result {
|
||||
Ok(index) => Self::get_value_from_size(index, vm),
|
||||
Err(e) => {
|
||||
// Only propagate non-TypeError exceptions
|
||||
// TypeError means the object doesn't support __index__, so fall back
|
||||
if e.fast_isinstance(vm.ctx.exceptions.type_error) {
|
||||
// Fall back to treating as buffer-like object
|
||||
Self::handle_object_fallback(obj, vm)
|
||||
} else {
|
||||
// Propagate other exceptions (e.g., ZeroDivisionError)
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
_s @ PyStr => Err(STRING_WITHOUT_ENCODING),
|
||||
obj => {
|
||||
Ok(Self::get_value_from_source(obj, vm)?)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Self::handle_object_fallback(obj, vm)
|
||||
}
|
||||
}
|
||||
(OptionalArg::Present(obj), OptionalArg::Present(encoding), errors) => {
|
||||
if let Ok(s) = obj.downcast::<PyStr>() {
|
||||
Ok(Self::get_value_from_string(s, encoding, errors, vm)?)
|
||||
Self::get_value_from_string(s, encoding, errors, vm)
|
||||
} else {
|
||||
Err(ENCODING_WITHOUT_STRING)
|
||||
Err(vm.new_type_error(ENCODING_WITHOUT_STRING.to_owned()))
|
||||
}
|
||||
}
|
||||
(OptionalArg::Missing, OptionalArg::Missing, OptionalArg::Missing) => {
|
||||
Ok(PyBytesInner::default())
|
||||
}
|
||||
(OptionalArg::Missing, OptionalArg::Present(_), _) => Err(ENCODING_WITHOUT_STRING),
|
||||
(OptionalArg::Missing, OptionalArg::Present(_), _) => {
|
||||
Err(vm.new_type_error(ENCODING_WITHOUT_STRING.to_owned()))
|
||||
}
|
||||
(OptionalArg::Missing, _, OptionalArg::Present(_)) => {
|
||||
Err("errors without a string argument")
|
||||
Err(vm.new_type_error("errors without a string argument".to_owned()))
|
||||
}
|
||||
(OptionalArg::Present(_), OptionalArg::Missing, OptionalArg::Present(_)) => {
|
||||
Err(STRING_WITHOUT_ENCODING)
|
||||
Err(vm.new_type_error(STRING_WITHOUT_ENCODING.to_owned()))
|
||||
}
|
||||
}
|
||||
.map_err(|e| vm.new_type_error(e.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user