Index: Doc/lib/libfuncs.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/lib/libfuncs.tex,v retrieving revision 1.158 diff -u -r1.158 libfuncs.tex --- Doc/lib/libfuncs.tex 17 Dec 2003 20:43:32 -0000 1.158 +++ Doc/lib/libfuncs.tex 18 Dec 2003 21:35:50 -0000 @@ -552,11 +552,9 @@ \var{object} is an object of that type. If \var{object} is not a class instance or an object of the given type, the function always returns false. If \var{classinfo} is neither a class object nor a - type object, it may be a tuple of class or type objects, or may - recursively contain other such tuples (other sequence types are not - accepted). If \var{classinfo} is not a class, type, or tuple of - classes, types, and such tuples, a \exception{TypeError} exception - is raised. + type object, it may be a tuple of class or type objects. If + \var{classinfo} is not a class, type, or tuple of + classes and types, a \exception{TypeError} exception is raised. \versionchanged[Support for a tuple of type information was added]{2.2} \end{funcdesc} Index: Objects/abstract.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/abstract.c,v retrieving revision 2.120 diff -u -r2.120 abstract.c --- Objects/abstract.c 27 Oct 2003 09:22:16 -0000 2.120 +++ Objects/abstract.c 18 Dec 2003 21:35:50 -0000 @@ -2042,11 +2042,9 @@ static PyObject *__class__ = NULL; int retval = 0; - if (__class__ == NULL) { - __class__ = PyString_FromString("__class__"); - if (__class__ == NULL) - return -1; - } + __class__ = PyString_FromString("__class__"); + if (__class__ == NULL) + return -1; if (PyClass_Check(cls) && PyInstance_Check(inst)) { PyObject *inclass = @@ -2071,16 +2069,23 @@ } } else if (PyTuple_Check(cls)) { - /* Not a general sequence -- that opens up the road to - recursion and stack overflow. */ int i, n; + PyObject *item = NULL; n = PyTuple_GET_SIZE(cls); for (i = 0; i < n; i++) { - retval = PyObject_IsInstance( - inst, PyTuple_GET_ITEM(cls, i)); - if (retval != 0) - break; + item = PyTuple_GET_ITEM(cls, i); + if (PyClass_Check(item) || PyType_Check(item)) { + retval = PyObject_IsInstance(inst, item); + if (retval != 0) + break; + } + else { + PyErr_SetString(PyExc_TypeError, + "isinstance() arg 2 must be a class, type," + " or tuple of classes and types"); + return -1; + } } } else { @@ -2115,13 +2120,25 @@ if (PyTuple_Check(cls)) { int i; int n = PyTuple_GET_SIZE(cls); + PyObject *item = NULL; + for (i = 0; i < n; ++i) { - retval = PyObject_IsSubclass( - derived, PyTuple_GET_ITEM(cls, i)); - if (retval != 0) { + item = PyTuple_GET_ITEM(cls, i); + if (PyClass_Check(item) || + PyType_Check(item)) { + retval = PyObject_IsSubclass( + derived, item); + if (retval != 0) { /* either found it, or got an error */ return retval; + } } + else { + PyErr_SetString(PyExc_TypeError, + "issubclass() arg 2 must be a class" + " or tuple of classes"); + return -1; + } } return 0; } Index: Python/bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.305 diff -u -r2.305 bltinmodule.c --- Python/bltinmodule.c 17 Dec 2003 20:43:33 -0000 2.305 +++ Python/bltinmodule.c 18 Dec 2003 21:35:51 -0000 @@ -1920,7 +1920,8 @@ Return whether an object is an instance of a class or of a subclass thereof.\n\ With a type as second argument, return whether that is the object's type.\n\ The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for\n\ -isinstance(x, A) or isinstance(x, B) or ... (etc.)."); +isinstance(x, A) or isinstance(x, B) or ... (etc.) but requires the tuple\n\ +to consistent of only classes and types."); static PyObject * @@ -1944,7 +1945,8 @@ \n\ Return whether class C is a subclass (i.e., a derived class) of class B.\n\ When using a tuple as the second argument issubclass(X, (A, B, ...)),\n\ -is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.)."); +is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.)\n\ +and requires that the tuple only consist of classes and types."); static PyObject* Index: Lib/test/test_isinstance.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_isinstance.py,v retrieving revision 1.7 diff -u -r1.7 test_isinstance.py --- Lib/test/test_isinstance.py 1 May 2003 17:45:37 -0000 1.7 +++ Lib/test/test_isinstance.py 18 Dec 2003 21:35:51 -0000 @@ -6,7 +6,7 @@ from test import test_support - + class TestIsInstanceExceptions(unittest.TestCase): # Test to make sure that an AttributeError when accessing the instance's # class's bases is masked. This was actually a bug in Python 2.2 and @@ -204,6 +204,10 @@ self.assertEqual(False, isinstance(AbstractChild(), Super)) self.assertEqual(False, isinstance(AbstractChild(), Child)) + def test_isinstance_tuple(self): + self.assertEqual(True, isinstance(Super(), (Child, Super))) + self.assertRaises(TypeError, isinstance, Super(), (Child, (Super, ))) + def test_subclass_normal(self): # normal classes self.assertEqual(True, issubclass(Super, Super)) @@ -232,21 +236,20 @@ self.assertEqual(False, issubclass(Super, (Child,))) self.assertEqual(True, issubclass(Super, (Child, Super))) self.assertEqual(False, issubclass(Child, ())) - self.assertEqual(True, issubclass(Super, (Child, (Super,)))) + self.assertRaises(TypeError, issubclass, Super, (Child, (Super,))) self.assertEqual(True, issubclass(NewChild, (NewChild,))) self.assertEqual(True, issubclass(NewChild, (NewSuper,))) self.assertEqual(False, issubclass(NewSuper, (NewChild,))) self.assertEqual(True, issubclass(NewSuper, (NewChild, NewSuper))) self.assertEqual(False, issubclass(NewChild, ())) - self.assertEqual(True, issubclass(NewSuper, (NewChild, (NewSuper,)))) + self.assertRaises(TypeError, issubclass, NewSuper, (NewChild, (NewSuper,))) - self.assertEqual(True, issubclass(int, (long, (float, int)))) - self.assertEqual(True, issubclass(str, (unicode, (Child, NewChild, basestring)))) + self.assertRaises(TypeError, issubclass, int, (long, (float, int))) + self.assertRaises(TypeError, issubclass, str, (unicode, (Child, NewChild, basestring))) - def test_main(): test_support.run_unittest( TestIsInstanceExceptions,