summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2005-08-13 02:28:54 (GMT)
committerRaymond Hettinger <python@rcn.com>2005-08-13 02:28:54 (GMT)
commitab294199b772e47dd86ca665dbc1080715b844d2 (patch)
tree355e719f2cbc756be0d9c8a2943a9056cc304a77
parent787b4c5fea8476a1146918f90a6da7f63d7aa31c (diff)
downloadcpython-ab294199b772e47dd86ca665dbc1080715b844d2.zip
cpython-ab294199b772e47dd86ca665dbc1080715b844d2.tar.gz
cpython-ab294199b772e47dd86ca665dbc1080715b844d2.tar.bz2
Teach set modules to correctly compute s-=s and s^=s as the empty set.
-rw-r--r--Lib/sets.py4
-rw-r--r--Lib/test/test_set.py12
-rw-r--r--Lib/test/test_sets.py13
-rw-r--r--Misc/NEWS4
-rw-r--r--Objects/setobject.c23
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)
{