[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.13,2.16.8.14
Guido van Rossum
gvanrossum@users.sourceforge.net
Thu, 10 May 2001 08:33:13 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv20151
Modified Files:
Tag: descr-branch
typeobject.c
Log Message:
Add a __dict__ to instances of Python classes that inherit from
built-in types.
Still to do (at least):
- class variables should serve as defaults for instance variables
- call __init__() if defined
- don't add a __dict__ if the base type has non-generic getattro or
setattro
- support fixed slots instead of a __dict__, as an option?
- multiple inheritance (limited to only one base class with C slots)
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.13
retrieving revision 2.16.8.14
diff -C2 -r2.16.8.13 -r2.16.8.14
*** typeobject.c 2001/05/07 23:19:24 2.16.8.13
--- typeobject.c 2001/05/10 15:33:11 2.16.8.14
***************
*** 54,57 ****
--- 54,59 ----
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
+ int size;
+ void *mem;
PyObject *obj, *res;
***************
*** 62,68 ****
return NULL;
}
! obj = PyObject_New(PyObject, type);
! if (obj == NULL)
! return NULL;
res = (type->tp_construct)(obj, args, kwds);
if (res != obj) {
--- 64,80 ----
return NULL;
}
!
! /* Inline PyObject_New() so we can zero the memory */
! size = _PyObject_SIZE(type);
! mem = PyObject_MALLOC(size);
! if (mem == NULL)
! return PyErr_NoMemory();
! memset(mem, '\0', size);
! if (PyType_IS_GC(type))
! obj = PyObject_FROM_GC(mem);
! else
! obj = (PyObject *)mem;
! PyObject_INIT(obj, type);
!
res = (type->tp_construct)(obj, args, kwds);
if (res != obj) {
***************
*** 149,154 ****
--- 161,217 ----
}
+ static PyObject *
+ subtype_getattro(PyObject *self, PyObject *name)
+ {
+ int dictoffset = self->ob_type->tp_members[0].offset;
+ PyObject *dict = * (PyObject **) ((char *)self + dictoffset);
+
+ if (dict != NULL) {
+ PyObject *res = PyObject_GetItem(dict, name);
+ if (res != NULL)
+ return res;
+ PyErr_Clear();
+ }
+ return PyGeneric_GetAttr(self, name);
+ }
+
+ static int
+ subtype_setattro(PyObject *self, PyObject *name, PyObject *value)
+ {
+ PyTypeObject *tp = self->ob_type;
+ PyObject *descr;
+
+ assert(tp->tp_dict != NULL && PyDict_Check(tp->tp_dict));
+ descr = PyDict_GetItem(tp->tp_dict, name);
+ if (descr == NULL) {
+ int dictoffset = self->ob_type->tp_members[0].offset;
+ PyObject **dictptr = (PyObject **) ((char *)self + dictoffset);
+ PyObject *dict = *dictptr;
+
+ if (dict == NULL) {
+ dict = PyDict_New();
+ if (dict == NULL)
+ return -1;
+ *dictptr = dict;
+ }
+ if (value == NULL) {
+ int res = PyObject_DelItem(dict, name);
+ if (res < 0 &&
+ PyErr_ExceptionMatches(PyExc_KeyError))
+ {
+ PyErr_SetObject(PyExc_AttributeError, name);
+ return -1;
+ }
+ }
+ else
+ return PyObject_SetItem(dict, name, value);
+ }
+ return PyGeneric_SetAttr(self, name, value);
+ }
+
staticforward void override_slots(PyTypeObject *type, PyObject *dict);
+ #define NMEMBERS 1
+
typedef struct {
PyTypeObject type;
***************
*** 157,160 ****
--- 220,224 ----
PyMappingMethods as_mapping;
PyBufferProcs as_buffer;
+ struct memberlist members[NMEMBERS+1];
char name[1];
} etype;
***************
*** 168,171 ****
--- 232,237 ----
PyTypeObject *base;
char *dummy = NULL;
+ etype *et;
+ struct memberlist *mp;
if (type != NULL) {
***************
*** 198,211 ****
return NULL;
}
! type = PyObject_MALLOC(sizeof(etype) + strlen(name));
! if (type == NULL)
return NULL;
! memset(type, '\0', sizeof(etype));
PyObject_INIT(type, &PyType_Type);
! type->tp_as_number = & (((etype *)type)->as_number);
! type->tp_as_sequence = & (((etype *)type)->as_sequence);
! type->tp_as_mapping = & (((etype *)type)->as_mapping);
! type->tp_as_buffer = & (((etype *)type)->as_buffer);
! type->tp_name = strcpy(((etype *)type)->name, name);
type->tp_flags = Py_TPFLAGS_DEFAULT;
Py_INCREF(base);
--- 264,278 ----
return NULL;
}
! et = PyObject_MALLOC(sizeof(etype) + strlen(name));
! if (et == NULL)
return NULL;
! memset(et, '\0', sizeof(etype));
! type = &et->type;
PyObject_INIT(type, &PyType_Type);
! type->tp_as_number = &et->as_number;
! type->tp_as_sequence = &et->as_sequence;
! type->tp_as_mapping = &et->as_mapping;
! type->tp_as_buffer = &et->as_buffer;
! type->tp_name = strcpy(et->name, name);
type->tp_flags = Py_TPFLAGS_DEFAULT;
Py_INCREF(base);
***************
*** 215,222 ****
--- 282,309 ----
if (base->tp_dealloc)
type->tp_dealloc = subtype_dealloc;
+ if (base->tp_getattro == NULL ||
+ base->tp_getattro == PyGeneric_GetAttr) {
+ type->tp_getattro = subtype_getattro;
+ type->tp_getattr = NULL;
+ }
+ if (base->tp_setattro == NULL ||
+ base->tp_setattro == PyGeneric_SetAttr) {
+ type->tp_setattro = subtype_setattro;
+ type->tp_setattr = NULL;
+ }
+
+ type->tp_members = mp = et->members;
+ mp->name = "__dict__";
+ mp->type = T_OBJECT;
+ mp->offset = base->tp_basicsize - ((base->tp_flags & Py_TPFLAGS_GC)
+ ? PyGC_HEAD_SIZE : 0);
+ mp->readonly = 1;
+ assert(mp+1 <= &et->members[NMEMBERS]);
+
if (PyType_InitDict(type) < 0) {
Py_DECREF(type);
return NULL;
}
+ type->tp_basicsize += sizeof(PyObject *); /* for __dict__ */
x = PyObject_CallMethod(type->tp_dict, "update", "O", dict);
if (x == NULL) {
***************
*** 429,432 ****
--- 516,521 ----
inherit_slots(PyTypeObject *type, PyTypeObject *base)
{
+ int oldsize, newsize;
+
#undef COPYSLOT
#undef COPYNUM
***************
*** 530,534 ****
COPYSLOT(tp_name);
! COPYSLOT(tp_basicsize);
if (!(type->tp_flags & Py_TPFLAGS_GC) &&
(base->tp_flags & Py_TPFLAGS_GC) &&
--- 619,632 ----
COPYSLOT(tp_name);
!
! /* Copying basicsize is connected to the GC flags */
! oldsize = base->tp_basicsize;
! if (base->tp_flags & Py_TPFLAGS_GC)
! oldsize -= PyGC_HEAD_SIZE;
! newsize = type->tp_basicsize;
! if (newsize && (type->tp_flags & Py_TPFLAGS_GC))
! newsize -= PyGC_HEAD_SIZE;
! if (!newsize)
! newsize = oldsize;
if (!(type->tp_flags & Py_TPFLAGS_GC) &&
(base->tp_flags & Py_TPFLAGS_GC) &&
***************
*** 536,543 ****
(!type->tp_traverse && !type->tp_clear)) {
type->tp_flags |= Py_TPFLAGS_GC;
- type->tp_basicsize += PyGC_HEAD_SIZE;
COPYSLOT(tp_traverse);
COPYSLOT(tp_clear);
}
COPYSLOT(tp_itemsize);
COPYSLOT(tp_dealloc);
--- 634,644 ----
(!type->tp_traverse && !type->tp_clear)) {
type->tp_flags |= Py_TPFLAGS_GC;
COPYSLOT(tp_traverse);
COPYSLOT(tp_clear);
}
+ if (type->tp_flags & Py_TPFLAGS_GC)
+ newsize += PyGC_HEAD_SIZE;
+ type->tp_basicsize = newsize;
+
COPYSLOT(tp_itemsize);
COPYSLOT(tp_dealloc);
***************
*** 1227,1230 ****
--- 1328,1333 ----
}
+ /* XXX the numerical slots should call the reverse operators too;
+ but how do they know their type? */
SLOT1(nb_add, add, PyObject *, O);
SLOT1(nb_subtract, sub, PyObject *, O);