Commit bfd334a4 authored by Raymond Hettinger's avatar Raymond Hettinger

Extend temporary hashability to remove() and discard().

Brings the functionality back in line with sets.py.
parent 5a5b2430
...@@ -182,12 +182,22 @@ class TestSet(TestJointOps): ...@@ -182,12 +182,22 @@ class TestSet(TestJointOps):
self.assert_('a' not in self.s) self.assert_('a' not in self.s)
self.assertRaises(KeyError, self.s.remove, 'Q') self.assertRaises(KeyError, self.s.remove, 'Q')
self.assertRaises(TypeError, self.s.remove, []) 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): def test_discard(self):
self.s.discard('a') self.s.discard('a')
self.assert_('a' not in self.s) self.assert_('a' not in self.s)
self.s.discard('Q') self.s.discard('Q')
self.assertRaises(TypeError, self.s.discard, []) 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): def test_pop(self):
for i in xrange(len(self.s)): for i in xrange(len(self.s)):
......
...@@ -73,6 +73,21 @@ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -73,6 +73,21 @@ set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return make_new_set(type, NULL); 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 static void
set_dealloc(PySetObject *so) set_dealloc(PySetObject *so)
{ {
...@@ -104,20 +119,16 @@ set_len(PySetObject *so) ...@@ -104,20 +119,16 @@ set_len(PySetObject *so)
static int static int
set_contains(PySetObject *so, PyObject *key) set_contains(PySetObject *so, PyObject *key)
{ {
PyObject *olddict; PyObject *tmp;
PySetObject *tmp;
int result; int result;
result = PySequence_Contains(so->data, key); result = PySequence_Contains(so->data, key);
if (result == -1 && PyType_IsSubtype(key->ob_type, &PySet_Type)) { if (result == -1 && PyType_IsSubtype(key->ob_type, &PySet_Type)) {
PyErr_Clear(); PyErr_Clear();
tmp = (PySetObject *)make_new_set(&PyFrozenSet_Type, NULL); tmp = frozenset_dict_wrapper(((PySetObject *)(key))->data);
if (tmp == NULL) if (tmp == NULL)
return -1; return -1;
olddict = tmp->data; result = PySequence_Contains(so->data, tmp);
tmp->data = ((PySetObject *)(key))->data;
result = PySequence_Contains(so->data, (PyObject *)tmp);
tmp->data = olddict;
Py_DECREF(tmp); Py_DECREF(tmp);
} }
return result; return result;
...@@ -820,8 +831,21 @@ This has no effect if the element is already present."); ...@@ -820,8 +831,21 @@ This has no effect if the element is already present.");
static PyObject * static PyObject *
set_remove(PySetObject *so, PyObject *item) set_remove(PySetObject *so, PyObject *item)
{ {
if (PyDict_DelItem(so->data, item) == -1) PyObject *tmp;
return NULL;
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); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
...@@ -834,11 +858,28 @@ If the element is not a member, raise a KeyError."); ...@@ -834,11 +858,28 @@ If the element is not a member, raise a KeyError.");
static PyObject * static PyObject *
set_discard(PySetObject *so, PyObject *item) set_discard(PySetObject *so, PyObject *item)
{ {
PyObject *tmp;
if (PyDict_DelItem(so->data, item) == -1) { if (PyDict_DelItem(so->data, item) == -1) {
if (PyErr_ExceptionMatches(PyExc_KeyError)) if (PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_Clear(); PyErr_Clear();
else else {
return NULL; 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); Py_INCREF(Py_None);
return Py_None; return Py_None;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment