summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-08-16 09:18:56 (GMT)
committerGuido van Rossum <guido@python.org>2001-08-16 09:18:56 (GMT)
commitc35422109b36d20f409a3a72f60c0c7e2e0bc824 (patch)
tree361f6efa619212bddc3789f37ddde4ba6142be55
parent83f56cb2dbb0e5df04ae2a6d2847991449cfde6b (diff)
downloadcpython-c35422109b36d20f409a3a72f60c0c7e2e0bc824.zip
cpython-c35422109b36d20f409a3a72f60c0c7e2e0bc824.tar.gz
cpython-c35422109b36d20f409a3a72f60c0c7e2e0bc824.tar.bz2
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'>.
-rw-r--r--Objects/typeobject.c76
1 files changed, 71 insertions, 5 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 30e693a..c4dc364 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -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},
@@ -21,9 +20,37 @@ static struct memberlist type_members[] = {
};
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);
}