diff --git a/Lib/test/test_isinstance.py b/Lib/test/test_isinstance.py --- a/Lib/test/test_isinstance.py +++ b/Lib/test/test_isinstance.py @@ -82,7 +82,21 @@ class TestIsInstanceExceptions(unittest. 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() diff --git a/Objects/abstract.c b/Objects/abstract.c --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2235,7 +2235,12 @@ recursive_isinstance(PyObject *inst, PyO 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) && @@ -2273,8 +2278,12 @@ recursive_isinstance(PyObject *inst, PyO 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);