mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Extend temporary hashability to remove() and discard().
Brings the functionality back in line with sets.py.
This commit is contained in:
parent
5a5b243043
commit
bfd334a42d
2 changed files with 62 additions and 11 deletions
|
@ -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)
|
||||||
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)
|
||||||
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.");
|
||||||
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;
|
||||||
|
|
||||||
|
if (PyDict_DelItem(so->data, item) == -1) {
|
||||||
|
if (!PyType_IsSubtype(item->ob_type, &PySet_Type))
|
||||||
return NULL;
|
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.");
|
||||||
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 {
|
||||||
|
if (!PyType_IsSubtype(item->ob_type, &PySet_Type))
|
||||||
return NULL;
|
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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue