Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
- index b34a41b5af6..2164d3d2d71 100644
- --- a/source/blender/python/intern/bpy_interface.c
- +++ b/source/blender/python/intern/bpy_interface.c
- @@ -236,6 +236,305 @@ static struct _inittab bpy_internal_modules[] = {
- {NULL, NULL},
- };
- +static ListBase bpy_import_main_list;
- +
- +/* returns a dummy filename for a textblock so we can tell what file a text block comes from */
- +void bpy_text_filename_get(char *fn, size_t fn_len, Text *text)
- +{
- + BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(G_MAIN, &text->id), SEP, text->id.name + 2);
- +}
- +
- +static void free_compiled_text(Text *text)
- +{
- + if (text->compiled) {
- + Py_DECREF((PyObject *)text->compiled);
- + }
- + text->compiled = NULL;
- +}
- +
- +bool bpy_text_compile(Text *text)
- +{
- + char fn_dummy[FILE_MAX];
- + PyObject *fn_dummy_py;
- + char *buf;
- +
- + bpy_text_filename_get(fn_dummy, sizeof(fn_dummy), text);
- +
- + /* if previously compiled, free the object */
- + free_compiled_text(text);
- +
- + fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
- +
- + buf = txt_to_buf(text);
- + text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
- + MEM_freeN(buf);
- +
- + Py_DECREF(fn_dummy_py);
- +
- + if (PyErr_Occurred()) {
- + PyErr_Print();
- + PyErr_Clear();
- + PySys_SetObject("last_traceback", NULL);
- + free_compiled_text(text);
- + return false;
- + }
- + else {
- + return true;
- + }
- +}
- +
- +PyObject *bpy_text_import(Text *text)
- +{
- + char modulename[MAX_ID_NAME + 2];
- + int len;
- +
- + if (!text->compiled) {
- + if (bpy_text_compile(text) == false) {
- + return NULL;
- + }
- + }
- +
- + len = strlen(text->id.name + 2);
- + BLI_strncpy(modulename, text->id.name + 2, len);
- + modulename[len - 3] = '\0'; /* remove .py */
- + return PyImport_ExecCodeModule(modulename, text->compiled);
- +}
- +
- +PyObject *bpy_text_import_name(const char *name, int *found)
- +{
- + Text *text;
- + char txtname[MAX_ID_NAME - 2];
- + int namelen = strlen(name);
- +//XXX Main *maggie = bpy_import_main ? bpy_import_main : G_MAIN;
- + Main *maggie = G_MAIN;
- +
- + *found = 0;
- +
- + if (!maggie) {
- + printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
- + return NULL;
- + }
- +
- + /* we know this cant be importable, the name is too long for blender! */
- + if (namelen >= (MAX_ID_NAME - 2) - 3)
- + return NULL;
- +
- + memcpy(txtname, name, namelen);
- + memcpy(&txtname[namelen], ".py", 4);
- +
- + text = BLI_findstring(&maggie->texts, txtname, offsetof(ID, name) + 2);
- +
- + if (text) {
- + *found = 1;
- + return bpy_text_import(text);
- + }
- +
- + /* If we still haven't found the module try additional modules form bpy_import_main_list */
- + maggie = bpy_import_main_list.first;
- + while (maggie && !text) {
- + text = BLI_findstring(&maggie->texts, txtname, offsetof(ID, name) + 2);
- + maggie = maggie->next;
- + }
- +
- + if (!text)
- + return NULL;
- + else
- + *found = 1;
- +
- + return bpy_text_import(text);
- +}
- +
- +static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
- +{
- + PyObject *exception, *err, *tb;
- + const char *name;
- + int found = 0;
- + PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
- + int level = 0; /* relative imports */
- + PyObject *newmodule;
- +
- + static const char *_keywords[] = {"name", "globals", "locals", "fromlist", "level", NULL};
- + static _PyArg_Parser _parser = {"s|OOOi:bpy_import_meth", _keywords, 0};
- + if (!_PyArg_ParseTupleAndKeywordsFast(
- + args, kw, &_parser,
- + &name, &globals, &locals, &fromlist, &level))
- + {
- + return NULL;
- + }
- +
- + /* import existing builtin modules or modules that have been imported already */
- + newmodule = PyImport_ImportModuleLevel(name, globals, locals, fromlist, level);
- +
- + if (newmodule)
- + return newmodule;
- +
- + PyErr_Fetch(&exception, &err, &tb); /* get the python error in case we cant import as blender text either */
- +
- + /* importing from existing modules failed, see if we have this module as blender text */
- + newmodule = bpy_text_import_name(name, &found);
- +
- + if (newmodule) { /* found module as blender text, ignore above exception */
- + PyErr_Clear();
- + Py_XDECREF(exception);
- + Py_XDECREF(err);
- + Py_XDECREF(tb);
- + /* printf("imported from text buffer...\n"); */
- + }
- + else if (found == 1) { /* blender text module failed to execute but was found, use its error message */
- + Py_XDECREF(exception);
- + Py_XDECREF(err);
- + Py_XDECREF(tb);
- + return NULL;
- + }
- + else {
- + /* no blender text was found that could import the module
- + * reuse the original error from PyImport_ImportModuleEx */
- + PyErr_Restore(exception, err, tb);
- + }
- + return newmodule;
- +}
- +
- +
- +/*
- + * our reload() module, to handle reloading in-memory scripts
- + */
- +
- +static PyObject *imp_reload_orig = NULL;
- +
- +/*
- + * find in-memory module and recompile
- + */
- +
- +PyObject *bpy_text_reimport(PyObject *module, int *found)
- +{
- + Text *text;
- + const char *name;
- + const char *filepath;
- +//XXX Main *maggie = bpy_import_main ? bpy_import_main : G_MAIN;
- + Main *maggie = G_MAIN;
- +
- + if (!maggie) {
- + printf("ERROR: bpy_import_main_set() was not called before running python. this is a bug.\n");
- + return NULL;
- + }
- +
- + *found = 0;
- +
- + /* get name, filename from the module itself */
- + if ((name = PyModule_GetName(module)) == NULL)
- + return NULL;
- +
- + {
- + PyObject *module_file = PyModule_GetFilenameObject(module);
- + if (module_file == NULL) {
- + return NULL;
- + }
- + filepath = _PyUnicode_AsString(module_file);
- + Py_DECREF(module_file);
- + if (filepath == NULL) {
- + return NULL;
- + }
- + }
- +
- + /* look up the text object */
- + text = BLI_findstring(&maggie->texts, BLI_path_basename(filepath), offsetof(ID, name) + 2);
- +
- + /* uh-oh.... didn't find it */
- + if (!text)
- + return NULL;
- + else
- + *found = 1;
- +
- + if (bpy_text_compile(text) == false) {
- + return NULL;
- + }
- +
- + /* make into a module */
- + return PyImport_ExecCodeModule(name, text->compiled);
- +}
- +
- +static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module)
- +{
- + PyObject *exception, *err, *tb;
- + PyObject *newmodule = NULL;
- + int found = 0;
- +
- + /* try reimporting from file */
- +
- + /* in Py3.3 this just calls imp.reload() which we overwrite, causing recursive calls */
- + //newmodule = PyImport_ReloadModule(module);
- +
- + newmodule = PyObject_CallFunctionObjArgs(imp_reload_orig, module, NULL);
- +
- + if (newmodule)
- + return newmodule;
- +
- + /* no file, try importing from memory */
- + PyErr_Fetch(&exception, &err, &tb); /*restore for probable later use */
- +
- + newmodule = bpy_text_reimport(module, &found);
- + if (newmodule) { /* found module as blender text, ignore above exception */
- + PyErr_Clear();
- + Py_XDECREF(exception);
- + Py_XDECREF(err);
- + Py_XDECREF(tb);
- + /* printf("imported from text buffer...\n"); */
- + }
- + else if (found == 1) { /* blender text module failed to execute but was found, use its error message */
- + Py_XDECREF(exception);
- + Py_XDECREF(err);
- + Py_XDECREF(tb);
- + return NULL;
- + }
- + else {
- + /* no blender text was found that could import the module
- + * reuse the original error from PyImport_ImportModuleEx */
- + PyErr_Restore(exception, err, tb);
- + }
- +
- + return newmodule;
- +}
- +
- +static PyMethodDef bpy_import_meth = {"bpy_import_meth", (PyCFunction)blender_import, METH_VARARGS | METH_KEYWORDS, "blenders import"};
- +static PyMethodDef bpy_reload_meth = {"bpy_reload_meth", (PyCFunction)blender_reload, METH_O, "blenders reload"};
- +
- +/**
- + * \note to the discerning developer, yes - this is nasty
- + * monkey-patching our own import into Python's builtin 'imp' module.
- + *
- + * However Python's alternative is to use import hooks,
- + * which are implemented in a way that we can't use our own importer as a
- + * fall-back (instead we must try and fail - raise an exception every time).
- + * Since importing from blenders text-blocks is not the common case
- + * I prefer to use Pythons import by default and fall-back to
- + * Blenders - which we can only do by intercepting import calls I'm afraid.
- + * - Campbell
- + */
- +void bpy_import_init(PyObject *builtins)
- +{
- + PyObject *item;
- + PyObject *mod;
- +
- + PyDict_SetItemString(builtins, "__import__", item = PyCFunction_New(&bpy_import_meth, NULL)); Py_DECREF(item);
- +
- + /* move reload here
- + * XXX, use import hooks */
- + mod = PyImport_ImportModuleLevel("importlib", NULL, NULL, NULL, 0);
- + if (mod) {
- + PyObject *mod_dict = PyModule_GetDict(mod);
- +
- + /* blender owns the function */
- + imp_reload_orig = PyDict_GetItemString(mod_dict, "reload");
- + Py_INCREF(imp_reload_orig);
- +
- + PyDict_SetItemString(mod_dict, "reload", item = PyCFunction_New(&bpy_reload_meth, NULL)); Py_DECREF(item);
- + Py_DECREF(mod);
- + }
- + else {
- + BLI_assert(!"unable to load 'importlib' module.");
- + }
- +}
- +
- /* call BPY_context_set first */
- void BPY_python_start(int argc, const char **argv)
- {
- @@ -327,6 +626,8 @@ void BPY_python_start(int argc, const char **argv)
- /* bpy.* and lets us import it */
- BPy_init_modules();
- + bpy_import_init(PyEval_GetBuiltins());
- +
- pyrna_alloc_types();
- #ifndef WITH_PYTHON_MODULE
- @@ -423,12 +724,6 @@ typedef struct {
- } PyModuleObject;
- #endif
- -/* returns a dummy filename for a textblock so we can tell what file a text block comes from */
- -static void bpy_text_filename_get(char *fn, const Main *bmain, size_t fn_len, const Text *text)
- -{
- - BLI_snprintf(fn, fn_len, "%s%c%s", ID_BLEND_PATH(bmain, &text->id), SEP, text->id.name + 2);
- -}
- -
- static bool python_script_exec(
- bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump)
- {
- @@ -449,7 +744,7 @@ static bool python_script_exec(
- if (text) {
- char fn_dummy[FILE_MAXDIR];
- - bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text);
- + bpy_text_filename_get(fn_dummy, /*bmain_old,*/ sizeof(fn_dummy), text);
- if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */
- char *buf;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement