[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.41,2.16.8.42

Guido van Rossum gvanrossum@users.sourceforge.net
Sun, 17 Jun 2001 16:28:33 -0700


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

Modified Files:
      Tag: descr-branch
	typeobject.c 
Log Message:
Test for the Py_TPFLAGS_BASETYPE flag.

Fold type_init() into type_new().

You can now instantiate object() again.


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.41
retrieving revision 2.16.8.42
diff -C2 -r2.16.8.41 -r2.16.8.42
*** typeobject.c	2001/06/16 14:41:40	2.16.8.41
--- typeobject.c	2001/06/17 23:28:31	2.16.8.42
***************
*** 321,347 ****
  }
  
! /* TypeType's initializer; called when a type is subclassed */
  
  staticforward void object_dealloc(PyObject *);
  staticforward int object_init(PyObject *, PyObject *, PyObject *);
  
! static int
! type_init(PyObject *self, PyObject *args, PyObject *kwds)
  {
! 	PyObject *name, *bases, *dict, *slots;
! 	PyTypeObject *type, *base;
  	static char *kwlist[] = {"name", "bases", "dict", 0};
  	etype *et;
  	struct memberlist *mp;
! 	int i, nbases, nslots, slotoffset, allocsize;
! 
! 	assert(PyType_Check(self));
! 	type = (PyTypeObject *)self;
  
! 	/* Check this is a virginal type object */
! 	if (type->tp_dict != NULL) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"can't re-initialize type objects");
! 		return -1;
  	}
  
--- 321,386 ----
  }
  
! static int
! extra_ivars(PyTypeObject *type, PyTypeObject *base)
! {
! 	int t_size = type->tp_basicsize;
! 	int b_size = base->tp_basicsize;
! 
! 	assert((type->tp_flags & Py_TPFLAGS_GC) >=
! 	       (base->tp_flags & Py_TPFLAGS_GC)); /* base has GC, type not! */
! 	if (type->tp_flags & Py_TPFLAGS_GC)
! 		t_size -= PyGC_HEAD_SIZE;
! 	if (base->tp_flags & Py_TPFLAGS_GC)
! 		b_size -= PyGC_HEAD_SIZE;
! 	assert(t_size >= b_size); /* type smaller than base! */
! 	if (type->tp_itemsize || base->tp_itemsize) {
! 		/* If itemsize is involved, stricter rules */
! 		return t_size != b_size ||
! 			type->tp_itemsize != base->tp_itemsize;
! 	}
! 	if (t_size == b_size)
! 		return 0;
! 	if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 &&
! 	    type->tp_dictoffset == b_size &&
! 	    t_size == b_size + sizeof(PyObject *))
! 		return 0; /* "Forgive" adding a __dict__ only */
! 	return 1;
! }
! 
! static PyTypeObject *
! solid_base(PyTypeObject *type)
! {
! 	PyTypeObject *base;
  
+ 	if (type->tp_base)
+ 		base = solid_base(type->tp_base);
+ 	else
+ 		base = &PyBaseObject_Type;
+ 	if (extra_ivars(type, base))
+ 		return type;
+ 	else
+ 		return base;
+ }
+ 
  staticforward void object_dealloc(PyObject *);
  staticforward int object_init(PyObject *, PyObject *, PyObject *);
  
! static PyObject *
! type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
  {
! 	PyObject *name, *bases, *dict;
  	static char *kwlist[] = {"name", "bases", "dict", 0};
+ 	PyObject *slots;
+ 	PyTypeObject *type, *base;
  	etype *et;
  	struct memberlist *mp;
! 	int i, nbases, nslots, slotoffset;
  
! 	if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
! 	    (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) {
! 		/* type(x) -> x.__class__ */
! 		PyObject *x = PyTuple_GET_ITEM(args, 0);
! 		Py_INCREF(x->ob_type);
! 		return (PyObject *) x->ob_type;
  	}
  
***************
*** 349,357 ****
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist,
  					 &name, &bases, &dict))
! 		return -1;
! 	if (!PyTuple_Check(bases) || !PyDict_Check(dict)) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"usage: type(name, bases, dict) ");
! 		return -1;
  	}
  
--- 388,410 ----
  	if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist,
  					 &name, &bases, &dict))
! 		return NULL;
! 	if (PyTuple_Check(bases)) {
! 		int i, n;
! 		n = PyTuple_GET_SIZE(bases);
! 		for (i = 0; i < n; i++) {
! 			PyObject *base_i = PyTuple_GET_ITEM(bases, i);
! 			PyTypeObject *type_i = base_i->ob_type;
! 			if (issubtype(metatype, type_i))
! 				continue;
! 			if (issubtype(type_i, metatype)) {
! 				metatype = type_i;
! 				continue;
! 			}
! 			PyErr_SetString(PyExc_TypeError,
! 					"metaclass conflict among bases");
! 			return NULL;
! 		}
! 		if (metatype->tp_new != type_new)
! 			return metatype->tp_new(metatype, args, kwds);
  	}
  
***************
*** 361,365 ****
  		bases = Py_BuildValue("(O)", &PyBaseObject_Type);
  		if (bases == NULL)
! 			return -1;
  		nbases = 1;
  	}
--- 414,418 ----
  		bases = Py_BuildValue("(O)", &PyBaseObject_Type);
  		if (bases == NULL)
! 			return NULL;
  		nbases = 1;
  	}
***************
*** 370,387 ****
  	base = best_base(bases);
  	if (base == NULL)
! 		return -1;
! 	if (base->tp_init == NULL && base != &PyBaseObject_Type) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"base type must have a constructor slot");
! 		return -1;
  	}
  
- 	/* Set tp_base and tp_bases */
- 	type->tp_bases = bases;
- 	Py_INCREF(base);
- 	type->tp_base = base;
- 
  	/* Check for a __slots__ sequence variable in dict, and count it */
- 	/* XXX This should move to type_alloc() */
  	slots = PyDict_GetItemString(dict, "__slots__");
  	nslots = 0;
--- 423,435 ----
  	base = best_base(bases);
  	if (base == NULL)
! 		return NULL;
! 	if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
! 		PyErr_Format(PyExc_TypeError,
! 			     "type '%.100s' is not an acceptable base type",
! 			     base->tp_name);
! 		return NULL;
  	}
  
  	/* Check for a __slots__ sequence variable in dict, and count it */
  	slots = PyDict_GetItemString(dict, "__slots__");
  	nslots = 0;
***************
*** 393,397 ****
  			slots = PySequence_Tuple(slots);
  		if (slots == NULL)
! 			return -1;
  		nslots = PyTuple_GET_SIZE(slots);
  		for (i = 0; i < nslots; i++) {
--- 441,445 ----
  			slots = PySequence_Tuple(slots);
  		if (slots == NULL)
! 			return NULL;
  		nslots = PyTuple_GET_SIZE(slots);
  		for (i = 0; i < nslots; i++) {
***************
*** 400,404 ****
  				"__slots__ must be a sequence of strings");
  				Py_DECREF(slots);
! 				return -1;
  			}
  		}
--- 448,452 ----
  				"__slots__ must be a sequence of strings");
  				Py_DECREF(slots);
! 				return NULL;
  			}
  		}
***************
*** 409,427 ****
  		nslots = 1;
  
! 	/* Check allocation size and initialize the type object */
! 	allocsize = sizeof(etype) + nslots*sizeof(struct memberlist);
! 	if (type->ob_type->tp_basicsize < allocsize) {
! 		PyErr_Format(
! 			PyExc_SystemError,
! 			"insufficient allocated memory for subtype: "
! 			"allocated %d, needed %d",
! 			type->ob_type->tp_basicsize,
! 			allocsize);
! 		return -1;
! 	}
  	et = (etype *)type;
  	Py_INCREF(name);
  	et->name = name;
  	et->slots = slots;
  	type->tp_as_number = &et->as_number;
  	type->tp_as_sequence = &et->as_sequence;
--- 457,474 ----
  		nslots = 1;
  
! 	/* Allocate the type object */
! 	type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);
! 	if (type == NULL)
! 		return NULL;
! 
! 	/* Keep name and slots alive in the extended type object */
  	et = (etype *)type;
  	Py_INCREF(name);
  	et->name = name;
  	et->slots = slots;
+ 
+ 	/* Initialize essential fields */
+ 	type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE |
+ 		Py_TPFLAGS_BASETYPE;
  	type->tp_as_number = &et->as_number;
  	type->tp_as_sequence = &et->as_sequence;
