summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-08-17 16:47:50 (GMT)
committerGuido van Rossum <guido@python.org>2001-08-17 16:47:50 (GMT)
commit1a49350e8d7fdf7c847cc41bc1d3511dd203320d (patch)
tree20b5eb20413550d1f150fadbe7526568a0b8529c
parent7cb32ae7bf1a9c3b9ce1ee0d93894a7a528a2a6f (diff)
downloadcpython-1a49350e8d7fdf7c847cc41bc1d3511dd203320d.zip
cpython-1a49350e8d7fdf7c847cc41bc1d3511dd203320d.tar.gz
cpython-1a49350e8d7fdf7c847cc41bc1d3511dd203320d.tar.bz2
type_new(): look for __dynamic__ at the module level (after looking in
the class dict). Anything but a nonnegative int in either place is *ignored* (before, a non-Boolean was an error). The default is still static -- in a comparative test, Jeremy's Tools/compiler package ran twice as slow (compiling itself) using dynamic as the default. (The static version, which requires a few tweaks to avoid modifying class variables, runs at about the same speed as the classic version.) slot_tp_descr_get(): this also needed fallback behavior. slot_tp_getattro(): remove a debug fprintf() call.
-rw-r--r--Objects/typeobject.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 474ff3e..29cb203 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -566,23 +566,44 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
return NULL;
}
- /* Should this be a dynamic class (i.e. modifiable __dict__)? */
+ /* Should this be a dynamic class (i.e. modifiable __dict__)?
+ Look in two places for a variable named __dynamic__:
+ 1) in the class dict
+ 2) in the module dict (globals)
+ The first variable that is an int >= 0 is used.
+ Otherwise, a default is calculated from the base classes:
+ if any base class is dynamic, this class is dynamic; otherwise
+ it is static. */
+ dynamic = -1; /* Not yet determined */
+ /* Look in the class */
tmp = PyDict_GetItemString(dict, "__dynamic__");
if (tmp != NULL) {
- /* The class author has a preference */
- dynamic = PyObject_IsTrue(tmp);
- Py_DECREF(tmp);
+ dynamic = PyInt_AsLong(tmp);
if (dynamic < 0)
- return NULL;
+ PyErr_Clear();
}
- else {
- /* Make a new class dynamic if any of its bases is dynamic.
- This is not always the same as inheriting the __dynamic__
- class attribute! */
+ if (dynamic < 0) {
+ /* Look in the module globals */
+ tmp = PyEval_GetGlobals();
+ if (tmp != NULL) {
+ tmp = PyDict_GetItemString(tmp, "__dynamic__");
+ if (tmp != NULL) {
+ dynamic = PyInt_AsLong(tmp);
+ if (dynamic < 0)
+ PyErr_Clear();
+ }
+ }
+ }
+ if (dynamic < 0) {
+ /* Make a new class dynamic if any of its bases is
+ dynamic. This is not always the same as inheriting
+ the __dynamic__ class attribute! */
dynamic = 0;
for (i = 0; i < nbases; i++) {
- tmptype = (PyTypeObject *)PyTuple_GET_ITEM(bases, i);
- if (tmptype->tp_flags & Py_TPFLAGS_DYNAMICTYPE) {
+ tmptype = (PyTypeObject *)
+ PyTuple_GET_ITEM(bases, i);
+ if (tmptype->tp_flags &
+ Py_TPFLAGS_DYNAMICTYPE) {
dynamic = 1;
break;
}
@@ -2565,8 +2586,6 @@ slot_tp_getattro(PyObject *self, PyObject *name)
/* Avoid further slowdowns */
if (tp->tp_getattro == slot_tp_getattro)
tp->tp_getattro = PyObject_GenericGetAttr;
- else
- fprintf(stderr, "huh?\n");
return PyObject_GenericGetAttr(self, name);
}
return PyObject_CallFunction(getattr, "OO", self, name);
@@ -2672,7 +2691,28 @@ slot_tp_iternext(PyObject *self)
return PyObject_CallMethod(self, "next", "");
}
-SLOT2(slot_tp_descr_get, "__get__", PyObject *, PyObject *, "OO")
+static PyObject *
+slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type)
+{
+ PyTypeObject *tp = self->ob_type;
+ PyObject *get;
+ static PyObject *get_str = NULL;
+
+ if (get_str == NULL) {
+ get_str = PyString_InternFromString("__get__");
+ if (get_str == NULL)
+ return NULL;
+ }
+ get = _PyType_Lookup(tp, get_str);
+ if (get == NULL) {
+ /* Avoid further slowdowns */
+ if (tp->tp_descr_get == slot_tp_descr_get)
+ tp->tp_descr_get = NULL;
+ Py_INCREF(self);
+ return self;
+ }
+ return PyObject_CallFunction(get, "OOO", self, obj, type);
+}
static int
slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value)