summaryrefslogtreecommitdiffstats
path: root/Objects/moduleobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/moduleobject.c')
-rw-r--r--Objects/moduleobject.c244
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 */