Mailing List Archive

CVS: python/dist/src/Objects typeobject.c,2.16.8.18,2.16.8.19
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv22095

Modified Files:
Tag: descr-branch
typeobject.c
Log Message:
Another cool feature: if a subtype of a built-in type defines a class
variable __slots__ (which must be a sequence of strings), it doesn't
have a __dict__, but instead it has named slots whose names are given
by the strings in the sequence. Setting __slots__ = [] implies the
subtype has no slots beyond those in the base class.

(I think subtypes of such subtypes must specifiy __slots__ = [] to
prevent adding a __dict__.)


Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.18
retrieving revision 2.16.8.19
diff -C2 -r2.16.8.18 -r2.16.8.19
*** typeobject.c 2001/05/11 20:12:27 2.16.8.18
--- typeobject.c 2001/05/11 21:51:35 2.16.8.19
***************
*** 126,131 ****
staticforward void override_slots(PyTypeObject *type, PyObject *dict);

- #define NMEMBERS 1
-
typedef struct {
PyTypeObject type;
--- 126,129 ----
***************
*** 134,139 ****
PyMappingMethods as_mapping;
PyBufferProcs as_buffer;
! struct memberlist members[NMEMBERS+1];
! char name[1];
} etype;

--- 132,137 ----
PyMappingMethods as_mapping;
PyBufferProcs as_buffer;
! PyObject *name, *slots;
! struct memberlist members[1];
} etype;

***************
*** 142,151 ****
type_construct(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! char *name;
! PyObject *bases, *dict, *x;
PyTypeObject *base;
char *dummy = NULL;
etype *et;
struct memberlist *mp;

/* Check arguments */
--- 140,149 ----
type_construct(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! PyObject *name, *bases, *dict, *x, *slots;
PyTypeObject *base;
char *dummy = NULL;
etype *et;
struct memberlist *mp;
+ int i, nslots, slotoffset, allocsize;

/* Check arguments */
***************
*** 155,159 ****
return NULL;
}
! if (!PyArg_ParseTupleAndKeywords(args, kwds, "sOO", &dummy,
&name, &bases, &dict))
return NULL;
--- 153,157 ----
return NULL;
}
! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", &dummy,
&name, &bases, &dict))
return NULL;
***************
*** 180,195 ****
}

/* Allocate memory and construct a type object in it */
! et = PyObject_MALLOC(sizeof(etype) + strlen(name));
if (et == NULL)
return NULL;
! memset(et, '\0', sizeof(etype));
type = &et->type;
PyObject_INIT(type, &PyDynamicType_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;

--- 178,223 ----
}

+ /* Check for a __slots__ sequence variable in dict, and count it */
+ slots = PyDict_GetItemString(dict, "__slots__");
+ nslots = 0;
+ if (slots != NULL) {
+ /* Make it into a tuple */
+ if (PyString_Check(slots))
+ slots = Py_BuildValue("(O)", slots);
+ else
+ slots = PySequence_Tuple(slots);
+ if (slots == NULL)
+ return NULL;
+ nslots = PyTuple_GET_SIZE(slots);
+ for (i = 0; i < nslots; i++) {
+ if (!PyString_Check(PyTuple_GET_ITEM(slots, i))) {
+ PyErr_SetString(PyExc_TypeError,
+ "__slots__ must be a sequence of strings");
+ Py_DECREF(slots);
+ return NULL;
+ }
+ }
+ }
+ if (slots == NULL && base->tp_dictoffset == 0 &&
+ (base->tp_setattro == PyGeneric_SetAttr ||
+ base->tp_setattro == NULL))
+ nslots = 1;
+
/* Allocate memory and construct a type object in it */
! allocsize = sizeof(etype) + nslots*sizeof(struct memberlist);
! et = PyObject_MALLOC(allocsize);
if (et == NULL)
return NULL;
! memset(et, '\0', allocsize);
type = &et->type;
PyObject_INIT(type, &PyDynamicType_Type);
+ Py_INCREF(name);
+ et->name = name;
+ et->slots = slots;
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 = PyString_AS_STRING(name);
type->tp_flags = Py_TPFLAGS_DEFAULT;

***************
*** 216,235 ****
}

! /* Add a __dict__ slot if we don't already have one,
! but only if the getattro is generic */
! if (type->tp_dictoffset == 0 &&
! type->tp_setattro == PyGeneric_SetAttr) {
! int dictoffset = type->tp_basicsize;
! if (type->tp_flags & Py_TPFLAGS_GC)
! dictoffset -= PyGC_HEAD_SIZE;
! type->tp_dictoffset = dictoffset;
type->tp_basicsize += sizeof(PyObject *);
- mp = et->members;
mp->name = "__dict__";
mp->type = T_OBJECT;
! mp->offset = dictoffset;
mp->readonly = 1;
- add_members(type, mp);
}

x = PyObject_CallMethod(type->tp_dict, "update", "O", dict);
--- 244,270 ----
}

! /* Add custom slots */
! mp = et->members;
! slotoffset = type->tp_basicsize;
! if (type->tp_flags & Py_TPFLAGS_GC)
! slotoffset -= PyGC_HEAD_SIZE;
! if (slots != NULL) {
! for (i = 0; i < nslots; i++, mp++) {
! mp->name = PyString_AS_STRING(
! PyTuple_GET_ITEM(slots, i));
! mp->type = T_OBJECT;
! mp->offset = slotoffset + i*sizeof(PyObject *);
! }
! type->tp_basicsize += nslots*sizeof(PyObject *);
! }
! else if (nslots) {
! type->tp_dictoffset = slotoffset;
type->tp_basicsize += sizeof(PyObject *);
mp->name = "__dict__";
mp->type = T_OBJECT;
! mp->offset = slotoffset;
mp->readonly = 1;
}
+ add_members(type, et->members);

x = PyObject_CallMethod(type->tp_dict, "update", "O", dict);
***************
*** 311,316 ****
--- 346,355 ----
dtype_dealloc(PyTypeObject *type)
{
+ etype *et = (etype *)type;
+
Py_XDECREF(type->tp_base);
Py_XDECREF(type->tp_dict);
+ Py_XDECREF(et->name);
+ Py_XDECREF(et->slots);
PyObject_DEL(type);
}
***************
*** 348,352 ****
type_members, /* tp_members */
type_getsets, /* tp_getset */
! 0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
--- 387,391 ----
type_members, /* tp_members */
type_getsets, /* tp_getset */
! &PyType_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */