diff options
Diffstat (limited to 'Objects/moduleobject.c')
-rw-r--r-- | Objects/moduleobject.c | 135 |
1 files changed, 108 insertions, 27 deletions
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 533db46..2f2bd36 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -27,36 +27,45 @@ static PyTypeObject moduledef_type = { PyObject * -PyModule_New(const char *name) +PyModule_NewObject(PyObject *name) { PyModuleObject *m; - PyObject *nameobj; m = PyObject_GC_New(PyModuleObject, &PyModule_Type); if (m == NULL) return NULL; m->md_def = NULL; m->md_state = NULL; - nameobj = PyUnicode_FromString(name); m->md_dict = PyDict_New(); - if (m->md_dict == NULL || nameobj == NULL) + if (m->md_dict == NULL) goto fail; - if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0) + if (PyDict_SetItemString(m->md_dict, "__name__", name) != 0) goto fail; if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0) goto fail; if (PyDict_SetItemString(m->md_dict, "__package__", Py_None) != 0) goto fail; - Py_DECREF(nameobj); PyObject_GC_Track(m); return (PyObject *)m; fail: - Py_XDECREF(nameobj); Py_DECREF(m); return NULL; } PyObject * +PyModule_New(const char *name) +{ + PyObject *nameobj, *module; + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + module = PyModule_NewObject(nameobj); + Py_DECREF(nameobj); + return module; +} + + +PyObject * PyModule_Create2(struct PyModuleDef* module, int module_api_version) { PyObject *d, *v, *n; @@ -175,24 +184,35 @@ PyModule_GetDict(PyObject *m) return d; } -const char * -PyModule_GetName(PyObject *m) +PyObject* +PyModule_GetNameObject(PyObject *m) { PyObject *d; - PyObject *nameobj; + PyObject *name; if (!PyModule_Check(m)) { PyErr_BadArgument(); return NULL; } d = ((PyModuleObject *)m)->md_dict; if (d == NULL || - (nameobj = PyDict_GetItemString(d, "__name__")) == NULL || - !PyUnicode_Check(nameobj)) + (name = PyDict_GetItemString(d, "__name__")) == NULL || + !PyUnicode_Check(name)) { PyErr_SetString(PyExc_SystemError, "nameless module"); return NULL; } - return _PyUnicode_AsString(nameobj); + Py_INCREF(name); + return name; +} + +const char * +PyModule_GetName(PyObject *m) +{ + PyObject *name = PyModule_GetNameObject(m); + if (name == NULL) + return NULL; + Py_DECREF(name); /* module dict has still a reference */ + return _PyUnicode_AsString(name); } PyObject* @@ -225,7 +245,7 @@ PyModule_GetFilename(PyObject *m) if (fileobj == NULL) return NULL; utf8 = _PyUnicode_AsString(fileobj); - Py_DECREF(fileobj); + Py_DECREF(fileobj); /* module dict has still a reference */ return utf8; } @@ -271,8 +291,8 @@ _PyModule_Clear(PyObject *m) pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - Py_UNICODE *u = PyUnicode_AS_UNICODE(key); - if (u[0] == '_' && u[1] != '_') { + if (PyUnicode_READ_CHAR(key, 0) == '_' && + PyUnicode_READ_CHAR(key, 1) != '_') { if (Py_VerboseFlag > 1) { const char *s = _PyUnicode_AsString(key); if (s != NULL) @@ -289,9 +309,8 @@ _PyModule_Clear(PyObject *m) pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { if (value != Py_None && PyUnicode_Check(key)) { - Py_UNICODE *u = PyUnicode_AS_UNICODE(key); - if (u[0] != '_' - || PyUnicode_CompareWithASCIIString(key, "__builtins__") != 0) + if (PyUnicode_READ_CHAR(key, 0) != '_' || + PyUnicode_CompareWithASCIIString(key, "__builtins__") != 0) { if (Py_VerboseFlag > 1) { const char *s = _PyUnicode_AsString(key); @@ -353,21 +372,54 @@ module_dealloc(PyModuleObject *m) static PyObject * module_repr(PyModuleObject *m) { - const char *name; - PyObject *filename, *repr; + PyObject *name, *filename, *repr, *loader = NULL; - name = PyModule_GetName((PyObject *)m); + /* See if the module has an __loader__. If it does, give the loader the + * first shot at producing a repr for the module. + */ + if (m->md_dict != NULL) { + loader = PyDict_GetItemString(m->md_dict, "__loader__"); + } + if (loader != NULL) { + repr = PyObject_CallMethod(loader, "module_repr", "(O)", + (PyObject *)m, NULL); + if (repr == NULL) { + PyErr_Clear(); + } + else { + return repr; + } + } + /* __loader__.module_repr(m) did not provide us with a repr. Next, see if + * the module has an __file__. If it doesn't then use repr(__loader__) if + * it exists, otherwise, just use module.__name__. + */ + name = PyModule_GetNameObject((PyObject *)m); if (name == NULL) { PyErr_Clear(); - name = "?"; + name = PyUnicode_FromStringAndSize("?", 1); + if (name == NULL) + return NULL; } filename = PyModule_GetFilenameObject((PyObject *)m); if (filename == NULL) { PyErr_Clear(); - return PyUnicode_FromFormat("<module '%s' (built-in)>", name); + /* There's no m.__file__, so if there was an __loader__, use that in + * the repr, otherwise, the only thing you can use is m.__name__ + */ + if (loader == NULL) { + repr = PyUnicode_FromFormat("<module %R>", name); + } + else { + repr = PyUnicode_FromFormat("<module %R (%R)>", name, loader); + } + } + /* Finally, use m.__file__ */ + else { + repr = PyUnicode_FromFormat("<module %R from %R>", name, filename); + Py_DECREF(filename); } - repr = PyUnicode_FromFormat("<module '%s' from '%U'>", name, filename); - Py_DECREF(filename); + Py_DECREF(name); return repr; } @@ -395,6 +447,35 @@ module_clear(PyModuleObject *m) return 0; } +static PyObject * +module_dir(PyObject *self, PyObject *args) +{ + _Py_IDENTIFIER(__dict__); + PyObject *result = NULL; + PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__); + + if (dict != NULL) { + if (PyDict_Check(dict)) + result = PyDict_Keys(dict); + else { + const char *name = PyModule_GetName(self); + if (name) + PyErr_Format(PyExc_TypeError, + "%.200s.__dict__ is not a dictionary", + name); + } + } + + Py_XDECREF(dict); + return result; +} + +static PyMethodDef module_methods[] = { + {"__dir__", module_dir, METH_NOARGS, + PyDoc_STR("__dir__() -> list\nspecialized dir() implementation")}, + {0} +}; + PyDoc_STRVAR(module_doc, "module(name[, doc])\n\ @@ -431,7 +512,7 @@ PyTypeObject PyModule_Type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + module_methods, /* tp_methods */ module_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ |