mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	Move the code implementing isinstance() and issubclass() to new C
APIs, PyObject_IsInstance() and PyObject_IsSubclass() -- both returning an int, or -1 for errors.
This commit is contained in:
		
							parent
							
								
									91751143eb
								
							
						
					
					
						commit
						823649d544
					
				
					 3 changed files with 125 additions and 96 deletions
				
			
		|  | @ -1626,3 +1626,115 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...) | |||
| 
 | ||||
| 	return retval; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* isinstance(), issubclass() */ | ||||
| 
 | ||||
| static int | ||||
| abstract_issubclass(PyObject *derived, PyObject *cls, int first) | ||||
| { | ||||
| 	static PyObject *__bases__ = NULL; | ||||
| 	PyObject *bases; | ||||
| 	int i, n; | ||||
| 	int r = 0; | ||||
| 
 | ||||
| 	if (__bases__ == NULL) { | ||||
| 		__bases__ = PyString_FromString("__bases__"); | ||||
| 		if (__bases__ == NULL) | ||||
| 			return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (first) { | ||||
| 		bases = PyObject_GetAttr(cls, __bases__); | ||||
| 		if (bases == NULL || !PyTuple_Check(bases)) { | ||||
| 			Py_XDECREF(bases); | ||||
| 			PyErr_SetString(PyExc_TypeError, | ||||
| 					"issubclass() arg 2 must be a class"); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		Py_DECREF(bases); | ||||
| 	} | ||||
| 
 | ||||
| 	if (derived == cls) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	bases = PyObject_GetAttr(derived, __bases__); | ||||
| 	if (bases == NULL || !PyTuple_Check(bases)) { | ||||
| 	        Py_XDECREF(bases); | ||||
| 		PyErr_SetString(PyExc_TypeError, | ||||
| 				"issubclass() arg 1 must be a class"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	n = PyTuple_GET_SIZE(bases); | ||||
| 	for (i = 0; i < n; i++) { | ||||
| 		r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls, 0); | ||||
| 		if (r != 0) | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	Py_DECREF(bases); | ||||
| 
 | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| PyObject_IsInstance(PyObject *inst, PyObject *cls) | ||||
| { | ||||
| 	PyObject *icls; | ||||
| 	static PyObject *__class__ = NULL; | ||||
| 	int retval = 0; | ||||
| 
 | ||||
|         if (PyClass_Check(cls)) { | ||||
| 		if (PyInstance_Check(inst)) { | ||||
| 			PyObject *inclass = | ||||
| 				(PyObject*)((PyInstanceObject*)inst)->in_class; | ||||
| 			retval = PyClass_IsSubclass(inclass, cls); | ||||
| 		} | ||||
| 	} | ||||
| 	else if (PyType_Check(cls)) { | ||||
| 		retval = ((PyObject *)(inst->ob_type) == cls); | ||||
| 	} | ||||
| 	else if (!PyInstance_Check(inst)) { | ||||
| 		if (__class__ == NULL) { | ||||
| 			__class__ = PyString_FromString("__class__"); | ||||
| 			if (__class__ == NULL) | ||||
| 				return -1; | ||||
| 		} | ||||
| 		icls = PyObject_GetAttr(inst, __class__); | ||||
| 		if (icls != NULL) { | ||||
| 			retval = abstract_issubclass(icls, cls, 1); | ||||
| 			Py_DECREF(icls); | ||||
| 			if (retval < 0 && | ||||
| 			    !PyErr_ExceptionMatches(PyExc_TypeError)) | ||||
| 				return -1; | ||||
| 		} | ||||
| 		else | ||||
| 			retval = -1; | ||||
| 	} | ||||
| 	else | ||||
| 		retval = -1; | ||||
| 
 | ||||
| 	if (retval < 0) { | ||||
| 		PyErr_SetString(PyExc_TypeError, | ||||
| 				"isinstance() arg 2 must be a class or type"); | ||||
| 	} | ||||
| 	return retval; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| PyObject_IsSubclass(PyObject *derived, PyObject *cls) | ||||
| { | ||||
| 	int retval; | ||||
| 
 | ||||
| 	if (!PyClass_Check(derived) || !PyClass_Check(cls)) { | ||||
| 		retval = abstract_issubclass(derived, cls, 1); | ||||
| 	} | ||||
| 	else { | ||||
| 		/* shortcut */ | ||||
| 	  	if (!(retval = (derived == cls))) | ||||
| 			retval = PyClass_IsSubclass(derived, cls); | ||||
| 	} | ||||
| 
 | ||||
| 	return retval; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum