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