Index: Objects/setobject.c =================================================================== --- Objects/setobject.c (revision 84382) +++ Objects/setobject.c (working copy) @@ -1171,6 +1171,31 @@ PyDoc_STRVAR(clear_doc, "Remove all elements from this set."); +/* Private helper function to check if the */ +int +isinstance_set_abc(PyObject *o) +{ + static PyObject *collections_set_abc = NULL; + PyObject *mod; + + if (PyAnySet_Check(o)) + return 1; + if (collections_set_abc == NULL) { + mod = PyImport_ImportModuleNoBlock("_abcoll"); + if (mod == NULL) { + PyErr_Clear(); + return 0; + } + collections_set_abc = PyObject_GetAttrString(mod, "Set"); + if (collections_set_abc == NULL) { + Py_DECREF(mod); + PyErr_Clear(); + return 0; + } + } + return PyObject_IsInstance(o, collections_set_abc); +} + static PyObject * set_union(PySetObject *so, PyObject *args) { @@ -1204,7 +1229,7 @@ { PySetObject *result; - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1224,7 +1249,7 @@ static PyObject * set_ior(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1377,7 +1402,7 @@ static PyObject * set_and(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1389,7 +1414,7 @@ { PyObject *result; - if (!PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1604,7 +1629,7 @@ static PyObject * set_sub(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1614,7 +1639,7 @@ static PyObject * set_isub(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1708,7 +1733,7 @@ static PyObject * set_xor(PySetObject *so, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1720,7 +1745,7 @@ { PyObject *result; - if (!PyAnySet_Check(other)) { + if (!isinstance_set_abc(other)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } Index: Lib/test/test_collections.py =================================================================== --- Lib/test/test_collections.py (revision 84382) +++ Lib/test/test_collections.py (working copy) @@ -456,6 +456,16 @@ # We should also test the proper behavior of the collection ABCs # as real base classes or mix-in classes. + def test_set_interoperability(self): + # classes inherited from MutableSet should interoperate with regular sets + # Issue #8743 + w = WithSet('abracadabra') + s = set('simsalabim') + self.assertEqual(sorted(s&w), sorted(w&s)) + self.assertEqual(sorted(s|w), sorted(w|s)) + self.assertEqual(sorted(s^w), sorted(w^s)) + self.assertEqual(sorted(s-w), + sorted(WithSet('simsalabim') - set('abracadabra'))) def test_Set(self): for sample in [set, frozenset]: self.assertIsInstance(sample(), Set)