Fix SF bug #442501: calculate __module__ properly.
authorGuido van Rossum <guido@python.org>
Thu, 16 Aug 2001 09:18:56 +0000 (09:18 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 16 Aug 2001 09:18:56 +0000 (09:18 +0000)
- type_module(), type_name(): if tp_name contains one or more period,
  the part before the last period is __module__, the part after that
  is __name__.  Otherwise, for non-heap types, __module__ is
  "__builtin__".  For heap types, __module__ is looked up in
  tp_defined.

- type_new(): heap types have their __module__ set from
  globals().__name__; a pre-existing __module__ in their dict is not
  overridden.  This is not inherited.

- type_repr(): if __module__ exists and is not "__builtin__", it is
  included in the string representation (just as it already is for
  classes).  For example <type '__main__.C'>.

Objects/typeobject.c

index 30e693ab91a50c4f11f2773d1969ab2f0f368e49..c4dc3640e768054c2f3cd67490e508af403675b0 100644 (file)
@@ -5,7 +5,6 @@
 #include "structmember.h"
 
 static struct memberlist type_members[] = {
-       {"__name__", T_STRING, offsetof(PyTypeObject, tp_name), READONLY},
        {"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
        {"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY},
        {"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
@@ -20,10 +19,38 @@ static struct memberlist type_members[] = {
        {0}
 };
 
+static PyObject *
+type_name(PyTypeObject *type, void *context)
+{
+       char *s;
+
+       s = strrchr(type->tp_name, '.');
+       if (s == NULL)
+               s = type->tp_name;
+       else
+               s++;
+       return PyString_FromString(s);
+}
+
 static PyObject *
 type_module(PyTypeObject *type, void *context)
 {
-       return PyString_FromString("__builtin__");
+       PyObject *mod;
+       char *s;
+
+       s = strrchr(type->tp_name, '.');
+       if (s != NULL)
+               return PyString_FromStringAndSize(type->tp_name,
+                                                 (int)(s - type->tp_name));
+       if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
+               return PyString_FromString("__builtin__");
+       mod = PyDict_GetItemString(type->tp_defined, "__module__");
+       if (mod != NULL && PyString_Check(mod)) {
+               Py_INCREF(mod);
+               return mod;
+       }
+       PyErr_SetString(PyExc_AttributeError, "__module__");
+       return NULL;
 }
 
 static PyObject *
@@ -65,6 +92,7 @@ type_dynamic(PyTypeObject *type, void *context)
 }
 
 struct getsetlist type_getsets[] = {
+       {"__name__", (getter)type_name, NULL, NULL},
        {"__module__", (getter)type_module, NULL, NULL},
        {"__dict__",  (getter)type_dict,  NULL, NULL},
        {"__defined__",  (getter)type_defined,  NULL, NULL},
@@ -85,8 +113,27 @@ type_compare(PyObject *v, PyObject *w)
 static PyObject *
 type_repr(PyTypeObject *type)
 {
-       char buf[100];
-       sprintf(buf, "<type '%.80s'>", type->tp_name);
+       PyObject *mod, *name;
+       char buf[200];
+
+       mod = type_module(type, NULL);
+       if (mod == NULL)
+               PyErr_Clear();
+       else if (!PyString_Check(mod)) {
+               Py_DECREF(mod);
+               mod = NULL;
+       }
+       name = type_name(type, NULL);
+       if (name == NULL)
+               return NULL;
+       if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__"))
+               sprintf(buf, "<type '%.80s.%.80s'>",
+                       PyString_AS_STRING(mod),
+                       PyString_AS_STRING(name));
+       else
+               sprintf(buf, "<type '%.80s'>", type->tp_name);
+       Py_XDECREF(mod);
+       Py_DECREF(name);
        return PyString_FromString(buf);
 }
 
@@ -611,6 +658,19 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
                return NULL;
        }
 
+       /* Set __module__ in the dict */
+       if (PyDict_GetItemString(dict, "__module__") == NULL) {
+               tmp = PyEval_GetGlobals();
+               if (tmp != NULL) {
+                       tmp = PyDict_GetItemString(tmp, "__name__");
+                       if (tmp != NULL) {
+                               if (PyDict_SetItemString(dict, "__module__",
+                                                        tmp) < 0)
+                                       return NULL;
+                       }
+               }
+       }
+
        /* Special-case __new__: if it's a plain function,
           make it a static function */
        tmp = PyDict_GetItemString(dict, "__new__");
@@ -2478,8 +2538,14 @@ slot_tp_getattro(PyObject *self, PyObject *name)
                        return NULL;
        }
        getattr = _PyType_Lookup(tp, getattr_str);
-       if (getattr == NULL)
+       if (getattr == NULL) {
+               /* 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);
 }