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