Blender V2.61 - r43446

bpy_internal_import.c

Go to the documentation of this file.
00001 /* 
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * This is a new part of Blender.
00019  *
00020  * Contributor(s): Willian P. Germano, Campbell Barton
00021  *
00022  * ***** END GPL LICENSE BLOCK *****
00023  */
00024 
00036 #include <Python.h>
00037 #include <stddef.h>
00038 
00039 #include "bpy_internal_import.h"
00040 
00041 #include "MEM_guardedalloc.h"
00042 
00043 #include "DNA_text_types.h"
00044 
00045 #include "BLI_listbase.h"
00046 #include "BLI_path_util.h"
00047 #include "BLI_string.h"
00048 #include "BLI_utildefines.h"
00049 
00050  /* UNUSED */   
00051 #include "BKE_text.h" /* txt_to_buf */  
00052 #include "BKE_main.h"
00053 
00054 static Main *bpy_import_main = NULL;
00055 
00056 /* 'builtins' is most likely PyEval_GetBuiltins() */
00057 void bpy_import_init(PyObject *builtins)
00058 {
00059     PyObject *item;
00060     PyObject *mod;
00061 
00062     PyDict_SetItemString(builtins, "__import__", item = PyCFunction_New(&bpy_import_meth, NULL)); Py_DECREF(item);
00063 
00064     /* move reload here
00065      * XXX, use import hooks */
00066     mod = PyImport_ImportModuleLevel((char *)"imp", NULL, NULL, NULL, 0);
00067     if (mod) {
00068         PyDict_SetItemString(PyModule_GetDict(mod), "reload", item = PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item);
00069         Py_DECREF(mod);
00070     }
00071     else {
00072         BLI_assert(!"unable to load 'imp' module.");
00073     }
00074 }
00075 
00076 
00077 static void free_compiled_text(Text *text)
00078 {
00079     if (text->compiled) {
00080         Py_DECREF((PyObject *)text->compiled);
00081     }
00082     text->compiled = NULL;
00083 }
00084 
00085 struct Main *bpy_import_main_get(void)
00086 {
00087     return bpy_import_main;
00088 }
00089 
00090 void bpy_import_main_set(struct Main *maggie)
00091 {
00092     bpy_import_main = maggie;
00093 }
00094 
00095 /* returns a dummy filename for a textblock so we can tell what file a text block comes from */
00096 void bpy_text_filename_get(char *fn, size_t fn_len, Text *text)
00097 {
00098     BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bpy_import_main, &text->id), SEP, text->id.name + 2);
00099 }
00100 
00101 PyObject *bpy_text_import(Text *text)
00102 {
00103     char *buf = NULL;
00104     char modulename[MAX_ID_NAME+2];
00105     int len;
00106 
00107     if (!text->compiled) {
00108         char fn_dummy[256];
00109         bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text);
00110 
00111         buf = txt_to_buf(text);
00112         text->compiled = Py_CompileString(buf, fn_dummy, Py_file_input);
00113         MEM_freeN(buf);
00114 
00115         if (PyErr_Occurred()) {
00116             PyErr_Print();
00117             PyErr_Clear();
00118             PySys_SetObject("last_traceback", NULL);
00119             free_compiled_text(text);
00120             return NULL;
00121         }
00122     }
00123 
00124     len = strlen(text->id.name + 2);
00125     BLI_strncpy(modulename, text->id.name + 2, len);
00126     modulename[len - 3] = '\0'; /* remove .py */
00127     return PyImport_ExecCodeModule(modulename, text->compiled);
00128 }
00129 
00130 PyObject *bpy_text_import_name(const char *name, int *found)
00131 {
00132     Text *text;
00133     char txtname[MAX_ID_NAME - 2];
00134     int namelen = strlen(name);
00135 //XXX   Main *maggie = bpy_import_main ? bpy_import_main:G.main;
00136     Main *maggie = bpy_import_main;
00137     
00138     *found = 0;
00139 
00140     if (!maggie) {
00141         printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
00142         return NULL;
00143     }
00144 
00145     /* we know this cant be importable, the name is too long for blender! */
00146     if (namelen >= (MAX_ID_NAME - 2) - 3) return NULL;
00147 
00148     memcpy(txtname, name, namelen);
00149     memcpy(&txtname[namelen], ".py", 4);
00150 
00151     text = BLI_findstring(&maggie->text, txtname, offsetof(ID, name) + 2);
00152 
00153     if (!text)
00154         return NULL;
00155     else
00156         *found = 1;
00157     
00158     return bpy_text_import(text);
00159 }
00160 
00161 
00162 /*
00163  * find in-memory module and recompile
00164  */
00165 
00166 PyObject *bpy_text_reimport(PyObject *module, int *found)
00167 {
00168     Text *text;
00169     const char *name;
00170     char *filepath;
00171     char *buf = NULL;
00172 //XXX   Main *maggie = bpy_import_main ? bpy_import_main:G.main;
00173     Main *maggie = bpy_import_main;
00174     
00175     if (!maggie) {
00176         printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
00177         return NULL;
00178     }
00179     
00180     *found = 0;
00181     
00182     /* get name, filename from the module itself */
00183     if ((name = PyModule_GetName(module)) == NULL)
00184         return NULL;
00185 
00186     if ((filepath = (char *)PyModule_GetFilename(module)) == NULL)
00187         return NULL;
00188 
00189     /* look up the text object */
00190     text = BLI_findstring(&maggie->text, BLI_path_basename(filepath), offsetof(ID, name) + 2);
00191 
00192     /* uh-oh.... didn't find it */
00193     if (!text)
00194         return NULL;
00195     else
00196         *found = 1;
00197 
00198     /* if previously compiled, free the object */
00199     /* (can't see how could be NULL, but check just in case) */ 
00200     if (text->compiled) {
00201         Py_DECREF((PyObject *)text->compiled);
00202     }
00203 
00204     /* compile the buffer */
00205     buf = txt_to_buf(text);
00206     text->compiled = Py_CompileString(buf, text->id.name + 2, Py_file_input);
00207     MEM_freeN(buf);
00208 
00209     /* if compile failed.... return this error */
00210     if (PyErr_Occurred()) {
00211         PyErr_Print();
00212         PyErr_Clear();
00213         PySys_SetObject("last_traceback", NULL);
00214         free_compiled_text(text);
00215         return NULL;
00216     }
00217 
00218     /* make into a module */
00219     return PyImport_ExecCodeModule((char *)name, text->compiled);
00220 }
00221 
00222 
00223 static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
00224 {
00225     PyObject *exception, *err, *tb;
00226     char *name;
00227     int found = 0;
00228     PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
00229     int level = -1; /* relative imports */
00230     
00231     PyObject *newmodule;
00232     //PyObject_Print(args, stderr, 0);
00233     static const char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", NULL};
00234     
00235     if (!PyArg_ParseTupleAndKeywords(args, kw, "s|OOOi:bpy_import_meth", (char **)kwlist,
00236                                      &name, &globals, &locals, &fromlist, &level))
00237     {
00238         return NULL;
00239     }
00240 
00241     /* import existing builtin modules or modules that have been imported already */
00242     newmodule = PyImport_ImportModuleLevel(name, globals, locals, fromlist, level);
00243     
00244     if (newmodule)
00245         return newmodule;
00246     
00247     PyErr_Fetch(&exception, &err, &tb); /* get the python error incase we cant import as blender text either */
00248     
00249     /* importing from existing modules failed, see if we have this module as blender text */
00250     newmodule = bpy_text_import_name(name, &found);
00251     
00252     if (newmodule) {/* found module as blender text, ignore above exception */
00253         PyErr_Clear();
00254         Py_XDECREF(exception);
00255         Py_XDECREF(err);
00256         Py_XDECREF(tb);
00257         /* printf("imported from text buffer...\n"); */
00258     }
00259     else if (found == 1) { /* blender text module failed to execute but was found, use its error message */
00260         Py_XDECREF(exception);
00261         Py_XDECREF(err);
00262         Py_XDECREF(tb);
00263         return NULL;
00264     }
00265     else {
00266         /* no blender text was found that could import the module
00267          * rause the original error from PyImport_ImportModuleEx */
00268         PyErr_Restore(exception, err, tb);
00269     }
00270     return newmodule;
00271 }
00272 
00273 
00274 /*
00275  * our reload() module, to handle reloading in-memory scripts
00276  */
00277 
00278 static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module)
00279 {
00280     PyObject *exception, *err, *tb;
00281     PyObject *newmodule = NULL;
00282     int found = 0;
00283 
00284     /* try reimporting from file */
00285     newmodule = PyImport_ReloadModule(module);
00286     if (newmodule)
00287         return newmodule;
00288 
00289     /* no file, try importing from memory */
00290     PyErr_Fetch(&exception, &err, &tb); /*restore for probable later use */
00291 
00292     newmodule = bpy_text_reimport(module, &found);
00293     if (newmodule) {/* found module as blender text, ignore above exception */
00294         PyErr_Clear();
00295         Py_XDECREF(exception);
00296         Py_XDECREF(err);
00297         Py_XDECREF(tb);
00298         /* printf("imported from text buffer...\n"); */
00299     }
00300     else if (found == 1) { /* blender text module failed to execute but was found, use its error message */
00301         Py_XDECREF(exception);
00302         Py_XDECREF(err);
00303         Py_XDECREF(tb);
00304         return NULL;
00305     }
00306     else {
00307         /* no blender text was found that could import the module
00308          * reuse the original error from PyImport_ImportModuleEx */
00309         PyErr_Restore(exception, err, tb);
00310     }
00311 
00312     return newmodule;
00313 }
00314 
00315 PyMethodDef bpy_import_meth = {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"};
00316 PyMethodDef bpy_reload_meth = {"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"};