macro formatting & remve some unused code.
[blender.git] / source / blender / python / generic / bpy_internal_import.c
1 /* 
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * This is a new part of Blender.
19  *
20  * Contributor(s): Willian P. Germano,
21  *                 Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/python/generic/bpy_internal_import.c
27  *  \ingroup pygen
28  */
29
30
31 #include <Python.h>
32 #include <stddef.h>
33
34 #include "bpy_internal_import.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_text_types.h"
39
40 #include "BLI_listbase.h"
41 #include "BLI_path_util.h"
42 #include "BLI_string.h"
43 #include "BLI_utildefines.h"
44
45  /* UNUSED */   
46 #include "BKE_text.h" /* txt_to_buf */  
47 #include "BKE_main.h"
48
49 static Main *bpy_import_main= NULL;
50
51 /* 'builtins' is most likely PyEval_GetBuiltins() */
52 void bpy_import_init(PyObject *builtins)
53 {
54         PyObject *item;
55         PyObject *mod;
56
57         PyDict_SetItemString(builtins, "__import__",    item=PyCFunction_New(&bpy_import_meth, NULL));  Py_DECREF(item);
58
59         /* move reload here
60          * XXX, use import hooks */
61         mod= PyImport_ImportModuleLevel((char *)"imp", NULL, NULL, NULL, 0);
62         if (mod) {
63                 PyDict_SetItemString(PyModule_GetDict(mod), "reload", item=PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item);
64                 Py_DECREF(mod);
65         }
66         else {
67                 BLI_assert(!"unable to load 'imp' module.");
68         }
69 }
70
71
72 static void free_compiled_text(Text *text)
73 {
74         if (text->compiled) {
75                 Py_DECREF((PyObject *)text->compiled);
76         }
77         text->compiled= NULL;
78 }
79
80 struct Main *bpy_import_main_get(void)
81 {
82         return bpy_import_main;
83 }
84
85 void bpy_import_main_set(struct Main *maggie)
86 {
87         bpy_import_main= maggie;
88 }
89
90 /* returns a dummy filename for a textblock so we can tell what file a text block comes from */
91 void bpy_text_filename_get(char *fn, size_t fn_len, Text *text)
92 {
93         BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bpy_import_main, &text->id), SEP, text->id.name+2);
94 }
95
96 PyObject *bpy_text_import(Text *text)
97 {
98         char *buf= NULL;
99         char modulename[24];
100         int len;
101
102         if (!text->compiled) {
103                 char fn_dummy[256];
104                 bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text);
105
106                 buf= txt_to_buf(text);
107                 text->compiled= Py_CompileString(buf, fn_dummy, Py_file_input);
108                 MEM_freeN(buf);
109
110                 if (PyErr_Occurred()) {
111                         PyErr_Print();
112                         PyErr_Clear();
113                         PySys_SetObject("last_traceback", NULL);
114                         free_compiled_text(text);
115                         return NULL;
116                 }
117         }
118
119         len= strlen(text->id.name+2);
120         BLI_strncpy(modulename, text->id.name+2, len);
121         modulename[len - 3]= '\0'; /* remove .py */
122         return PyImport_ExecCodeModule(modulename, text->compiled);
123 }
124
125 PyObject *bpy_text_import_name(const char *name, int *found)
126 {
127         Text *text;
128         char txtname[MAX_ID_NAME-2];
129         int namelen= strlen(name);
130 //XXX   Main *maggie= bpy_import_main ? bpy_import_main:G.main;
131         Main *maggie= bpy_import_main;
132         
133         *found= 0;
134
135         if (!maggie) {
136                 printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
137                 return NULL;
138         }
139         
140         if (namelen >= (MAX_ID_NAME-2) - 3) return NULL; /* we know this cant be importable, the name is too long for blender! */
141         
142         memcpy(txtname, name, namelen);
143         memcpy(&txtname[namelen], ".py", 4);
144
145         text= BLI_findstring(&maggie->text, txtname, offsetof(ID, name) + 2);
146
147         if (!text)
148                 return NULL;
149         else
150                 *found= 1;
151         
152         return bpy_text_import(text);
153 }
154
155
156 /*
157  * find in-memory module and recompile
158  */
159
160 PyObject *bpy_text_reimport(PyObject *module, int *found)
161 {
162         Text *text;
163         const char *name;
164         char *filepath;
165         char *buf= NULL;
166 //XXX   Main *maggie= bpy_import_main ? bpy_import_main:G.main;
167         Main *maggie= bpy_import_main;
168         
169         if (!maggie) {
170                 printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
171                 return NULL;
172         }
173         
174         *found= 0;
175         
176         /* get name, filename from the module itself */
177         if ((name= PyModule_GetName(module)) == NULL)
178                 return NULL;
179
180         if ((filepath= (char *)PyModule_GetFilename(module)) == NULL)
181                 return NULL;
182
183         /* look up the text object */
184         text= BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2);
185
186         /* uh-oh.... didn't find it */
187         if (!text)
188                 return NULL;
189         else
190                 *found= 1;
191
192         /* if previously compiled, free the object */
193         /* (can't see how could be NULL, but check just in case) */ 
194         if (text->compiled) {
195                 Py_DECREF((PyObject *)text->compiled);
196         }
197
198         /* compile the buffer */
199         buf= txt_to_buf(text);
200         text->compiled= Py_CompileString(buf, text->id.name+2, Py_file_input);
201         MEM_freeN(buf);
202
203         /* if compile failed.... return this error */
204         if (PyErr_Occurred()) {
205                 PyErr_Print();
206                 PyErr_Clear();
207                 PySys_SetObject("last_traceback", NULL);
208                 free_compiled_text(text);
209                 return NULL;
210         }
211
212         /* make into a module */
213         return PyImport_ExecCodeModule((char *)name, text->compiled);
214 }
215
216
217 static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
218 {
219         PyObject *exception, *err, *tb;
220         char *name;
221         int found= 0;
222         PyObject *globals= NULL, *locals= NULL, *fromlist= NULL;
223         int level= -1; /* relative imports */
224         
225         PyObject *newmodule;
226         //PyObject_Print(args, stderr, 0);
227         static const char *kwlist[]= {"name", "globals", "locals", "fromlist", "level", NULL};
228         
229         if (!PyArg_ParseTupleAndKeywords(args, kw, "s|OOOi:bpy_import_meth", (char **)kwlist,
230                                    &name, &globals, &locals, &fromlist, &level))
231                 return NULL;
232
233         /* import existing builtin modules or modules that have been imported already */
234         newmodule= PyImport_ImportModuleLevel(name, globals, locals, fromlist, level);
235         
236         if (newmodule)
237                 return newmodule;
238         
239         PyErr_Fetch(&exception, &err, &tb);     /* get the python error incase we cant import as blender text either */
240         
241         /* importing from existing modules failed, see if we have this module as blender text */
242         newmodule= bpy_text_import_name(name, &found);
243         
244         if (newmodule) {/* found module as blender text, ignore above exception */
245                 PyErr_Clear();
246                 Py_XDECREF(exception);
247                 Py_XDECREF(err);
248                 Py_XDECREF(tb);
249                 /* printf("imported from text buffer...\n"); */
250         }
251         else if (found==1) { /* blender text module failed to execute but was found, use its error message */
252                 Py_XDECREF(exception);
253                 Py_XDECREF(err);
254                 Py_XDECREF(tb);
255                 return NULL;
256         }
257         else {
258                 /* no blender text was found that could import the module
259                  * rause the original error from PyImport_ImportModuleEx */
260                 PyErr_Restore(exception, err, tb);
261         }
262         return newmodule;
263 }
264
265
266 /*
267  * our reload() module, to handle reloading in-memory scripts
268  */
269
270 static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module)
271 {
272         PyObject *exception, *err, *tb;
273         PyObject *newmodule= NULL;
274         int found= 0;
275
276         /* try reimporting from file */
277         newmodule= PyImport_ReloadModule(module);
278         if (newmodule)
279                 return newmodule;
280
281         /* no file, try importing from memory */
282         PyErr_Fetch(&exception, &err, &tb);     /*restore for probable later use */
283
284         newmodule= bpy_text_reimport(module, &found);
285         if (newmodule) {/* found module as blender text, ignore above exception */
286                 PyErr_Clear();
287                 Py_XDECREF(exception);
288                 Py_XDECREF(err);
289                 Py_XDECREF(tb);
290                 /* printf("imported from text buffer...\n"); */
291         }
292         else if (found==1) { /* blender text module failed to execute but was found, use its error message */
293                 Py_XDECREF(exception);
294                 Py_XDECREF(err);
295                 Py_XDECREF(tb);
296                 return NULL;
297         }
298         else {
299                 /* no blender text was found that could import the module
300                  * reuse the original error from PyImport_ImportModuleEx */
301                 PyErr_Restore(exception, err, tb);
302         }
303
304         return newmodule;
305 }
306
307 PyMethodDef bpy_import_meth= {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"};
308 PyMethodDef bpy_reload_meth= {"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"};