type_new(): look for __dynamic__ at the module level (after looking in
authorGuido van Rossum <guido@python.org>
Fri, 17 Aug 2001 16:47:50 +0000 (16:47 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 17 Aug 2001 16:47:50 +0000 (16:47 +0000)
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.

Objects/typeobject.c

index 474ff3ee2b30fd5738243e7e85f7ba31d0708658..29cb2031c0fefc9e94d08c7c9eb392d9bb4d542b 100644 (file)
@@ -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)