Updated for 2.1a3
[python/dscho.git] / Objects / moduleobject.c
blobf9c9228c6cc518c856fffeb3b001e660575e901c
2 /* Module object implementation */
4 #include "Python.h"
6 typedef struct {
7 PyObject_HEAD
8 PyObject *md_dict;
9 } PyModuleObject;
11 PyObject *
12 PyModule_New(char *name)
14 PyModuleObject *m;
15 PyObject *nameobj;
16 m = PyObject_NEW(PyModuleObject, &PyModule_Type);
17 if (m == NULL)
18 return NULL;
19 nameobj = PyString_FromString(name);
20 m->md_dict = PyDict_New();
21 PyObject_GC_Init(m);
22 if (m->md_dict == NULL || nameobj == NULL)
23 goto fail;
24 if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)
25 goto fail;
26 if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)
27 goto fail;
28 Py_DECREF(nameobj);
29 return (PyObject *)m;
31 fail:
32 Py_XDECREF(nameobj);
33 Py_DECREF(m);
34 return NULL;
37 PyObject *
38 PyModule_GetDict(PyObject *m)
40 if (!PyModule_Check(m)) {
41 PyErr_BadInternalCall();
42 return NULL;
44 return ((PyModuleObject *)m) -> md_dict;
47 char *
48 PyModule_GetName(PyObject *m)
50 PyObject *nameobj;
51 if (!PyModule_Check(m)) {
52 PyErr_BadArgument();
53 return NULL;
55 nameobj = PyDict_GetItemString(((PyModuleObject *)m)->md_dict,
56 "__name__");
57 if (nameobj == NULL || !PyString_Check(nameobj)) {
58 PyErr_SetString(PyExc_SystemError, "nameless module");
59 return NULL;
61 return PyString_AsString(nameobj);
64 char *
65 PyModule_GetFilename(PyObject *m)
67 PyObject *fileobj;
68 if (!PyModule_Check(m)) {
69 PyErr_BadArgument();
70 return NULL;
72 fileobj = PyDict_GetItemString(((PyModuleObject *)m)->md_dict,
73 "__file__");
74 if (fileobj == NULL || !PyString_Check(fileobj)) {
75 PyErr_SetString(PyExc_SystemError, "module filename missing");
76 return NULL;
78 return PyString_AsString(fileobj);
81 void
82 _PyModule_Clear(PyObject *m)
84 /* To make the execution order of destructors for global
85 objects a bit more predictable, we first zap all objects
86 whose name starts with a single underscore, before we clear
87 the entire dictionary. We zap them by replacing them with
88 None, rather than deleting them from the dictionary, to
89 avoid rehashing the dictionary (to some extent). */
91 int pos;
92 PyObject *key, *value;
93 PyObject *d;
95 d = ((PyModuleObject *)m)->md_dict;
97 /* First, clear only names starting with a single underscore */
98 pos = 0;
99 while (PyDict_Next(d, &pos, &key, &value)) {
100 if (value != Py_None && PyString_Check(key)) {
101 char *s = PyString_AsString(key);
102 if (s[0] == '_' && s[1] != '_') {
103 if (Py_VerboseFlag > 1)
104 PySys_WriteStderr("# clear[1] %s\n", s);
105 PyDict_SetItem(d, key, Py_None);
110 /* Next, clear all names except for __builtins__ */
111 pos = 0;
112 while (PyDict_Next(d, &pos, &key, &value)) {
113 if (value != Py_None && PyString_Check(key)) {
114 char *s = PyString_AsString(key);
115 if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {
116 if (Py_VerboseFlag > 1)
117 PySys_WriteStderr("# clear[2] %s\n", s);
118 PyDict_SetItem(d, key, Py_None);
123 /* Note: we leave __builtins__ in place, so that destructors
124 of non-global objects defined in this module can still use
125 builtins, in particularly 'None'. */
129 /* Methods */
131 static void
132 module_dealloc(PyModuleObject *m)
134 PyObject_GC_Fini(m);
135 if (m->md_dict != NULL) {
136 _PyModule_Clear((PyObject *)m);
137 Py_DECREF(m->md_dict);
139 PyObject_DEL(PyObject_AS_GC(m));
142 static PyObject *
143 module_repr(PyModuleObject *m)
145 char buf[400];
146 char *name;
147 char *filename;
148 name = PyModule_GetName((PyObject *)m);
149 if (name == NULL) {
150 PyErr_Clear();
151 name = "?";
153 filename = PyModule_GetFilename((PyObject *)m);
154 if (filename == NULL) {
155 PyErr_Clear();
156 sprintf(buf, "<module '%.80s' (built-in)>", name);
157 } else {
158 sprintf(buf, "<module '%.80s' from '%.255s'>", name, filename);
161 return PyString_FromString(buf);
164 static PyObject *
165 module_getattr(PyModuleObject *m, char *name)
167 PyObject *res;
168 char* modname;
169 if (strcmp(name, "__dict__") == 0) {
170 Py_INCREF(m->md_dict);
171 return m->md_dict;
173 res = PyDict_GetItemString(m->md_dict, name);
174 if (res == NULL) {
175 modname = PyModule_GetName((PyObject *)m);
176 if (modname == NULL) {
177 PyErr_Clear();
178 modname = "?";
180 PyErr_Format(PyExc_AttributeError,
181 "'%.50s' module has no attribute '%.400s'",
182 modname, name);
184 else
185 Py_INCREF(res);
186 return res;
189 static int
190 module_setattr(PyModuleObject *m, char *name, PyObject *v)
192 char* modname;
193 if (name[0] == '_' && strcmp(name, "__dict__") == 0) {
194 PyErr_SetString(PyExc_TypeError,
195 "read-only special attribute");
196 return -1;
198 if (v == NULL) {
199 int rv = PyDict_DelItemString(m->md_dict, name);
200 if (rv < 0) {
201 modname = PyModule_GetName((PyObject *)m);
202 if (modname == NULL) {
203 PyErr_Clear();
204 modname = "?";
206 PyErr_Format(PyExc_AttributeError,
207 "'%.50s' module has no attribute '%.400s'",
208 modname, name);
210 return rv;
212 else
213 return PyDict_SetItemString(m->md_dict, name, v);
216 /* We only need a traverse function, no clear function: If the module
217 is in a cycle, md_dict will be cleared as well, which will break
218 the cycle. */
219 static int
220 module_traverse(PyModuleObject *m, visitproc visit, void *arg)
222 if (m->md_dict != NULL)
223 return visit(m->md_dict, arg);
224 return 0;
227 PyTypeObject PyModule_Type = {
228 PyObject_HEAD_INIT(&PyType_Type)
229 0, /*ob_size*/
230 "module", /*tp_name*/
231 sizeof(PyModuleObject) + PyGC_HEAD_SIZE, /*tp_size*/
232 0, /*tp_itemsize*/
233 (destructor)module_dealloc, /*tp_dealloc*/
234 0, /*tp_print*/
235 (getattrfunc)module_getattr, /*tp_getattr*/
236 (setattrfunc)module_setattr, /*tp_setattr*/
237 0, /*tp_compare*/
238 (reprfunc)module_repr, /*tp_repr*/
239 0, /*tp_as_number*/
240 0, /*tp_as_sequence*/
241 0, /*tp_as_mapping*/
242 0, /* tp_hash */
243 0, /* tp_call */
244 0, /* tp_str */
245 0, /* tp_getattro */
246 0, /* tp_setattro */
247 0, /* tp_as_buffer */
248 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/
249 0, /* tp_doc */
250 (traverseproc)module_traverse, /* tp_traverse */