***************
*** 430,437 ****
  	type->tp_name = PyString_AS_STRING(name);
  
  	/* Initialize tp_introduced from passed-in dict */
  	type->tp_introduced = dict = PyDict_Copy(dict);
  	if (dict == NULL)
! 		return -1;
  
  	/* Add descriptors for custom slots from __slots__, or for __dict__ */
--- 477,489 ----
  	type->tp_name = PyString_AS_STRING(name);
  
+ 	/* Set tp_base and tp_bases */
+ 	type->tp_bases = bases;
+ 	Py_INCREF(base);
+ 	type->tp_base = base;
+ 
  	/* Initialize tp_introduced from passed-in dict */
  	type->tp_introduced = dict = PyDict_Copy(dict);
  	if (dict == NULL)
! 		return NULL;
  
  	/* Add descriptors for custom slots from __slots__, or for __dict__ */
***************
*** 467,584 ****
  			type->tp_setattro = PyObject_GenericSetAttr;
  	}
- 	if (base->tp_dealloc == NULL)
- 		type->tp_dealloc = object_dealloc;
- 	else
- 		type->tp_dealloc = subtype_dealloc;
  	if (base->tp_new == NULL)
  		type->tp_new = PyType_GenericNew;
  	if (base->tp_alloc == NULL)
  		type->tp_alloc = PyType_GenericAlloc;
- 	if (base->tp_init == NULL)
- 		type->tp_init = object_init;
  
  	/* Initialize the rest */
  	if (PyType_InitDict(type) < 0)
! 		return -1;
  
  	/* Override slots that deserve it */
  	override_slots(type, type->tp_dict);
- 	return 0;
- }
- 
- static int
- extra_ivars(PyTypeObject *type, PyTypeObject *base)
- {
- 	int t_size = type->tp_basicsize;
- 	int b_size = base->tp_basicsize;
- 
- 	assert((type->tp_flags & Py_TPFLAGS_GC) >=
- 	       (base->tp_flags & Py_TPFLAGS_GC)); /* base has GC, type not! */
- 	if (type->tp_flags & Py_TPFLAGS_GC)
- 		t_size -= PyGC_HEAD_SIZE;
- 	if (base->tp_flags & Py_TPFLAGS_GC)
- 		b_size -= PyGC_HEAD_SIZE;
- 	assert(t_size >= b_size); /* type smaller than base! */
- 	if (type->tp_itemsize || base->tp_itemsize) {
- 		/* If itemsize is involved, stricter rules */
- 		return t_size != b_size ||
- 			type->tp_itemsize != base->tp_itemsize;
- 	}
- 	if (t_size == b_size)
- 		return 0;
- 	if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 &&
- 	    type->tp_dictoffset == b_size &&
- 	    t_size == b_size + sizeof(PyObject *))
- 		return 0; /* "Forgive" adding a __dict__ only */
- 	return 1;
- }
- 
- static PyTypeObject *
- solid_base(PyTypeObject *type)
- {
- 	PyTypeObject *base;
- 
- 	if (type->tp_base)
- 		base = solid_base(type->tp_base);
- 	else
- 		base = &PyBaseObject_Type;
- 	if (extra_ivars(type, base))
- 		return type;
- 	else
- 		return base;
- }
- 
- static PyObject *
- type_alloc(PyTypeObject *metatype, int nitems)
- {
- 	PyTypeObject *type;
- 
- 	type = (PyTypeObject *)PyType_GenericAlloc(metatype, nitems);
- 	if (type != NULL)
- 		type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
  	return (PyObject *)type;
  }
  
  static PyObject *
- type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
- {
- 	PyObject *name, *bases, *dict;
- 	static char *kwlist[] = {"name", "bases", "dict", 0};
- 
- 	if (PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
- 	    (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) {
- 		/* type(x) -> x.__class__ */
- 		PyObject *x = PyTuple_GET_ITEM(args, 0);
- 		Py_INCREF(x->ob_type);
- 		return (PyObject *) x->ob_type;
- 	}
- 
- 	/* Check arguments (again?!?! yes, alas -- we need the bases!) */
- 	if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO:type", kwlist,
- 					 &name, &bases, &dict))
- 		return NULL;
- 	if (PyTuple_Check(bases)) {
- 		int i, n;
- 		n = PyTuple_GET_SIZE(bases);
- 		for (i = 0; i < n; i++) {
- 			PyObject *base_i = PyTuple_GET_ITEM(bases, i);
- 			PyTypeObject *type_i = base_i->ob_type;
- 			if (issubtype(metatype, type_i))
- 				continue;
- 			if (issubtype(type_i, metatype)) {
- 				metatype = type_i;
- 				continue;
- 			}
- 			PyErr_SetString(PyExc_TypeError,
- 					"metaclass conflict among bases");
- 			return NULL;
- 		}
- 		if (metatype->tp_new != type_new)
- 			return metatype->tp_new(metatype, args, kwds);
- 	}
- 	return PyType_GenericNew(metatype, args, kwds);
- }
- 
- static PyObject *
  type_getattro(PyTypeObject *type, PyObject *name)
  {
--- 519,537 ----
  			type->tp_setattro = PyObject_GenericSetAttr;
  	}
  	if (base->tp_new == NULL)
  		type->tp_new = PyType_GenericNew;
  	if (base->tp_alloc == NULL)
  		type->tp_alloc = PyType_GenericAlloc;
  
  	/* Initialize the rest */
  	if (PyType_InitDict(type) < 0)
! 		return NULL;
  
  	/* Override slots that deserve it */
  	override_slots(type, type->tp_dict);
  	return (PyObject *)type;
  }
  
  static PyObject *
  type_getattro(PyTypeObject *type, PyObject *name)
  {
***************
*** 614,619 ****
  	0,					/* ob_size */
  	"type",					/* tp_name */
! 	sizeof(etype) + sizeof(struct memberlist), /* tp_basicsize */
! 	0,					/* tp_itemsize */
  	(destructor)type_dealloc,		/* tp_dealloc */
  	0,					/* tp_print */
--- 567,572 ----
  	0,					/* ob_size */
  	"type",					/* tp_name */
! 	sizeof(etype),				/* tp_basicsize */
! 	sizeof(struct memberlist),		/* tp_itemsize */
  	(destructor)type_dealloc,		/* tp_dealloc */
  	0,					/* tp_print */
***************
*** 631,635 ****
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT,			/* tp_flags */
  	type_doc,				/* tp_doc */
  	0,					/* tp_traverse */
--- 584,588 ----
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  	type_doc,				/* tp_doc */
  	0,					/* tp_traverse */
***************
*** 647,652 ****
  	0,					/* tp_descr_set */
  	offsetof(PyTypeObject, tp_dict),	/* tp_dictoffset */
! 	type_init,				/* tp_init */
! 	type_alloc,				/* tp_alloc */
  	type_new,				/* tp_new */
  };
--- 600,605 ----
  	0,					/* tp_descr_set */
  	offsetof(PyTypeObject, tp_dict),	/* tp_dictoffset */
! 	0,					/* tp_init */
! 	PyType_GenericAlloc,			/* tp_alloc */
  	type_new,				/* tp_new */
  };
***************
*** 678,682 ****
  	sizeof(PyObject),			/* tp_basicsize */
  	0,					/* tp_itemsize */
! 	0/*(destructor)object_dealloc*/,	/* tp_dealloc */
  	0,					/* tp_print */
  	0,			 		/* tp_getattr */
--- 631,635 ----
  	sizeof(PyObject),			/* tp_basicsize */
  	0,					/* tp_itemsize */
! 	(destructor)object_dealloc,		/* tp_dealloc */
  	0,					/* tp_print */
  	0,			 		/* tp_getattr */
***************
*** 693,697 ****
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT,			/* tp_flags */
  	"The most base type",			/* tp_doc */
  	0,					/* tp_traverse */
--- 646,650 ----
  	0,					/* tp_setattro */
  	0,					/* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  	"The most base type",			/* tp_doc */
  	0,					/* tp_traverse */
***************
*** 709,715 ****
  	0,					/* tp_descr_set */
  	0,					/* tp_dictoffset */
! 	0,					/* tp_init */
! 	0,					/* tp_alloc */
! 	0,					/* tp_new */
  };
  
--- 662,668 ----
  	0,					/* tp_descr_set */
  	0,					/* tp_dictoffset */
! 	object_init,				/* tp_init */
! 	PyType_GenericAlloc,			/* tp_alloc */
! 	PyType_GenericNew,			/* tp_new */
  };