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