Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python/intern/bpy_interface.c')
-rw-r--r--source/blender/python/intern/bpy_interface.c146
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