use const for readonly strings and set some functions to static
[blender.git] / source / blender / python / generic / bpy_internal_import.c
1 /* 
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * This is a new part of Blender.
22  *
23  * Contributor(s): Willian P. Germano
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/python/generic/bpy_internal_import.c
29  *  \ingroup pygen
30  */
31
32
33 #include <Python.h>
34 #include <stddef.h>
35
36 #include "bpy_internal_import.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_text_types.h"
41
42 #include "BLI_listbase.h"
43 #include "BLI_path_util.h"
44 #include "BLI_string.h"
45 #include "BLI_utildefines.h"
46
47  /* UNUSED */   
48 #include "BKE_text.h" /* txt_to_buf */  
49 #include "BKE_main.h"
50
51 static Main *bpy_import_main= NULL;
52
53 /* 'builtins' is most likely PyEval_GetBuiltins() */
54 void bpy_import_init(PyObject *builtins)
55 {
56         PyObject *item;
57         PyObject *mod;
58
59         PyDict_SetItemString(builtins, "__import__",    item=PyCFunction_New(&bpy_import_meth, NULL));  Py_DECREF(item);
60
61         /* move reload here
62          * XXX, use import hooks */
63         mod= PyImport_ImportModuleLevel((char *)"imp", NULL, NULL, NULL, 0);
64         if (mod) {
65                 PyDict_SetItemString(PyModule_GetDict(mod), "reload", item=PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item);
66                 Py_DECREF(mod);
67         }
68         else {
69                 BLI_assert(!"unable to load 'imp' module.");
70         }
71 }
72
73
74 static void free_compiled_text(Text *text)
75 {
76         if (text->compiled) {
77                 Py_DECREF((PyObject *)text->compiled);
78         }
79         text->compiled= NULL;
80 }
81
82 struct Main *bpy_import_main_get(void)
83 {
84         return bpy_import_main;
85 }
86
87 void bpy_import_main_set(struct Main *maggie)
88 {
89         bpy_import_main= maggie;
90 }
91
92 /* returns a dummy filename for a textblock so we can tell what file a text block comes from */
93 void bpy_text_filename_get(char *fn, size_t fn_len, Text *text)
94 {
95         BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bpy_import_main, &text->id), SEP, text->id.name+2);
96 }
97
98 PyObject *bpy_text_import(Text *text)
99 {
100         char *buf= NULL;
101         char modulename[24];
102         int len;
103
104         if (!text->compiled) {
105                 char fn_dummy[256];
106                 bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text);
107
108                 buf= txt_to_buf(text);
109                 text->compiled= Py_CompileString(buf, fn_dummy, Py_file_input);
110                 MEM_freeN(buf);
111
112                 if (PyErr_Occurred()) {
113                         PyErr_Print();
114                         PyErr_Clear();
115                         PySys_SetObject("last_traceback", NULL);
116                         free_compiled_text(text);
117                         return NULL;
118                 }
119         }
120
121         len= strlen(text->id.name+2);
122         BLI_strncpy(modulename, text->id.name+2, len);
123         modulename[len - 3]= '\0'; /* remove .py */
124         return PyImport_ExecCodeModule(modulename, text->compiled);
125 }
126
127 PyObject *bpy_text_import_name(const char *name, int *found)
128 {
129         Text *text;
130         char txtname[MAX_ID_NAME-2];
131         int namelen= strlen(name);
132 //XXX   Main *maggie= bpy_import_main ? bpy_import_main:G.main;
133         Main *maggie= bpy_import_main;
134         
135         *found= 0;
136
137         if (!maggie) {
138                 printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
139                 return NULL;
140         }
141         
142         if (namelen >= (MAX_ID_NAME-2) - 3) return NULL; /* we know this cant be importable, the name is too long for blender! */
143         
144         memcpy(txtname, name, namelen);
145         memcpy(&txtname[namelen], ".py", 4);
146
147         text= BLI_findstring(&maggie->text, txtname, offsetof(ID, name) + 2);
148
149         if (!text)
150                 return NULL;
151         else
152                 *found= 1;
153         
154         return bpy_text_import(text);
155 }
156
157
158 /*
159  * find in-memory module and recompile
160  */
161
162 PyObject *bpy_text_reimport(PyObject *module, int *found)
163 {
164         Text *text;
165         const char *name;
166         char *filepath;
167         char *buf= NULL;
168 //XXX   Main *maggie= bpy_import_main ? bpy_import_main:G.main;
169         Main *maggie= bpy_import_main;
170         
171         if (!maggie) {
172                 printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
173                 return NULL;
174         }
175         
176         *found= 0;
177         
178         /* get name, filename from the module itself */
179         if ((name= PyModule_GetName(module)) == NULL)
180                 return NULL;
181
182         if ((filepath= (char *)PyModule_GetFilename(module)) == NULL)
183                 return NULL;
184
185         /* look up the text object */
186         text= BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2);
187
188         /* uh-oh.... didn't find it */
189         if (!text)
190                 return NULL;
191         else
192                 *found= 1;
193
194         /* if previously compiled, free the object */
195         /* (can't see how could be NULL, but check just in case) */ 
196         if (text->compiled) {
197                 Py_DECREF((PyObject *)text->compiled);
198         }
199
200         /* compile the buffer */
201         buf= txt_to_buf(text);
202         text->compiled= Py_CompileString(buf, text->id.name+2, Py_file_input);
203         MEM_freeN(buf);
204
205         /* if compile failed.... return this error */
206         if (PyErr_Occurred()) {
207                 PyErr_Print();
208                 PyErr_Clear();
209                 PySys_SetObject("last_traceback", NULL);
210                 free_compiled_text(text);
211                 return NULL;
212         }
213
214         /* make into a module */
215         return PyImport_ExecCodeModule((char *)name, text->compiled);
216 }
217
218
219 static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
220 {
221         PyObject *exception, *err, *tb;
222         char *name;
223         int found= 0;
224         PyObject *globals= NULL, *locals= NULL, *fromlist= NULL;
225         int level= -1; /* relative imports */
226         
227         PyObject *newmodule;
228         //PyObject_Print(args, stderr, 0);
229         static const char *kwlist[]= {"name", "globals", "locals", "fromlist", "level", NULL};
230         
231         if (!PyArg_ParseTupleAndKeywords(args, kw, "s|OOOi:bpy_import_meth", (char **)kwlist,
232                                    &name, &globals, &locals, &fromlist, &level))
233                 return NULL;
234
235         /* import existing builtin modules or modules that have been imported already */
236         newmodule= PyImport_ImportModuleLevel(name, globals, locals, fromlist, level);
237         
238         if (newmodule)
239                 return newmodule;
240         
241         PyErr_Fetch(&exception, &err, &tb);     /* get the python error incase we cant import as blender text either */
242         
243         /* importing from existing modules failed, see if we have this module as blender text */
244         newmodule= bpy_text_import_name(name, &found);
245         
246         if (newmodule) {/* found module as blender text, ignore above exception */
247                 PyErr_Clear();
248                 Py_XDECREF(exception);
249                 Py_XDECREF(err);
250                 Py_XDECREF(tb);
251                 /* printf("imported from text buffer...\n"); */
252         }
253         else if (found==1) { /* blender text module failed to execute but was found, use its error message */
254                 Py_XDECREF(exception);
255                 Py_XDECREF(err);
256                 Py_XDECREF(tb);
257                 return NULL;
258         }
259         else {
260                 /* no blender text was found that could import the module
261                  * rause the original error from PyImport_ImportModuleEx */
262                 PyErr_Restore(exception, err, tb);
263         }
264         return newmodule;
265 }
266
267
268 /*
269  * our reload() module, to handle reloading in-memory scripts
270  */
271
272 static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module)
273 {
274         PyObject *exception, *err, *tb;
275         PyObject *newmodule= NULL;
276         int found= 0;
277
278         /* try reimporting from file */
279         newmodule= PyImport_ReloadModule(module);
280         if (newmodule)
281                 return newmodule;
282
283         /* no file, try importing from memory */
284         PyErr_Fetch(&exception, &err, &tb);     /*restore for probable later use */
285
286         newmodule= bpy_text_reimport(module, &found);
287         if (newmodule) {/* found module as blender text, ignore above exception */
288                 PyErr_Clear();
289                 Py_XDECREF(exception);
290                 Py_XDECREF(err);
291                 Py_XDECREF(tb);
292                 /* printf("imported from text buffer...\n"); */
293         }
294         else if (found==1) { /* blender text module failed to execute but was found, use its error message */
295                 Py_XDECREF(exception);
296                 Py_XDECREF(err);
297                 Py_XDECREF(tb);
298                 return NULL;
299         }
300         else {
301                 /* no blender text was found that could import the module
302                  * reuse the original error from PyImport_ImportModuleEx */
303                 PyErr_Restore(exception, err, tb);
304         }
305
306         return newmodule;
307 }
308
309 PyMethodDef bpy_import_meth= {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"};
310 PyMethodDef bpy_reload_meth= {"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"};
311
312
313 /* Clear user modules.
314  * This is to clear any modules that could be defined from running scripts in blender.
315  * 
316  * Its also needed for the BGE Python api so imported scripts are not used between levels
317  * 
318  * This clears every modules that has a __file__ attribute (is not a builtin)
319  *
320  * Note that clearing external python modules is important for the BGE otherwise
321  * it wont reload scripts between loading different blend files or while making the game.
322  * - use 'clear_all' arg in this case.
323  *
324  * Since pythons built-ins include a full path even for win32.
325  * even if we remove a python module a re-import will bring it back again.
326  */
327
328 #if 0 // not used anymore but may still come in handy later
329
330 #if defined(WIN32) || defined(WIN64)
331 #define SEPSTR "\\"
332 #else
333 #define SEPSTR "/"
334 #endif
335
336
337 void bpy_text_clear_modules(int clear_all)
338 {
339         PyObject *modules= PyImport_GetModuleDict();
340         
341         char *fname;
342         char *file_extension;
343         
344         /* looping over the dict */
345         PyObject *key, *value;
346         Py_ssize_t pos= 0;
347         
348         /* new list */
349         PyObject *list;
350
351         if (modules==NULL)
352                 return; /* should never happen but just incase */
353
354         list= PyList_New(0);
355
356         /* go over sys.modules and remove anything with a 
357          * sys.modukes[x].__file__ thats ends with a .py and has no path
358          */
359         while (PyDict_Next(modules, &pos, &key, &value)) {
360                 fname= PyModule_GetFilename(value);
361                 if (fname) {
362                         if (clear_all || ((strstr(fname, SEPSTR))==0)) { /* no path ? */
363                                 file_extension= strstr(fname, ".py");
364                                 if (file_extension && (*(file_extension + 3) == '\0' || *(file_extension + 4) == '\0')) { /* .py or pyc extension? */
365                                         /* now we can be fairly sure its a python import from the blendfile */
366                                         PyList_Append(list, key); /* free'd with the list */
367                                 }
368                         }
369                 }
370                 else {
371                         PyErr_Clear();
372                 }
373         }
374         
375         /* remove all our modules */
376         for (pos=0; pos < PyList_GET_SIZE(list); pos++) {
377                 /* PyObject_Print(key, stderr, 0); */
378                 key= PyList_GET_ITEM(list, pos);
379                 PyDict_DelItem(modules, key);
380         }
381         
382         Py_DECREF(list); /* removes all references from append */
383 }
384 #endif