[Python-checkins] CVS: python/dist/src/Python ceval.c,2.273,2.274

Guido van Rossum gvanrossum@users.sourceforge.net
Wed, 12 Sep 2001 12:19:20 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv28674

Modified Files:
	ceval.c 
Log Message:
build_class(): one more (hopefully the last) step on the way to
backwards compatibility.  When using the class of the first base as
the metaclass, use its __class__ attribute in preference over its
ob_type slot.  This ensures that we can still use classic classes as
metaclasse, as shown in the original "Metaclasses" essay.  This also
makes all the examples in Demo/metaclasses/ work again (maybe these
should be turned into a test suite?).


Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.273
retrieving revision 2.274
diff -C2 -d -r2.273 -r2.274
*** ceval.c	2001/09/04 19:03:35	2.273
--- ceval.c	2001/09/12 19:19:18	2.274
***************
*** 3501,3523 ****
  build_class(PyObject *methods, PyObject *bases, PyObject *name)
  {
! 	PyObject *metaclass = NULL;
  
  	if (PyDict_Check(methods))
  		metaclass = PyDict_GetItemString(methods, "__metaclass__");
! 
! 	if (metaclass == NULL) {
! 		if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0)
! 			metaclass = (PyObject *)
! 				PyTuple_GET_ITEM(bases, 0)->ob_type;
! 		else {
! 			PyObject *g = PyEval_GetGlobals();
! 			if (g != NULL && PyDict_Check(g))
! 				metaclass = PyDict_GetItemString(
! 					g, "__metaclass__");
! 			if (metaclass == NULL)
! 				metaclass = (PyObject *) &PyClass_Type;
  		}
  	}
! 	return PyObject_CallFunction(metaclass, "OOO", name, bases, methods);
  }
  
--- 3501,3530 ----
  build_class(PyObject *methods, PyObject *bases, PyObject *name)
  {
! 	PyObject *metaclass = NULL, *result, *base;
  
  	if (PyDict_Check(methods))
  		metaclass = PyDict_GetItemString(methods, "__metaclass__");
! 	if (metaclass != NULL)
! 		Py_INCREF(methods);
! 	else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
! 		base = PyTuple_GET_ITEM(bases, 0);
! 		metaclass = PyObject_GetAttrString(base, "__class__");
! 		if (metaclass == NULL) {
! 			PyErr_Clear();
! 			metaclass = (PyObject *)base->ob_type;
! 			Py_INCREF(metaclass);
  		}
  	}
! 	else {
! 		PyObject *g = PyEval_GetGlobals();
! 		if (g != NULL && PyDict_Check(g))
! 			metaclass = PyDict_GetItemString(g, "__metaclass__");
! 		if (metaclass == NULL)
! 			metaclass = (PyObject *) &PyClass_Type;
! 		Py_INCREF(metaclass);
! 	}
! 	result = PyObject_CallFunction(metaclass, "OOO", name, bases, methods);
! 	Py_DECREF(metaclass);
! 	return result;
  }