From ab294199b772e47dd86ca665dbc1080715b844d2 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 13 Aug 2005 02:28:54 +0000 Subject: Teach set modules to correctly compute s-=s and s^=s as the empty set. --- Lib/sets.py | 4 ++++ Lib/test/test_set.py | 12 ++++++++++++ Lib/test/test_sets.py | 13 +++++++++++++ Misc/NEWS | 4 ++++ Objects/setobject.c | 23 +++++++++++++---------- 5 files changed, 46 insertions(+), 10 deletions(-) diff --git a/Lib/sets.py b/Lib/sets.py index 8ec7e2f..32a0dd6 100644 --- a/Lib/sets.py +++ b/Lib/sets.py @@ -480,6 +480,8 @@ class Set(BaseSet): value = True if not isinstance(other, BaseSet): other = Set(other) + if self is other: + self.clear() for elt in other: if elt in data: del data[elt] @@ -497,6 +499,8 @@ class Set(BaseSet): data = self._data if not isinstance(other, BaseSet): other = Set(other) + if self is other: + self.clear() for elt in ifilter(data.has_key, other): del data[elt] diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index b4c7c4f..354db78 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -382,6 +382,18 @@ class TestSet(TestJointOps): else: self.assert_(c not in self.s) + def test_inplace_on_self(self): + t = self.s.copy() + t |= t + self.assertEqual(t, self.s) + t &= t + self.assertEqual(t, self.s) + t -= t + self.assertEqual(t, self.thetype()) + t = self.s.copy() + t ^= t + self.assertEqual(t, self.thetype()) + def test_weakref(self): s = self.thetype('gallahad') p = proxy(s) diff --git a/Lib/test/test_sets.py b/Lib/test/test_sets.py index c5a48b1..ff834e0 100644 --- a/Lib/test/test_sets.py +++ b/Lib/test/test_sets.py @@ -243,6 +243,19 @@ class TestBinaryOps(unittest.TestCase): self.assertRaises(TypeError, cmp, a, 12) self.assertRaises(TypeError, cmp, "abc", a) + def test_inplace_on_self(self): + t = self.set.copy() + t |= t + self.assertEqual(t, self.set) + t &= t + self.assertEqual(t, self.set) + t -= t + self.assertEqual(len(t), 0) + t = self.set.copy() + t ^= t + self.assertEqual(len(t), 0) + + #============================================================================== class TestUpdateOps(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index 0e37a1e..5d58ce9 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,8 @@ Core and builtins __hash__() function. Also, changed set.__contains__() to have identical logic. +- The set() builtin can now properly compute s-=s as an empty set. + - SF bug #1238681: freed pointer is used in longobject.c:long_pow(). - SF bug #1185883: Python's small-object memory allocator took over @@ -58,6 +60,8 @@ Extension Modules Library ------- +- The sets module can now properly compute s-=s and s^=s as an empty set. + - Patch #827386: Support absolute source paths in msvccompiler.py. - Fix a problem in Tkinter introduced by SF patch #869468: delete bogus diff --git a/Objects/setobject.c b/Objects/setobject.c index e77e7cd..0e65320 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -193,6 +193,16 @@ frozenset_copy(PySetObject *so) PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set."); static PyObject * +set_clear(PySetObject *so) +{ + PyDict_Clear(so->data); + so->hash = -1; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); + +static PyObject * set_union(PySetObject *so, PyObject *other) { PySetObject *result; @@ -379,6 +389,9 @@ static PyObject * set_difference_update(PySetObject *so, PyObject *other) { PyObject *item, *tgtdata, *it; + + if ((PyObject *)so == other) + return set_clear(so); it = PyObject_GetIter(other); if (it == NULL) @@ -758,16 +771,6 @@ set_tp_print(PySetObject *so, FILE *fp, int flags) return 0; } -static PyObject * -set_clear(PySetObject *so) -{ - PyDict_Clear(so->data); - so->hash = -1; - Py_RETURN_NONE; -} - -PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); - static int set_tp_clear(PySetObject *so) { -- cgit v0.12