summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2003-11-22 03:55:23 (GMT)
committerRaymond Hettinger <python@rcn.com>2003-11-22 03:55:23 (GMT)
commitbfd334a42d35e58369e3a53e16733234e2741975 (patch)
tree321b419c239c475b52fb6272f0a0b26e8de1fb7d
parent5a5b243043aacd6c4ba2b06089cc255075ddc262 (diff)
downloadcpython-bfd334a42d35e58369e3a53e16733234e2741975.zip
cpython-bfd334a42d35e58369e3a53e16733234e2741975.tar.gz
cpython-bfd334a42d35e58369e3a53e16733234e2741975.tar.bz2
Extend temporary hashability to remove() and discard().
Brings the functionality back in line with sets.py.
-rw-r--r--Lib/test/test_set.py10
-rw-r--r--Objects/setobject.c63
2 files changed, 62 insertions, 11 deletions
diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py
index 3203d51..85f87f7 100644
--- a/Lib/test/test_set.py
+++ b/Lib/test/test_set.py
@@ -182,12 +182,22 @@ class TestSet(TestJointOps):
self.assert_('a' not in self.s)
self.assertRaises(KeyError, self.s.remove, 'Q')
self.assertRaises(TypeError, self.s.remove, [])
+ s = self.thetype([frozenset(self.word)])
+ self.assert_(self.thetype(self.word) in s)
+ s.remove(self.thetype(self.word))
+ self.assert_(self.thetype(self.word) not in s)
+ self.assertRaises(KeyError, self.s.remove, self.thetype(self.word))
def test_discard(self):
self.s.discard('a')
self.assert_('a' not in self.s)
self.s.discard('Q')
self.assertRaises(TypeError, self.s.discard, [])
+ s = self.thetype([frozenset(self.word)])
+ self.assert_(self.thetype(self.word) in s)
+ s.discard(self.thetype(self.word))
+ self.assert_(self.thetype(self.word) not in s)
+ s.discard(self.thetype(self.word))
def test_pop(self):
for i in xrange(len(self.s)):
diff --git a/Objects/setobject.c b/Objects/setobject.c
index 2d77c74..be73954 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -73,6 +73,21 @@ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return make_new_set(type, NULL);
}
+static PyObject *
+frozenset_dict_wrapper(PyObject *d)
+{
+ PySetObject *w;
+
+ assert(PyDict_Check(d));
+ w = (PySetObject *)make_new_set(&PyFrozenSet_Type, NULL);
+ if (w == NULL)
+ return NULL;
+ Py_DECREF(w->data);
+ Py_INCREF(d);
+ w->data = d;
+ return (PyObject *)w;
+}
+
static void
set_dealloc(PySetObject *so)
{
@@ -104,20 +119,16 @@ set_len(PySetObject *so)
static int
set_contains(PySetObject *so, PyObject *key)
{
- PyObject *olddict;
- PySetObject *tmp;
+ PyObject *tmp;
int result;
result = PySequence_Contains(so->data, key);
if (result == -1 && PyType_IsSubtype(key->ob_type, &PySet_Type)) {
PyErr_Clear();
- tmp = (PySetObject *)make_new_set(&PyFrozenSet_Type, NULL);
+ tmp = frozenset_dict_wrapper(((PySetObject *)(key))->data);
if (tmp == NULL)
return -1;
- olddict = tmp->data;
- tmp->data = ((PySetObject *)(key))->data;
- result = PySequence_Contains(so->data, (PyObject *)tmp);
- tmp->data = olddict;
+ result = PySequence_Contains(so->data, tmp);
Py_DECREF(tmp);
}
return result;
@@ -820,8 +831,21 @@ This has no effect if the element is already present.");
static PyObject *
set_remove(PySetObject *so, PyObject *item)
{
- if (PyDict_DelItem(so->data, item) == -1)
- return NULL;
+ PyObject *tmp;
+
+ if (PyDict_DelItem(so->data, item) == -1) {
+ if (!PyType_IsSubtype(item->ob_type, &PySet_Type))
+ return NULL;
+ PyErr_Clear();
+ tmp = frozenset_dict_wrapper(((PySetObject *)(item))->data);
+ if (tmp == NULL)
+ return NULL;
+ if (PyDict_DelItem(so->data, tmp) == -1) {
+ Py_DECREF(tmp);
+ return NULL;
+ }
+ Py_DECREF(tmp);
+ }
Py_INCREF(Py_None);
return Py_None;
}
@@ -834,11 +858,28 @@ If the element is not a member, raise a KeyError.");
static PyObject *
set_discard(PySetObject *so, PyObject *item)
{
+ PyObject *tmp;
+
if (PyDict_DelItem(so->data, item) == -1) {
if (PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_Clear();
- else
- return NULL;
+ else {
+ if (!PyType_IsSubtype(item->ob_type, &PySet_Type))
+ return NULL;
+ PyErr_Clear();
+ tmp = frozenset_dict_wrapper(((PySetObject *)(item))->data);
+ if (tmp == NULL)
+ return NULL;
+ if (PyDict_DelItem(so->data, tmp) == -1) {
+ if (PyErr_ExceptionMatches(PyExc_KeyError))
+ PyErr_Clear();
+ else {
+ Py_DECREF(tmp);
+ return NULL;
+ }
+ }
+ Py_DECREF(tmp);
+ }
}
Py_INCREF(Py_None);
return Py_None;