Skip to content

Commit 774b622

Browse files
committed
Impl __reduce_ex__ with _array_reconstructor
1 parent b1f99bb commit 774b622

File tree

2 files changed

+44
-25
lines changed

2 files changed

+44
-25
lines changed

Lib/test/test_array.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,17 +247,13 @@ def test_deepcopy(self):
247247
self.assertNotEqual(id(a), id(b))
248248
self.assertEqual(a, b)
249249

250-
# TODO: RUSTPYTHON
251-
# @unittest.expectedFailure
252250
def test_reduce_ex(self):
253251
a = array.array(self.typecode, self.example)
254252
for protocol in range(3):
255253
self.assertIs(a.__reduce_ex__(protocol)[0], array.array)
256-
# for protocol in range(3, pickle.HIGHEST_PROTOCOL + 1):
257-
# self.assertIs(a.__reduce_ex__(protocol)[0], array_reconstructor)
254+
for protocol in range(3, pickle.HIGHEST_PROTOCOL + 1):
255+
self.assertIs(a.__reduce_ex__(protocol)[0], array_reconstructor)
258256

259-
# TODO: RUSTPYTHON
260-
# @unittest.expectedFailure
261257
def test_pickle(self):
262258
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
263259
a = array.array(self.typecode, self.example)
@@ -273,8 +269,6 @@ def test_pickle(self):
273269
self.assertEqual(a.x, b.x)
274270
self.assertEqual(type(a), type(b))
275271

276-
# TODO: RUSTPYTHON
277-
# @unittest.expectedFailure
278272
def test_pickle_for_empty_array(self):
279273
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
280274
a = array.array(self.typecode)

stdlib/src/array.rs

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ mod array {
496496
}
497497

498498
macro_rules! impl_array_element {
499-
($(($t:ty, $f_from:path, $f_swap:path, $totype:ty),)*) => {$(
499+
($(($t:ty, $f_from:path, $f_swap:path, $f_to:path),)*) => {$(
500500
impl ArrayElement for $t {
501501
fn try_into_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
502502
$f_from(vm, obj)
@@ -505,23 +505,28 @@ mod array {
505505
$f_swap(self)
506506
}
507507
fn to_object(self, vm: &VirtualMachine) -> PyObjectRef {
508-
<$totype>::from(self).into_object(vm)
508+
$f_to(self).into_object(vm)
509509
}
510510
}
511511
)*};
512512
}
513513

514514
impl_array_element!(
515-
(i8, i8::try_from_object, i8::swap_bytes, PyInt),
516-
(u8, u8::try_from_object, u8::swap_bytes, PyInt),
517-
(i16, i16::try_from_object, i16::swap_bytes, PyInt),
518-
(u16, u16::try_from_object, u16::swap_bytes, PyInt),
519-
(i32, i32::try_from_object, i32::swap_bytes, PyInt),
520-
(u32, u32::try_from_object, u32::swap_bytes, PyInt),
521-
(i64, i64::try_from_object, i64::swap_bytes, PyInt),
522-
(u64, u64::try_from_object, u64::swap_bytes, PyInt),
523-
(f32, f32_try_into_from_object, f32_swap_bytes, PyFloat),
524-
(f64, f64_try_into_from_object, f64_swap_bytes, PyFloat),
515+
(i8, i8::try_from_object, i8::swap_bytes, PyInt::from),
516+
(u8, u8::try_from_object, u8::swap_bytes, PyInt::from),
517+
(i16, i16::try_from_object, i16::swap_bytes, PyInt::from),
518+
(u16, u16::try_from_object, u16::swap_bytes, PyInt::from),
519+
(i32, i32::try_from_object, i32::swap_bytes, PyInt::from),
520+
(u32, u32::try_from_object, u32::swap_bytes, PyInt::from),
521+
(i64, i64::try_from_object, i64::swap_bytes, PyInt::from),
522+
(u64, u64::try_from_object, u64::swap_bytes, PyInt::from),
523+
(
524+
f32,
525+
f32_try_into_from_object,
526+
f32_swap_bytes,
527+
pyfloat_from_f32
528+
),
529+
(f64, f64_try_into_from_object, f64_swap_bytes, PyFloat::from),
525530
);
526531

527532
fn f32_swap_bytes(x: f32) -> f32 {
@@ -540,6 +545,10 @@ mod array {
540545
IntoPyFloat::try_from_object(vm, obj).map(|x| x.to_f64())
541546
}
542547

548+
fn pyfloat_from_f32(value: f32) -> PyFloat {
549+
PyFloat::from(value as f64)
550+
}
551+
543552
impl ArrayElement for WideChar {
544553
fn try_into_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
545554
PyStrRef::try_from_object(vm, obj)?
@@ -1102,20 +1111,36 @@ mod array {
11021111
zelf: PyRef<Self>,
11031112
proto: usize,
11041113
vm: &VirtualMachine,
1105-
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
1106-
Self::reduce(zelf, vm)
1114+
) -> PyResult<(PyObjectRef, PyTupleRef, Option<PyDictRef>)> {
1115+
if proto < 3 {
1116+
return Ok(Self::reduce(zelf, vm));
1117+
}
1118+
let array = zelf.read();
1119+
let cls = zelf.as_object().clone_class().into_object();
1120+
let typecode = vm.ctx.new_str(array.typecode_str());
1121+
let bytes = vm.ctx.new_bytes(array.get_bytes().to_vec());
1122+
let code = MachineFormatCode::from_typecode(array.typecode()).unwrap();
1123+
let code = PyInt::from(u8::from(code)).into_object(vm);
1124+
let module = vm.import("array", None, 0)?;
1125+
let func = vm.get_attribute(module, "_array_reconstructor")?;
1126+
Ok((
1127+
func,
1128+
PyTupleRef::with_elements(vec![cls, typecode, code, bytes], &vm.ctx),
1129+
zelf.as_object().dict(),
1130+
))
11071131
}
11081132

11091133
#[pymethod(magic)]
11101134
fn reduce(
11111135
zelf: PyRef<Self>,
11121136
vm: &VirtualMachine,
1113-
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
1137+
) -> (PyObjectRef, PyTupleRef, Option<PyDictRef>) {
11141138
let array = zelf.read();
1115-
let values = vm.ctx.new_list(array.get_objects(vm));
1139+
let cls = zelf.as_object().clone_class().into_object();
11161140
let typecode = vm.ctx.new_str(array.typecode_str());
1141+
let values = vm.ctx.new_list(array.get_objects(vm));
11171142
(
1118-
zelf.as_object().clone_class(),
1143+
cls,
11191144
PyTupleRef::with_elements(vec![typecode, values], &vm.ctx),
11201145
zelf.as_object().dict(),
11211146
)

0 commit comments

Comments
 (0)