873398e77638280db4346f435a830e90a6664cc9
[blender.git] / source / blender / python / generic / bpy_internal_import.c
1 /* 
2  * $Id$
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 #include "DNA_ID.h"
32
33 #include "MEM_guardedalloc.h"
34 #include "BKE_text.h" /* txt_to_buf */  
35 #include "BKE_main.h"
36 #include "BLI_listbase.h"
37 #include <stddef.h>
38
39 static Main *bpy_import_main= NULL;
40
41 static void free_compiled_text(Text *text)
42 {
43         if(text->compiled) {
44                 Py_DECREF(( PyObject * )text->compiled);
45         }
46         text->compiled= NULL;
47 }
48
49 struct Main *bpy_import_main_get(void)
50 {
51         return bpy_import_main;
52 }
53
54 void bpy_import_main_set(struct Main *maggie)
55 {
56         bpy_import_main= maggie;
57 }
58
59 PyObject *bpy_text_import( Text *text )
60 {
61         char *buf = NULL;
62         char modulename[24];
63         int len;
64
65         if( !text->compiled ) {
66                 buf = txt_to_buf( text );
67                 text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
68                 MEM_freeN( buf );
69
70                 if( PyErr_Occurred(  ) ) {
71                         PyErr_Print(  );
72                         PyErr_Clear(  );
73                         PySys_SetObject("last_traceback", NULL);
74                         free_compiled_text( text );
75                         return NULL;
76                 }
77         }
78
79         len= strlen(text->id.name+2);
80         strncpy(modulename, text->id.name+2, len);
81         modulename[len - 3]= '\0'; /* remove .py */
82         return PyImport_ExecCodeModule(modulename, text->compiled);
83 }
84
85 PyObject *bpy_text_import_name( char *name, int *found )
86 {
87         Text *text;
88         char txtname[22]; /* 21+NULL */
89         int namelen = strlen( name );
90 //XXX   Main *maggie= bpy_import_main ? bpy_import_main:G.main;
91         Main *maggie= bpy_import_main;
92         
93         *found= 0;
94
95         if(!maggie) {
96                 printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
97                 return NULL;
98         }
99         
100         if (namelen>21-3) return NULL; /* we know this cant be importable, the name is too long for blender! */
101         
102         memcpy( txtname, name, namelen );
103         memcpy( &txtname[namelen], ".py", 4 );
104
105         text= BLI_findstring(&maggie->text, txtname, offsetof(ID, name) + 2);
106
107         if( !text )
108                 return NULL;
109         else
110                 *found = 1;
111         
112         return bpy_text_import(text);
113 }
114
115
116 /*
117  * find in-memory module and recompile
118  */
119
120 PyObject *bpy_text_reimport( PyObject *module, int *found )
121 {
122         Text *text;
123         const char *txtname;
124         const char *name;
125         char *buf = NULL;
126 //XXX   Main *maggie= bpy_import_main ? bpy_import_main:G.main;
127         Main *maggie= bpy_import_main;
128         
129         if(!maggie) {
130                 printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
131                 return NULL;
132         }
133         
134         *found= 0;
135         
136         /* get name, filename from the module itself */
137
138         txtname = PyModule_GetFilename( module );
139         name = PyModule_GetName( module );
140         if( !txtname || !name)
141                 return NULL;
142
143         /* look up the text object */
144         text= BLI_findstring(&maggie->text, txtname, offsetof(ID, name) + 2);
145
146         /* uh-oh.... didn't find it */
147         if( !text )
148                 return NULL;
149         else
150                 *found = 1;
151
152         /* if previously compiled, free the object */
153         /* (can't see how could be NULL, but check just in case) */ 
154         if( text->compiled ){
155                 Py_DECREF( (PyObject *)text->compiled );
156         }
157
158         /* compile the buffer */
159         buf = txt_to_buf( text );
160         text->compiled = Py_CompileString( buf, text->id.name+2, Py_file_input );
161         MEM_freeN( buf );
162
163         /* if compile failed.... return this error */
164         if( PyErr_Occurred(  ) ) {
165                 PyErr_Print(  );
166                 PyErr_Clear(  );
167                 PySys_SetObject("last_traceback", NULL);
168                 free_compiled_text( text );
169                 return NULL;
170         }
171
172         /* make into a module */
173         return PyImport_ExecCodeModule( (char *)name, text->compiled );
174 }
175
176
177 static PyObject *blender_import( PyObject * self, PyObject * args,  PyObject * kw)
178 {
179         PyObject *exception, *err, *tb;
180         char *name;
181         int found= 0;
182         PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
183         PyObject *newmodule;
184         
185         //PyObject_Print(args, stderr, 0);
186         int dummy_val; /* what does this do?*/
187         static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0};
188         
189         if( !PyArg_ParseTupleAndKeywords( args, kw, "s|OOOi:bpy_import_meth", kwlist,
190                                &name, &globals, &locals, &fromlist, &dummy_val) )
191                 return NULL;
192
193         /* import existing builtin modules or modules that have been imported alredy */
194         newmodule = PyImport_ImportModuleEx( name, globals, locals, fromlist );
195         
196         if(newmodule)
197                 return newmodule;
198         
199         PyErr_Fetch( &exception, &err, &tb );   /* get the python error incase we cant import as blender text either */
200         
201         /* importing from existing modules failed, see if we have this module as blender text */
202         newmodule = bpy_text_import_name( name, &found );
203         
204         if( newmodule ) {/* found module as blender text, ignore above exception */
205                 PyErr_Clear(  );
206                 Py_XDECREF( exception );
207                 Py_XDECREF( err );
208                 Py_XDECREF( tb );
209                 /* printf( "imported from text buffer...\n" ); */
210         }
211         else if (found==1) { /* blender text module failed to execute but was found, use its error message */
212                 Py_XDECREF( exception );
213                 Py_XDECREF( err );
214                 Py_XDECREF( tb );
215                 return NULL;
216         }
217         else {
218                 /* no blender text was found that could import the module
219                  * rause the original error from PyImport_ImportModuleEx */
220                 PyErr_Restore( exception, err, tb );
221         }
222         return newmodule;
223 }
224
225
226 /*
227  * our reload() module, to handle reloading in-memory scripts
228  */
229
230 static PyObject *blender_reload( PyObject * self, PyObject * args )
231 {
232         PyObject *exception, *err, *tb;
233         PyObject *module = NULL;
234         PyObject *newmodule = NULL;
235         int found= 0;
236         
237         /* check for a module arg */
238         if( !PyArg_ParseTuple( args, "O:bpy_reload_meth", &module ) )
239                 return NULL;
240
241         /* try reimporting from file */
242         newmodule = PyImport_ReloadModule( module );
243         if( newmodule )
244                 return newmodule;
245
246         /* no file, try importing from memory */
247         PyErr_Fetch( &exception, &err, &tb );   /*restore for probable later use */
248
249         newmodule = bpy_text_reimport( module, &found );
250         if( newmodule ) {/* found module as blender text, ignore above exception */
251                 PyErr_Clear(  );
252                 Py_XDECREF( exception );
253                 Py_XDECREF( err );
254                 Py_XDECREF( tb );
255                 /* printf( "imported from text buffer...\n" ); */
256         }
257         else if (found==1) { /* blender text module failed to execute but was found, use its error message */
258                 Py_XDECREF( exception );
259                 Py_XDECREF( err );
260                 Py_XDECREF( tb );
261                 return NULL;
262         }
263         else {
264                 /* no blender text was found that could import the module
265                  * rause the original error from PyImport_ImportModuleEx */
266                 PyErr_Restore( exception, err, tb );
267         }
268
269         return newmodule;
270 }
271
272 PyMethodDef bpy_import_meth[] = { {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"} };
273 PyMethodDef bpy_reload_meth[] = { {"bpy_reload_meth", (PyCFunction)blender_reload, METH_VARARGS, "blenders reload"} };
274
275
276 /* Clear user modules.
277  * This is to clear any modules that could be defined from running scripts in blender.
278  * 
279  * Its also needed for the BGE Python api so imported scripts are not used between levels
280  * 
281  * This clears every modules that has a __file__ attribute (is not a builtin)
282  *
283  * Note that clearing external python modules is important for the BGE otherwise
284  * it wont reload scripts between loading different blend files or while making the game.
285  * - use 'clear_all' arg in this case.
286  *
287  * Since pythons bultins include a full path even for win32.
288  * even if we remove a python module a reimport will bring it back again.
289  */
290
291 #if 0 // not used anymore but may still come in handy later
292
293 #if defined(WIN32) || defined(WIN64)
294 #define SEPSTR "\\"
295 #else
296 #define SEPSTR "/"
297 #endif
298
299
300 void bpy_text_clear_modules(int clear_all)
301 {
302         PyObject *modules= PySys_GetObject("modules");
303         
304         char *fname;
305         char *file_extension;
306         
307         /* looping over the dict */
308         PyObject *key, *value;
309         int pos = 0;
310         
311         /* new list */
312         PyObject *list;
313
314         if (modules==NULL)
315                 return; /* should never happen but just incase */
316
317         list= PyList_New(0);
318
319         /* go over sys.modules and remove anything with a 
320          * sys.modukes[x].__file__ thats ends with a .py and has no path
321          */
322         while (PyDict_Next(modules, &pos, &key, &value)) {
323                 fname= PyModule_GetFilename(value);
324                 if(fname) {
325                         if (clear_all || ((strstr(fname, SEPSTR))==0)) { /* no path ? */
326                                 file_extension = strstr(fname, ".py");
327                                 if(file_extension && (*(file_extension + 3) == '\0' || *(file_extension + 4) == '\0')) { /* .py or pyc extension? */
328                                         /* now we can be fairly sure its a python import from the blendfile */
329                                         PyList_Append(list, key); /* free'd with the list */
330                                 }
331                         }
332                 }
333                 else {
334                         PyErr_Clear();
335                 }
336         }
337         
338         /* remove all our modules */
339         for(pos=0; pos < PyList_Size(list); pos++) {
340                 /* PyObject_Print(key, stderr, 0); */
341                 key= PyList_GET_ITEM(list, pos);
342                 PyDict_DelItem(modules, key);
343         }
344         
345         Py_DECREF(list); /* removes all references from append */
346 }
347 #endif