1
2/* Module object implementation */
3
4#include "Python.h"
5#include "structmember.h"
6
7typedef struct {
8    PyObject_HEAD
9    PyObject *md_dict;
10} PyModuleObject;
11
12static PyMemberDef module_members[] = {
13    {"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},
14    {0}
15};
16
17PyObject *
18PyModule_New(const char *name)
19{
20    PyModuleObject *m;
21    PyObject *nameobj;
22    m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
23    if (m == NULL)
24        return NULL;
25    nameobj = PyString_FromString(name);
26    m->md_dict = PyDict_New();
27    if (m->md_dict == NULL || nameobj == NULL)
28        goto fail;
29    if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)
30        goto fail;
31    if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)
32        goto fail;
33    if (PyDict_SetItemString(m->md_dict, "__package__", Py_None) != 0)
34        goto fail;
35    Py_DECREF(nameobj);
36    PyObject_GC_Track(m);
37    return (PyObject *)m;
38
39 fail:
40    Py_XDECREF(nameobj);
41    Py_DECREF(m);
42    return NULL;
43}
44
45PyObject *
46PyModule_GetDict(PyObject *m)
47{
48    PyObject *d;
49    if (!PyModule_Check(m)) {
50        PyErr_BadInternalCall();
51        return NULL;
52    }
53    d = ((PyModuleObject *)m) -> md_dict;
54    if (d == NULL)
55        ((PyModuleObject *)m) -> md_dict = d = PyDict_New();
56    return d;
57}
58
59char *
60PyModule_GetName(PyObject *m)
61{
62    PyObject *d;
63    PyObject *nameobj;
64    if (!PyModule_Check(m)) {
65        PyErr_BadArgument();
66        return NULL;
67    }
68    d = ((PyModuleObject *)m)->md_dict;
69    if (d == NULL ||
70        (nameobj = PyDict_GetItemString(d, "__name__")) == NULL ||
71        !PyString_Check(nameobj))
72    {
73        PyErr_SetString(PyExc_SystemError, "nameless module");
74        return NULL;
75    }
76    return PyString_AsString(nameobj);
77}
78
79char *
80PyModule_GetFilename(PyObject *m)
81{
82    PyObject *d;
83    PyObject *fileobj;
84    if (!PyModule_Check(m)) {
85        PyErr_BadArgument();
86        return NULL;
87    }
88    d = ((PyModuleObject *)m)->md_dict;
89    if (d == NULL ||
90        (fileobj = PyDict_GetItemString(d, "__file__")) == NULL ||
91        !PyString_Check(fileobj))
92    {
93        PyErr_SetString(PyExc_SystemError, "module filename missing");
94        return NULL;
95    }
96    return PyString_AsString(fileobj);
97}
98
99void
100_PyModule_Clear(PyObject *m)
101{
102    /* To make the execution order of destructors for global
103       objects a bit more predictable, we first zap all objects
104       whose name starts with a single underscore, before we clear
105       the entire dictionary.  We zap them by replacing them with
106       None, rather than deleting them from the dictionary, to
107       avoid rehashing the dictionary (to some extent). */
108
109    Py_ssize_t pos;
110    PyObject *key, *value;
111    PyObject *d;
112
113    d = ((PyModuleObject *)m)->md_dict;
114    if (d == NULL)
115        return;
116
117    /* First, clear only names starting with a single underscore */
118    pos = 0;
119    while (PyDict_Next(d, &pos, &key, &value)) {
120        if (value != Py_None && PyString_Check(key)) {
121            char *s = PyString_AsString(key);
122            if (s[0] == '_' && s[1] != '_') {
123                if (Py_VerboseFlag > 1)
124                    PySys_WriteStderr("#   clear[1] %s\n", s);
125                if (PyDict_SetItem(d, key, Py_None) != 0)
126                    PyErr_Clear();
127            }
128        }
129    }
130
131    /* Next, clear all names except for __builtins__ */
132    pos = 0;
133    while (PyDict_Next(d, &pos, &key, &value)) {
134        if (value != Py_None && PyString_Check(key)) {
135            char *s = PyString_AsString(key);
136            if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {
137                if (Py_VerboseFlag > 1)
138                    PySys_WriteStderr("#   clear[2] %s\n", s);
139                if (PyDict_SetItem(d, key, Py_None) != 0)
140                    PyErr_Clear();
141            }
142        }
143    }
144
145    /* Note: we leave __builtins__ in place, so that destructors
146       of non-global objects defined in this module can still use
147       builtins, in particularly 'None'. */
148
149}
150
151/* Methods */
152
153static int
154module_init(PyModuleObject *m, PyObject *args, PyObject *kwds)
155{
156    static char *kwlist[] = {"name", "doc", NULL};
157    PyObject *dict, *name = Py_None, *doc = Py_None;
158    if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|O:module.__init__",
159                                     kwlist, &name, &doc))
160        return -1;
161    dict = m->md_dict;
162    if (dict == NULL) {
163        dict = PyDict_New();
164        if (dict == NULL)
165            return -1;
166        m->md_dict = dict;
167    }
168    if (PyDict_SetItemString(dict, "__name__", name) < 0)
169        return -1;
170    if (PyDict_SetItemString(dict, "__doc__", doc) < 0)
171        return -1;
172    return 0;
173}
174
175static void
176module_dealloc(PyModuleObject *m)
177{
178    PyObject_GC_UnTrack(m);
179    if (m->md_dict != NULL) {
180        _PyModule_Clear((PyObject *)m);
181        Py_DECREF(m->md_dict);
182    }
183    Py_TYPE(m)->tp_free((PyObject *)m);
184}
185
186static PyObject *
187module_repr(PyModuleObject *m)
188{
189    char *name;
190    char *filename;
191
192    name = PyModule_GetName((PyObject *)m);
193    if (name == NULL) {
194        PyErr_Clear();
195        name = "?";
196    }
197    filename = PyModule_GetFilename((PyObject *)m);
198    if (filename == NULL) {
199        PyErr_Clear();
200        return PyString_FromFormat("<module '%s' (built-in)>", name);
201    }
202    return PyString_FromFormat("<module '%s' from '%s'>", name, filename);
203}
204
205/* We only need a traverse function, no clear function: If the module
206   is in a cycle, md_dict will be cleared as well, which will break
207   the cycle. */
208static int
209module_traverse(PyModuleObject *m, visitproc visit, void *arg)
210{
211    Py_VISIT(m->md_dict);
212    return 0;
213}
214
215PyDoc_STRVAR(module_doc,
216"module(name[, doc])\n\
217\n\
218Create a module object.\n\
219The name must be a string; the optional doc argument can have any type.");
220
221PyTypeObject PyModule_Type = {
222    PyVarObject_HEAD_INIT(&PyType_Type, 0)
223    "module",                                   /* tp_name */
224    sizeof(PyModuleObject),                     /* tp_size */
225    0,                                          /* tp_itemsize */
226    (destructor)module_dealloc,                 /* tp_dealloc */
227    0,                                          /* tp_print */
228    0,                                          /* tp_getattr */
229    0,                                          /* tp_setattr */
230    0,                                          /* tp_compare */
231    (reprfunc)module_repr,                      /* tp_repr */
232    0,                                          /* tp_as_number */
233    0,                                          /* tp_as_sequence */
234    0,                                          /* tp_as_mapping */
235    0,                                          /* tp_hash */
236    0,                                          /* tp_call */
237    0,                                          /* tp_str */
238    PyObject_GenericGetAttr,                    /* tp_getattro */
239    PyObject_GenericSetAttr,                    /* tp_setattro */
240    0,                                          /* tp_as_buffer */
241    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
242        Py_TPFLAGS_BASETYPE,                    /* tp_flags */
243    module_doc,                                 /* tp_doc */
244    (traverseproc)module_traverse,              /* tp_traverse */
245    0,                                          /* tp_clear */
246    0,                                          /* tp_richcompare */
247    0,                                          /* tp_weaklistoffset */
248    0,                                          /* tp_iter */
249    0,                                          /* tp_iternext */
250    0,                                          /* tp_methods */
251    module_members,                             /* tp_members */
252    0,                                          /* tp_getset */
253    0,                                          /* tp_base */
254    0,                                          /* tp_dict */
255    0,                                          /* tp_descr_get */
256    0,                                          /* tp_descr_set */
257    offsetof(PyModuleObject, md_dict),          /* tp_dictoffset */
258    (initproc)module_init,                      /* tp_init */
259    PyType_GenericAlloc,                        /* tp_alloc */
260    PyType_GenericNew,                          /* tp_new */
261    PyObject_GC_Del,                            /* tp_free */
262};
263