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