mirror of https://github.com/python/cpython
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:
parent
83f56cb2db
commit
c35422109b
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue