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