diff options
Diffstat (limited to 'source/blender/python/intern/bpy_interface.c')
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 146 |
1 files changed, 137 insertions, 9 deletions
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 4ae1b41bb89..60ada6e983b 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -35,6 +35,7 @@ #include "bpy.h" #include "bpy_rna.h" #include "bpy_util.h" +#include "bpy_traceback.h" #include "DNA_space_types.h" #include "DNA_text_types.h" @@ -157,6 +158,7 @@ void BPY_modules_update(bContext *C) } /* must be called before Py_Initialize */ +#ifndef WITH_PYTHON_MODULE static void bpy_python_start_path(void) { char *py_path_bundle= BLI_get_folder(BLENDER_PYTHON, NULL); @@ -195,8 +197,7 @@ static void bpy_python_start_path(void) // printf("found python (wchar_t) '%ls'\n", py_path_bundle_wchar); } } - - +#endif void BPY_context_set(bContext *C) { @@ -219,8 +220,9 @@ static struct _inittab bpy_internal_modules[]= { /* call BPY_context_set first */ void BPY_python_start(int argc, const char **argv) { +#ifndef WITH_PYTHON_MODULE PyThreadState *py_tstate = NULL; - + /* not essential but nice to set our name */ static wchar_t bprogname_wchar[FILE_MAXDIR+FILE_MAXFILE]; /* python holds a reference */ utf8towchar(bprogname_wchar, bprogname); @@ -252,8 +254,13 @@ void BPY_python_start(int argc, const char **argv) /* Initialize thread support (also acquires lock) */ PyEval_InitThreads(); +#else + (void)argc; + (void)argv; - + PyImport_ExtendInittab(bpy_internal_modules); +#endif + /* bpy.* and lets us import it */ BPy_init_modules(); @@ -281,8 +288,10 @@ void BPY_python_start(int argc, const char **argv) pyrna_alloc_types(); +#ifndef WITH_PYTHON_MODULE py_tstate = PyGILState_GetThisThreadState(); PyEval_ReleaseThread(py_tstate); +#endif } void BPY_python_end(void) @@ -319,6 +328,18 @@ void BPY_python_end(void) } +static void python_script_error_jump_text(struct Text *text) +{ + int lineno; + int offset; + python_script_error_jump(text->id.name+2, &lineno, &offset); + if(lineno != -1) { + /* select the line with the error */ + txt_move_to(text, lineno - 1, INT_MAX, FALSE); + txt_move_to(text, lineno - 1, offset, TRUE); + } +} + /* super annoying, undo _PyModule_Clear(), bug [#23871] */ #define PYMODULE_CLEAR_WORKAROUND @@ -332,7 +353,7 @@ typedef struct { } PyModuleObject; #endif -static int python_script_exec(bContext *C, const char *fn, struct Text *text, struct ReportList *reports) +static int python_script_exec(bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const short do_jump) { PyObject *main_mod= NULL; PyObject *py_dict= NULL, *py_result= NULL; @@ -361,6 +382,9 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, st MEM_freeN( buf ); if(PyErr_Occurred()) { + if(do_jump) { + python_script_error_jump_text(text); + } BPY_text_free_code(text); } } @@ -406,6 +430,11 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, st } if (!py_result) { + if(text) { + if(do_jump) { + python_script_error_jump_text(text); + } + } BPy_errors_to_report(reports); } else { Py_DECREF( py_result ); @@ -434,13 +463,13 @@ static int python_script_exec(bContext *C, const char *fn, struct Text *text, st /* Can run a file or text block */ int BPY_filepath_exec(bContext *C, const char *filepath, struct ReportList *reports) { - return python_script_exec(C, filepath, NULL, reports); + return python_script_exec(C, filepath, NULL, reports, FALSE); } -int BPY_text_exec(bContext *C, struct Text *text, struct ReportList *reports) +int BPY_text_exec(bContext *C, struct Text *text, struct ReportList *reports, const short do_jump) { - return python_script_exec(C, NULL, text, reports); + return python_script_exec(C, NULL, text, reports, do_jump); } void BPY_DECREF(void *pyob_ptr) @@ -659,3 +688,102 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * return done; } + +#ifdef WITH_PYTHON_MODULE +#include "BLI_storage.h" +/* TODO, reloading the module isnt functional at the moment. */ + +extern int main_python(int argc, const char **argv); +static struct PyModuleDef bpy_proxy_def = { + PyModuleDef_HEAD_INIT, + "bpy", /* m_name */ + NULL, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +typedef struct { + PyObject_HEAD + /* Type-specific fields go here. */ + PyObject *mod; +} dealloc_obj; + +/* call once __file__ is set */ +void bpy_module_delay_init(PyObject *bpy_proxy) +{ + const int argc= 1; + const char *argv[2]; + + const char *filename_rel= PyModule_GetFilename(bpy_proxy); /* can be relative */ + char filename_abs[1024]; + + BLI_strncpy(filename_abs, filename_rel, sizeof(filename_abs)); + BLI_path_cwd(filename_abs); + + argv[0]= filename_abs; + argv[1]= NULL; + + // printf("module found %s\n", argv[0]); + + main_python(argc, argv); + + /* initialized in BPy_init_modules() */ + PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py)); +} + +static void dealloc_obj_dealloc(PyObject *self); + +static PyTypeObject dealloc_obj_Type = {{{0}}}; + +/* use our own dealloc so we can free a property if we use one */ +static void dealloc_obj_dealloc(PyObject *self) +{ + bpy_module_delay_init(((dealloc_obj *)self)->mod); + + /* Note, for subclassed PyObjects we cant just call PyObject_DEL() directly or it will crash */ + dealloc_obj_Type.tp_free(self); +} + +PyMODINIT_FUNC +PyInit_bpy(void) +{ + PyObject *bpy_proxy= PyModule_Create(&bpy_proxy_def); + + /* Problem: + * 1) this init function is expected to have a private member defined - 'md_def' + * but this is only set for C defined modules (not py packages) + * so we cant return 'bpy_package_py' as is. + * + * 2) there is a 'bpy' C module for python to load which is basically all of blender, + * and there is scripts/bpy/__init__.py, + * we may end up having to rename this module so there is no naming conflict here eg: + * 'from blender import bpy' + * + * 3) we dont know the filename at this point, workaround by assigning a dummy value + * which calls back when its freed so the real loading can take place. + */ + + /* assign an object which is freed after __file__ is assigned */ + dealloc_obj *dob; + + /* assign dummy type */ + dealloc_obj_Type.tp_name = "dealloc_obj"; + dealloc_obj_Type.tp_basicsize = sizeof(dealloc_obj); + dealloc_obj_Type.tp_dealloc = dealloc_obj_dealloc; + dealloc_obj_Type.tp_flags = Py_TPFLAGS_DEFAULT; + + if(PyType_Ready(&dealloc_obj_Type) < 0) + return NULL; + + dob= (dealloc_obj *) dealloc_obj_Type.tp_alloc(&dealloc_obj_Type, 0); + dob->mod= bpy_proxy; /* borrow */ + PyModule_AddObject(bpy_proxy, "__file__", (PyObject *)dob); /* borrow */ + + return bpy_proxy; +} + +#endif |