diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index b00c433b3..287cb77d5 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -258,8 +258,6 @@ class TestJointOps: it = pickle.loads(d) self.assertEqual(self.thetype(it), data - self.thetype((drop,))) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_deepcopy(self): class Tracer: def __init__(self, value): @@ -673,8 +671,6 @@ class TestSetSubclass(TestSet): thetype = SetSubclass basetype = set - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_pickling(self): super().test_pickling() @@ -688,8 +684,6 @@ class SetSubclassWithKeywordArgs(set): set.__init__(self, iterable) class TestSetSubclassWithKeywordArgs(TestSet): - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_keywords_in_subclass(self): 'SF bug #1486663 -- this used to erroneously raise a TypeError' SetSubclassWithKeywordArgs(newarg=1) @@ -787,8 +781,6 @@ class TestFrozenSetSubclass(TestFrozenSet): thetype = FrozenSetSubclass basetype = frozenset - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_pickling(self): super().test_pickling() @@ -1591,8 +1583,6 @@ class TestCopyingSingleton(TestCopying, unittest.TestCase): def setUp(self): self.set = set(["hello"]) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_deep_copy(self): super().test_deep_copy() @@ -1602,8 +1592,6 @@ class TestCopyingTriple(TestCopying, unittest.TestCase): def setUp(self): self.set = set(["zero", 0, None]) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_deep_copy(self): super().test_deep_copy() @@ -1613,8 +1601,6 @@ class TestCopyingTuple(TestCopying, unittest.TestCase): def setUp(self): self.set = set([(1, 2)]) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_deep_copy(self): super().test_deep_copy() @@ -1624,8 +1610,6 @@ class TestCopyingNested(TestCopying, unittest.TestCase): def setUp(self): self.set = set([((1, 2), (3, 4))]) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_deep_copy(self): super().test_deep_copy() diff --git a/vm/src/builtins/set.rs b/vm/src/builtins/set.rs index b0d4d0ee9..3ed14f6f9 100644 --- a/vm/src/builtins/set.rs +++ b/vm/src/builtins/set.rs @@ -1,11 +1,11 @@ /* * Builtin set type with a sequence of unique items. */ -use super::pytype::PyTypeRef; +use super::{pytype::PyTypeRef, PyDictRef}; use crate::common::hash::PyHash; use crate::common::rc::PyRc; use crate::dictdatatype; -use crate::function::{Args, OptionalArg}; +use crate::function::{Args, FuncArgs, OptionalArg}; use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable}; use crate::vm::{ReprGuard, VirtualMachine}; use crate::{ @@ -113,7 +113,7 @@ impl PySetInner { } else { (self, other) }; - for key in subset.content.keys() { + for key in subset.elements() { if !superset.contains(&key, vm)? { return Ok(false); } @@ -155,7 +155,7 @@ impl PySetInner { // We want to remove duplicates in other let other_set = Self::new(other, vm)?; - for item in other_set.content.keys() { + for item in other_set.elements() { new_inner.content.delete_or_insert(vm, &item, ())? } @@ -193,14 +193,14 @@ impl PySetInner { PySetIterator { dict: PyRc::clone(&self.content), - elements: self.content.keys(), + elements: self.elements(), size_info: AtomicCell::new(set_size), } } fn repr(&self, vm: &VirtualMachine) -> PyResult { let mut str_parts = Vec::with_capacity(self.content.len()); - for key in self.content.keys() { + for key in self.elements() { let part = vm.to_repr(&key)?; str_parts.push(part.as_str().to_owned()); } @@ -224,6 +224,10 @@ impl PySetInner { self.content.clear() } + fn elements(&self) -> Vec { + self.content.keys() + } + fn pop(&self, vm: &VirtualMachine) -> PyResult { // TODO: should be pop_front, but that requires rearranging every index if let Some((key, _)) = self.content.pop_back() { @@ -275,7 +279,7 @@ impl PySetInner { for iterable in others { // We want to remove duplicates in iterable let iterable_set = Self::new(iterable, vm)?; - for item in iterable_set.content.keys() { + for item in iterable_set.elements() { self.content.delete_or_insert(vm, &item, ())?; } } @@ -283,7 +287,7 @@ impl PySetInner { } fn hash(&self, vm: &VirtualMachine) -> PyResult { - crate::utils::hash_iter_unordered(self.content.keys().iter(), vm) + crate::utils::hash_iter_unordered(self.elements().iter(), vm) } // Run operation, on failure, if item is a set/set subclass, convert it @@ -331,6 +335,21 @@ fn extract_set(obj: &PyObjectRef) -> Option<&PySetInner> { }) } +fn reduce_set( + zelf: &PyObjectRef, + vm: &VirtualMachine, +) -> PyResult<(PyTypeRef, PyObjectRef, Option)> { + Ok(( + zelf.clone_class(), + vm.ctx.new_tuple(vec![vm.ctx.new_list( + extract_set(zelf) + .unwrap_or(&PySetInner::default()) + .elements(), + )]), + zelf.dict(), + )) +} + macro_rules! multi_args_set { ($vm:expr, $others:expr, $zelf:expr, $op:tt) => {{ let mut res = $zelf.inner.copy(); @@ -344,11 +363,7 @@ macro_rules! multi_args_set { #[pyimpl(with(Hashable, Comparable, Iterable), flags(BASETYPE))] impl PySet { #[pyslot] - fn tp_new( - cls: PyTypeRef, - _iterable: OptionalArg, - vm: &VirtualMachine, - ) -> PyResult> { + fn tp_new(cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult> { PySet::default().into_ref_with_type(vm, cls) } @@ -543,6 +558,14 @@ impl PySet { .symmetric_difference_update(iterable.iterable, vm)?; Ok(zelf.as_object().clone()) } + + #[pymethod(magic)] + fn reduce( + zelf: PyRef, + vm: &VirtualMachine, + ) -> PyResult<(PyTypeRef, PyObjectRef, Option)> { + reduce_set(&zelf.into_object(), vm) + } } impl Comparable for PySet { @@ -719,6 +742,14 @@ impl PyFrozenSet { }; Ok(vm.ctx.new_str(s)) } + + #[pymethod(magic)] + fn reduce( + zelf: PyRef, + vm: &VirtualMachine, + ) -> PyResult<(PyTypeRef, PyObjectRef, Option)> { + reduce_set(&zelf.into_object(), vm) + } } impl Hashable for PyFrozenSet {