Index: Objects/abstract.c =================================================================== --- Objects/abstract.c (revision 82887) +++ Objects/abstract.c (working copy) @@ -2508,7 +2508,12 @@ if (retval == 0) { PyObject *c = PyObject_GetAttr(inst, __class__); if (c == NULL) { - PyErr_Clear(); + if(PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + else { + retval = -1; + } } else { if (c != (PyObject *)(inst->ob_type) && @@ -2526,8 +2531,12 @@ return -1; icls = PyObject_GetAttr(inst, __class__); if (icls == NULL) { - PyErr_Clear(); - retval = 0; + if(PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } + else { + retval = -1; + } } else { retval = abstract_issubclass(icls, cls); Index: Lib/test/test_isinstance.py =================================================================== --- Lib/test/test_isinstance.py (revision 82887) +++ Lib/test/test_isinstance.py (working copy) @@ -81,7 +81,21 @@ self.assertRaises(TypeError, isinstance, I(), C()) + # check that we don't mask non AttributeErrors + # see: http://bugs.python.org/issue1574217 + def test_isinstance_dont_mask_non_attribute_error(self): + class C(object): + def getclass(self): + raise RuntimeError() + __class__=property(getclass) + c=C() + self.assertRaises(RuntimeError, isinstance, c, bool) + + # test another code path + class D: pass + self.assertRaises(RuntimeError, isinstance, c, D) + # These tests are similar to above, but tickle certain code paths in # issubclass() instead of isinstance() -- really PyObject_IsSubclass()