diff options
Diffstat (limited to 'Objects/moduleobject.c')
| -rw-r--r-- | Objects/moduleobject.c | 244 |
1 files changed, 215 insertions, 29 deletions
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 08e9740..533db46 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -4,9 +4,13 @@ #include "Python.h" #include "structmember.h" +static Py_ssize_t max_module_number; + typedef struct { PyObject_HEAD PyObject *md_dict; + struct PyModuleDef *md_def; + void *md_state; } PyModuleObject; static PyMemberDef module_members[] = { @@ -14,6 +18,14 @@ static PyMemberDef module_members[] = { {0} }; +static PyTypeObject moduledef_type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "moduledef", /* tp_name */ + sizeof(struct PyModuleDef), /* tp_size */ + 0, /* tp_itemsize */ +}; + + PyObject * PyModule_New(const char *name) { @@ -22,7 +34,9 @@ PyModule_New(const char *name) m = PyObject_GC_New(PyModuleObject, &PyModule_Type); if (m == NULL) return NULL; - nameobj = PyString_FromString(name); + m->md_def = NULL; + m->md_state = NULL; + nameobj = PyUnicode_FromString(name); m->md_dict = PyDict_New(); if (m->md_dict == NULL || nameobj == NULL) goto fail; @@ -43,6 +57,111 @@ PyModule_New(const char *name) } PyObject * +PyModule_Create2(struct PyModuleDef* module, int module_api_version) +{ + PyObject *d, *v, *n; + PyMethodDef *ml; + const char* name; + PyModuleObject *m; + PyInterpreterState *interp = PyThreadState_Get()->interp; + if (interp->modules == NULL) + Py_FatalError("Python import machinery not initialized"); + if (PyType_Ready(&moduledef_type) < 0) + return NULL; + if (module->m_base.m_index == 0) { + max_module_number++; + Py_REFCNT(module) = 1; + Py_TYPE(module) = &moduledef_type; + module->m_base.m_index = max_module_number; + } + name = module->m_name; + if (module_api_version != PYTHON_API_VERSION && module_api_version != PYTHON_ABI_VERSION) { + int err; + err = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, + "Python C API version mismatch for module %.100s: " + "This Python has API version %d, module %.100s has version %d.", + name, + PYTHON_API_VERSION, name, module_api_version); + if (err) + return NULL; + } + /* Make sure name is fully qualified. + + This is a bit of a hack: when the shared library is loaded, + the module name is "package.module", but the module calls + PyModule_Create*() with just "module" for the name. The shared + library loader squirrels away the true name of the module in + _Py_PackageContext, and PyModule_Create*() will substitute this + (if the name actually matches). + */ + if (_Py_PackageContext != NULL) { + char *p = strrchr(_Py_PackageContext, '.'); + if (p != NULL && strcmp(module->m_name, p+1) == 0) { + name = _Py_PackageContext; + _Py_PackageContext = NULL; + } + } + if ((m = (PyModuleObject*)PyModule_New(name)) == NULL) + return NULL; + + if (module->m_size > 0) { + m->md_state = PyMem_MALLOC(module->m_size); + if (!m->md_state) { + PyErr_NoMemory(); + Py_DECREF(m); + return NULL; + } + memset(m->md_state, 0, module->m_size); + } + + d = PyModule_GetDict((PyObject*)m); + if (module->m_methods != NULL) { + n = PyUnicode_FromString(name); + if (n == NULL) { + Py_DECREF(m); + return NULL; + } + for (ml = module->m_methods; ml->ml_name != NULL; ml++) { + if ((ml->ml_flags & METH_CLASS) || + (ml->ml_flags & METH_STATIC)) { + PyErr_SetString(PyExc_ValueError, + "module functions cannot set" + " METH_CLASS or METH_STATIC"); + Py_DECREF(n); + Py_DECREF(m); + return NULL; + } + v = PyCFunction_NewEx(ml, (PyObject*)m, n); + if (v == NULL) { + Py_DECREF(n); + Py_DECREF(m); + return NULL; + } + if (PyDict_SetItemString(d, ml->ml_name, v) != 0) { + Py_DECREF(v); + Py_DECREF(n); + Py_DECREF(m); + return NULL; + } + Py_DECREF(v); + } + Py_DECREF(n); + } + if (module->m_doc != NULL) { + v = PyUnicode_FromString(module->m_doc); + if (v == NULL || PyDict_SetItemString(d, "__doc__", v) != 0) { + Py_XDECREF(v); + Py_DECREF(m); + return NULL; + } + Py_DECREF(v); + } + m->md_def = module; + return (PyObject*)m; +} + + +PyObject * PyModule_GetDict(PyObject *m) { PyObject *d; @@ -56,7 +175,7 @@ PyModule_GetDict(PyObject *m) return d; } -char * +const char * PyModule_GetName(PyObject *m) { PyObject *d; @@ -68,16 +187,16 @@ PyModule_GetName(PyObject *m) d = ((PyModuleObject *)m)->md_dict; if (d == NULL || (nameobj = PyDict_GetItemString(d, "__name__")) == NULL || - !PyString_Check(nameobj)) + !PyUnicode_Check(nameobj)) { PyErr_SetString(PyExc_SystemError, "nameless module"); return NULL; } - return PyString_AsString(nameobj); + return _PyUnicode_AsString(nameobj); } -char * -PyModule_GetFilename(PyObject *m) +PyObject* +PyModule_GetFilenameObject(PyObject *m) { PyObject *d; PyObject *fileobj; @@ -88,12 +207,46 @@ PyModule_GetFilename(PyObject *m) d = ((PyModuleObject *)m)->md_dict; if (d == NULL || (fileobj = PyDict_GetItemString(d, "__file__")) == NULL || - !PyString_Check(fileobj)) + !PyUnicode_Check(fileobj)) { PyErr_SetString(PyExc_SystemError, "module filename missing"); return NULL; } - return PyString_AsString(fileobj); + Py_INCREF(fileobj); + return fileobj; +} + +const char * +PyModule_GetFilename(PyObject *m) +{ + PyObject *fileobj; + char *utf8; + fileobj = PyModule_GetFilenameObject(m); + if (fileobj == NULL) + return NULL; + utf8 = _PyUnicode_AsString(fileobj); + Py_DECREF(fileobj); + return utf8; +} + +PyModuleDef* +PyModule_GetDef(PyObject* m) +{ + if (!PyModule_Check(m)) { + PyErr_BadArgument(); + return NULL; + } + return ((PyModuleObject *)m)->md_def; +} + +void* +PyModule_GetState(PyObject* m) +{ + if (!PyModule_Check(m)) { + PyErr_BadArgument(); + return NULL; + } + return ((PyModuleObject *)m)->md_state; } void @@ -117,11 +270,16 @@ _PyModule_Clear(PyObject *m) /* First, clear only names starting with a single underscore */ pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { - if (value != Py_None && PyString_Check(key)) { - char *s = PyString_AsString(key); - if (s[0] == '_' && s[1] != '_') { - if (Py_VerboseFlag > 1) - PySys_WriteStderr("# clear[1] %s\n", s); + if (value != Py_None && PyUnicode_Check(key)) { + Py_UNICODE *u = PyUnicode_AS_UNICODE(key); + if (u[0] == '_' && u[1] != '_') { + if (Py_VerboseFlag > 1) { + const char *s = _PyUnicode_AsString(key); + if (s != NULL) + PySys_WriteStderr("# clear[1] %s\n", s); + else + PyErr_Clear(); + } PyDict_SetItem(d, key, Py_None); } } @@ -130,11 +288,18 @@ _PyModule_Clear(PyObject *m) /* Next, clear all names except for __builtins__ */ pos = 0; while (PyDict_Next(d, &pos, &key, &value)) { - if (value != Py_None && PyString_Check(key)) { - char *s = PyString_AsString(key); - if (s[0] != '_' || strcmp(s, "__builtins__") != 0) { - if (Py_VerboseFlag > 1) - PySys_WriteStderr("# clear[2] %s\n", s); + if (value != Py_None && PyUnicode_Check(key)) { + Py_UNICODE *u = PyUnicode_AS_UNICODE(key); + if (u[0] != '_' + || PyUnicode_CompareWithASCIIString(key, "__builtins__") != 0) + { + if (Py_VerboseFlag > 1) { + const char *s = _PyUnicode_AsString(key); + if (s != NULL) + PySys_WriteStderr("# clear[2] %s\n", s); + else + PyErr_Clear(); + } PyDict_SetItem(d, key, Py_None); } } @@ -153,7 +318,7 @@ module_init(PyModuleObject *m, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"name", "doc", NULL}; PyObject *dict, *name = Py_None, *doc = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|O:module.__init__", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|O:module.__init__", kwlist, &name, &doc)) return -1; dict = m->md_dict; @@ -174,42 +339,63 @@ static void module_dealloc(PyModuleObject *m) { PyObject_GC_UnTrack(m); + if (m->md_def && m->md_def->m_free) + m->md_def->m_free(m); if (m->md_dict != NULL) { _PyModule_Clear((PyObject *)m); Py_DECREF(m->md_dict); } + if (m->md_state != NULL) + PyMem_FREE(m->md_state); Py_TYPE(m)->tp_free((PyObject *)m); } static PyObject * module_repr(PyModuleObject *m) { - char *name; - char *filename; + const char *name; + PyObject *filename, *repr; name = PyModule_GetName((PyObject *)m); if (name == NULL) { PyErr_Clear(); name = "?"; } - filename = PyModule_GetFilename((PyObject *)m); + filename = PyModule_GetFilenameObject((PyObject *)m); if (filename == NULL) { PyErr_Clear(); - return PyString_FromFormat("<module '%s' (built-in)>", name); + return PyUnicode_FromFormat("<module '%s' (built-in)>", name); } - return PyString_FromFormat("<module '%s' from '%s'>", name, filename); + repr = PyUnicode_FromFormat("<module '%s' from '%U'>", name, filename); + Py_DECREF(filename); + return repr; } -/* We only need a traverse function, no clear function: If the module - is in a cycle, md_dict will be cleared as well, which will break - the cycle. */ static int module_traverse(PyModuleObject *m, visitproc visit, void *arg) { + if (m->md_def && m->md_def->m_traverse) { + int res = m->md_def->m_traverse((PyObject*)m, visit, arg); + if (res) + return res; + } Py_VISIT(m->md_dict); return 0; } +static int +module_clear(PyModuleObject *m) +{ + if (m->md_def && m->md_def->m_clear) { + int res = m->md_def->m_clear((PyObject*)m); + if (res) + return res; + } + Py_CLEAR(m->md_dict); + return 0; +} + + PyDoc_STRVAR(module_doc, "module(name[, doc])\n\ \n\ @@ -225,7 +411,7 @@ PyTypeObject PyModule_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)module_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -240,7 +426,7 @@ PyTypeObject PyModule_Type = { Py_TPFLAGS_BASETYPE, /* tp_flags */ module_doc, /* tp_doc */ (traverseproc)module_traverse, /* tp_traverse */ - 0, /* tp_clear */ + (inquiry)module_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ |
