diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 3c55688da..a2b9ab033 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -1722,8 +1722,6 @@ class AssortedBytesTest(unittest.TestCase): self.assertEqual(f(b"'"), '''b"'"''') # ''' self.assertEqual(f(b"'\""), r"""b'\'"'""") # ' - # TODO: RUSTPYTHON - @unittest.expectedFailure @check_bytes_warnings def test_format(self): for b in b'abc', bytearray(b'abc'): @@ -1962,8 +1960,6 @@ class SubclassTest: self.assertEqual(type(a), type(b)) self.assertEqual(type(a.y), type(b.y)) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_fromhex(self): b = self.type2test.fromhex('1a2B30') self.assertEqual(b, b'\x1a\x2b\x30') diff --git a/extra_tests/snippets/bytes.py b/extra_tests/snippets/bytes.py index a4816984d..d9489a613 100644 --- a/extra_tests/snippets/bytes.py +++ b/extra_tests/snippets/bytes.py @@ -647,3 +647,12 @@ assert id(b) != id(b * -1) assert id(b) != id(b * 0) assert id(b) != id(b * 1) assert id(b) != id(b * 2) + +class B1(bytearray): + def __new__(cls, value): + assert type(value) == bytes + me = super().__new__(cls, value) + me.foo = 'bar' + return me +b = B1.fromhex('a0a1a2') +assert b.foo == 'bar' diff --git a/vm/src/builtins/bytearray.rs b/vm/src/builtins/bytearray.rs index cb6049db3..85638161e 100644 --- a/vm/src/builtins/bytearray.rs +++ b/vm/src/builtins/bytearray.rs @@ -20,7 +20,9 @@ use crate::common::lock::{ }; use crate::function::{FuncArgs, OptionalArg, OptionalOption}; use crate::sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex}; -use crate::slots::{AsBuffer, Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable}; +use crate::slots::{ + AsBuffer, Callable, Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable, +}; use crate::utils::Either; use crate::vm::VirtualMachine; use crate::{ @@ -373,9 +375,11 @@ impl PyByteArray { self.inner().hex(sep, bytes_per_sep, vm) } - #[pymethod] - fn fromhex(string: PyStrRef, vm: &VirtualMachine) -> PyResult { - Ok(PyBytesInner::fromhex(string.as_str(), vm)?.into()) + #[pyclassmethod] + fn fromhex(cls: PyTypeRef, string: PyStrRef, vm: &VirtualMachine) -> PyResult { + let bytes = PyBytesInner::fromhex(string.as_str(), vm)?; + let bytes = vm.ctx.new_bytes(bytes); + Callable::call(&cls, vec![bytes].into(), vm) } #[pymethod] diff --git a/vm/src/builtins/bytes.rs b/vm/src/builtins/bytes.rs index 62d8caaf2..f8d35eb0d 100644 --- a/vm/src/builtins/bytes.rs +++ b/vm/src/builtins/bytes.rs @@ -12,7 +12,7 @@ use crate::bytesinner::{ use crate::byteslike::ArgBytesLike; use crate::common::hash::PyHash; use crate::function::{OptionalArg, OptionalOption}; -use crate::slots::{AsBuffer, Comparable, Hashable, Iterable, PyComparisonOp, PyIter}; +use crate::slots::{AsBuffer, Callable, Comparable, Hashable, Iterable, PyComparisonOp, PyIter}; use crate::utils::Either; use crate::vm::VirtualMachine; use crate::{ @@ -222,9 +222,11 @@ impl PyBytes { self.inner.hex(sep, bytes_per_sep, vm) } - #[pymethod] - fn fromhex(string: PyStrRef, vm: &VirtualMachine) -> PyResult { - Ok(PyBytesInner::fromhex(string.as_str(), vm)?.into()) + #[pyclassmethod] + fn fromhex(cls: PyTypeRef, string: PyStrRef, vm: &VirtualMachine) -> PyResult { + let bytes = PyBytesInner::fromhex(string.as_str(), vm)?; + let bytes = vm.ctx.new_bytes(bytes); + Callable::call(&cls, vec![bytes].into(), vm) } #[pymethod] diff --git a/vm/src/builtins/object.rs b/vm/src/builtins/object.rs index 32930f4c3..7b5e2beda 100644 --- a/vm/src/builtins/object.rs +++ b/vm/src/builtins/object.rs @@ -217,9 +217,10 @@ impl PyBaseObject { if format_spec.as_str().is_empty() { vm.to_str(&obj) } else { - Err(vm.new_type_error( - "unsupported format string passed to object.__format__".to_string(), - )) + Err(vm.new_type_error(format!( + "unsupported format string passed to {}.__format__", + obj.class().name + ))) } }