Implement isinstance(x, (A, B, ...)).  Note that we only allow tuples,
not other sequences (then we'd have to except strings, and we'd still
be susceptible to recursive attacks).
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 4891622..33991a8 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1805,6 +1805,20 @@
 	else if (PyType_Check(cls)) {
 		retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
 	}
+	else if (PyTuple_Check(cls)) {
+		/* Not a general sequence -- that opens up the road to
+		   recursion and stack overflow. */
+		int i, n;
+
+		n = PyTuple_GET_SIZE(cls);
+		for (i = 0; i < n; i++) {
+			retval = PyObject_IsInstance(
+				inst, PyTuple_GET_ITEM(cls, i));
+			if (retval != 0)
+				break;
+		}
+		return retval;
+	}
 	else if (!PyInstance_Check(inst)) {
 		if (__class__ == NULL) {
 			__class__ = PyString_FromString("__class__");
@@ -1827,7 +1841,8 @@
 
 	if (retval < 0) {
 		PyErr_SetString(PyExc_TypeError,
-				"isinstance() arg 2 must be a class or type");
+				"isinstance() arg 2 must be a class or type "
+				"or tuple of those");
 	}
 	return retval;
 }
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 64afb1b..8390b7b 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1641,10 +1641,12 @@
 }
 
 static char isinstance_doc[] =
-"isinstance(object, class-or-type) -> Boolean\n\
+"isinstance(object, class-or-type-or-tuple) -> Boolean\n\
 \n\
 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.";
+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.).";
 
 
 static PyObject *