Fix SF bug #442501: calculate __module__ properly.

- 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'>.
This commit is contained in:
Guido van Rossum 2001-08-16 09:18:56 +00:00
parent 83f56cb2db
commit c35422109b
1 changed files with 71 additions and 5 deletions

View 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);
}