Index: Objects/dictobject.c =================================================================== --- Objects/dictobject.c (revision 83091) +++ Objects/dictobject.c (working copy) @@ -2807,7 +2807,55 @@ (binaryfunc)dictviews_or, /*nb_or*/ }; +/* isdisjoint for dict_keys and dict_items */ +static PyObject* +dictviews_isdisjoint(PyObject *self, PyObject *other) +{ + PyObject *it; + PyObject *item=NULL; + int contains; + + assert(self != NULL); + assert(PyDictViewSet_Check(self)); + assert(other != NULL); + + if (self == other) { + if (dictview_len((dictviewobject *)self) == 0) { + Py_RETURN_TRUE; + } + else { + Py_RETURN_FALSE; + } + } + + it = PyObject_GetIter(other); + if (it == NULL) { + return NULL; + } + + while ((item = PyIter_Next(it)) != NULL) { + contains = PySequence_Contains(self, item); + Py_DECREF(item); + if (contains == -1) { + Py_DECREF(it); + return NULL; + } + + if (contains) { + Py_DECREF(it); + Py_RETURN_FALSE; + } + } + Py_DECREF(it); + Py_RETURN_TRUE; +} + +PyDoc_STRVAR(isdisjoint_doc, +"Return True if the view and the given iterable have a null intersection."); + static PyMethodDef dictkeys_methods[] = { + {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, + isdisjoint_doc}, {NULL, NULL} /* sentinel */ }; @@ -2892,6 +2940,8 @@ }; static PyMethodDef dictitems_methods[] = { + {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, + isdisjoint_doc}, {NULL, NULL} /* sentinel */ }; Index: Lib/test/test_dictviews.py =================================================================== --- Lib/test/test_dictviews.py (revision 83091) +++ Lib/test/test_dictviews.py (working copy) @@ -112,6 +112,16 @@ self.assertEqual(d1.keys() ^ set(d3.keys()), {'a', 'b', 'd', 'e'}) + # issue 9212: test dict_keys.isdisjoint: + self.assertFalse(d1.keys().isdisjoint(d1.keys())) + self.assertFalse(d1.keys().isdisjoint(d2.keys())) + self.assertTrue(d1.keys().isdisjoint({'x', 'y'})) + self.assertTrue(d1.keys().isdisjoint(d3.keys())) + + de = {} + self.assertTrue(de.keys().isdisjoint(set())) + self.assertTrue(de.keys().isdisjoint(de.keys())) + def test_items_set_operations(self): d1 = {'a': 1, 'b': 2} d2 = {'a': 2, 'b': 2} @@ -144,7 +154,17 @@ self.assertEqual(d1.items() ^ d3.items(), {('a', 1), ('b', 2), ('d', 4), ('e', 5)}) + # issue 9212: test dict_items.isdisjoint: + self.assertFalse(d1.items().isdisjoint(d1.items())) + self.assertFalse(d1.items().isdisjoint(d2.items())) + self.assertTrue(d1.items().isdisjoint({'x', 'y'})) + self.assertTrue(d1.items().isdisjoint(d3.items())) + de = {} + self.assertTrue(de.items().isdisjoint(set())) + self.assertTrue(de.items().isdisjoint(de.items())) + + def test_main(): support.run_unittest(DictSetTest)