diff options
author | Guido van Rossum <guido@python.org> | 2001-08-16 09:18:56 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-08-16 09:18:56 (GMT) |
commit | c35422109b36d20f409a3a72f60c0c7e2e0bc824 (patch) | |
tree | 361f6efa619212bddc3789f37ddde4ba6142be55 | |
parent | 83f56cb2dbb0e5df04ae2a6d2847991449cfde6b (diff) | |
download | cpython-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.c | 76 |
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); } |