Skip to content

Commit a8285f4

Browse files
authored
Merge pull request RustPython#2302 from qingshi163/bytes_pickle
Fix bytes pickle with subclass
2 parents 7eb9335 + 1d4cfa4 commit a8285f4

File tree

4 files changed

+62
-9
lines changed

4 files changed

+62
-9
lines changed

Lib/test/test_bytes.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,8 +1860,6 @@ def test_join(self):
18601860
s3 = s1.join([b"abcd"])
18611861
self.assertIs(type(s3), self.basetype)
18621862

1863-
# TODO: RUSTPYTHON
1864-
@unittest.expectedFailure
18651863
def test_pickle(self):
18661864
a = self.type2test(b"abcd")
18671865
a.x = 10
@@ -1875,8 +1873,6 @@ def test_pickle(self):
18751873
self.assertEqual(type(a), type(b))
18761874
self.assertEqual(type(a.y), type(b.y))
18771875

1878-
# TODO: RUSTPYTHON
1879-
@unittest.expectedFailure
18801876
def test_copy(self):
18811877
a = self.type2test(b"abcd")
18821878
a.x = 10

extra_tests/snippets/bytearray.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,3 +729,28 @@
729729
assert pickle.dumps(a, 2) == b'\x80\x02c__builtin__\nbytearray\nq\x00c_codecs\nencode\nq\x01X\x0c\x00\x00\x00\xc3\xbfab\xc2\x80\x00\x00\xc3\xb8\x00\x00q\x02X\x06\x00\x00\x00latin1q\x03\x86q\x04Rq\x05\x85q\x06Rq\x07.'
730730
assert pickle.dumps(a, 3) == b'\x80\x03cbuiltins\nbytearray\nq\x00C\t\xffab\x80\x00\x00\xf8\x00\x00q\x01\x85q\x02Rq\x03.'
731731
assert pickle.dumps(a, 4) == b'\x80\x04\x95*\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\tbytearray\x94\x93\x94C\t\xffab\x80\x00\x00\xf8\x00\x00\x94\x85\x94R\x94.'
732+
733+
# pickle with subclass
734+
class A(bytes):
735+
pass
736+
737+
a = A()
738+
a.x = 10
739+
a.y = A(b'123')
740+
b = pickle.loads(pickle.dumps(a, 4))
741+
assert type(a) == type(b)
742+
assert a.x == b.x
743+
assert a.y == b.y
744+
assert a == b
745+
746+
class B(bytearray):
747+
pass
748+
749+
a = B()
750+
a.x = 10
751+
a.y = B(b'123')
752+
b = pickle.loads(pickle.dumps(a, 4))
753+
assert type(a) == type(b)
754+
assert a.x == b.x
755+
assert a.y == b.y
756+
assert a == b

vm/src/builtins/bytearray.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Implementation of the python bytearray object.
22
use super::bytes::{PyBytes, PyBytesRef};
3+
use super::dict::PyDictRef;
34
use super::int::PyIntRef;
45
use super::memory::{Buffer, BufferOptions, ResizeGuard};
56
use super::pystr::PyStrRef;
@@ -19,7 +20,7 @@ use crate::common::lock::{
1920
use crate::function::{OptionalArg, OptionalOption};
2021
use crate::pyobject::{
2122
BorrowValue, Either, IdProtocol, IntoPyObject, PyClassImpl, PyComparisonValue, PyContext,
22-
PyIterable, PyObjectRef, PyRef, PyResult, PyValue,
23+
PyIterable, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
2324
};
2425
use crate::sliceable::{PySliceableSequence, PySliceableSequenceMut, SequenceIndex};
2526
use crate::slots::{BufferProtocol, Comparable, Hashable, PyComparisonOp, Unhashable};
@@ -627,16 +628,24 @@ impl PyByteArray {
627628
}
628629

629630
#[pymethod(magic)]
630-
fn reduce_ex(zelf: PyRef<Self>, _proto: usize, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef) {
631+
fn reduce_ex(
632+
zelf: PyRef<Self>,
633+
_proto: usize,
634+
vm: &VirtualMachine,
635+
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
631636
Self::reduce(zelf, vm)
632637
}
633638

634639
#[pymethod(magic)]
635-
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> (PyTypeRef, PyTupleRef) {
640+
fn reduce(
641+
zelf: PyRef<Self>,
642+
vm: &VirtualMachine,
643+
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
636644
let bytes = PyBytes::from(zelf.borrow_value().elements.clone()).into_pyobject(vm);
637645
(
638-
Self::class(vm).clone(),
646+
zelf.as_object().clone_class(),
639647
PyTupleRef::with_elements(vec![bytes], &vm.ctx),
648+
zelf.as_object().dict(),
640649
)
641650
}
642651
}

vm/src/builtins/bytes.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustpython_common::{
77
use std::mem::size_of;
88
use std::ops::Deref;
99

10+
use super::dict::PyDictRef;
1011
use super::int::PyIntRef;
1112
use super::pystr::PyStrRef;
1213
use super::pytype::PyTypeRef;
@@ -19,7 +20,7 @@ use crate::common::hash::PyHash;
1920
use crate::function::{OptionalArg, OptionalOption};
2021
use crate::pyobject::{
2122
BorrowValue, Either, IntoPyObject, PyClassImpl, PyComparisonValue, PyContext, PyIterable,
22-
PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
23+
PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
2324
};
2425
use crate::slots::{BufferProtocol, Comparable, Hashable, PyComparisonOp};
2526
use crate::vm::VirtualMachine;
@@ -472,6 +473,28 @@ impl PyBytes {
472473
.collect();
473474
PyTupleRef::with_elements(param, &vm.ctx)
474475
}
476+
477+
#[pymethod(magic)]
478+
fn reduce_ex(
479+
zelf: PyRef<Self>,
480+
_proto: usize,
481+
vm: &VirtualMachine,
482+
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
483+
Self::reduce(zelf, vm)
484+
}
485+
486+
#[pymethod(magic)]
487+
fn reduce(
488+
zelf: PyRef<Self>,
489+
vm: &VirtualMachine,
490+
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
491+
let bytes = PyBytes::from(zelf.inner.elements.clone()).into_pyobject(vm);
492+
(
493+
zelf.as_object().clone_class(),
494+
PyTupleRef::with_elements(vec![bytes], &vm.ctx),
495+
zelf.as_object().dict(),
496+
)
497+
}
475498
}
476499

477500
impl BufferProtocol for PyBytes {

0 commit comments

Comments
 (0)