diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/python/intern/bpy_interface_inoutwrapper.c | 24 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface_run.c | 79 |
2 files changed, 90 insertions, 13 deletions
diff --git a/source/blender/python/intern/bpy_interface_inoutwrapper.c b/source/blender/python/intern/bpy_interface_inoutwrapper.c index 3757e970948..910a0f65532 100644 --- a/source/blender/python/intern/bpy_interface_inoutwrapper.c +++ b/source/blender/python/intern/bpy_interface_inoutwrapper.c @@ -21,11 +21,9 @@ */ #include <Python.h> +#include <stdbool.h> -#include "MEM_guardedalloc.h" - -#include "BLI_string_utf8.h" -#include "BLI_utildefines.h" +#include <BLI_assert.h> #include "bpy_interface_inoutwrapper.h" @@ -36,21 +34,25 @@ PyObject *stderr_backup = NULL; PyObject *string_io_buf = NULL; PyObject *string_io_getvalue = NULL; -/* TODO (grzelins) move this whole implementation to bpy_capi_utils? */ bool BPY_intern_init_io_wrapper() { + BLI_assert(string_io_mod == NULL); + BLI_assert(string_io == NULL); + BLI_assert(stderr_backup == NULL); + BLI_assert(stdout_backup == NULL); + BLI_assert(string_io_buf == NULL); + BLI_assert(string_io_getvalue == NULL); PyImport_ImportModule("sys"); stdout_backup = PySys_GetObject("stdout"); /* borrowed */ stderr_backup = PySys_GetObject("stderr"); /* borrowed */ - BLI_assert(stderr_backup != NULL); if (!(string_io_mod = PyImport_ImportModule("io"))) { return false; } - else if (!(string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) { + if (!(string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) { return false; } - else if (!(string_io_getvalue = PyObject_GetAttrString(string_io, "getvalue"))) { + if (!(string_io_getvalue = PyObject_GetAttrString(string_io, "getvalue"))) { return false; } Py_INCREF(stdout_backup); // since these were borrowed we don't want them freed when replaced. @@ -75,13 +77,15 @@ PyObject *BPY_intern_get_io_buffer() void BPY_intern_free_io_twrapper() { - Py_DECREF(stdout_backup); // since these were borrowed we don't want them freed when replaced. + Py_DECREF(stdout_backup); Py_DECREF(stderr_backup); Py_DECREF(string_io_mod); Py_DECREF(string_io_getvalue); - Py_DECREF(string_io); /* free the original reference */ + Py_DECREF(string_io); stdout_backup = NULL; stderr_backup = NULL; string_io_buf = NULL; string_io_getvalue = NULL; + string_io_mod = NULL; + string_io = NULL; } diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c index a7593ae7d79..5b7bd18e97c 100644 --- a/source/blender/python/intern/bpy_interface_run.c +++ b/source/blender/python/intern/bpy_interface_run.c @@ -20,6 +20,8 @@ #include <stdio.h> +#include <BKE_report.h> +#include <CLG_log.h> #include <Python.h> #include "MEM_guardedalloc.h" @@ -43,6 +45,8 @@ #include "bpy_traceback.h" #include "../generic/py_capi_utils.h" +#include "bpy.h" +#include "bpy_interface_inoutwrapper.h" /* -------------------------------------------------------------------- */ /** \name Private Utilities @@ -96,10 +100,16 @@ static bool python_script_exec( PyC_MainModule_Backup(&main_mod); - if (text) { - char fn_dummy[FILE_MAXDIR]; - bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text); + bool wrapper_init_ok = BPY_intern_init_io_wrapper(); + if (!wrapper_init_ok) { + CLOG_WARN( + BPY_LOG_RNA, + "Setting python IO wrapper failed! Script output will not be visible in Info Editor"); + } + char fn_dummy[FILE_MAXDIR]; + bpy_text_filename_get(fn_dummy, bmain_old, sizeof(fn_dummy), text); + if (text) { if (text->compiled == NULL) { /* if it wasn't already compiled, do it now */ char *buf; PyObject *fn_dummy_py; @@ -167,6 +177,31 @@ static bool python_script_exec( } } + if (wrapper_init_ok) { + /* printing io buffer will fail if error is set */ + if (PyErr_Occurred()) { + PyObject *error_type, *error_value, *error_traceback; + PyErr_Fetch(&error_type, &error_value, &error_traceback); + PyErr_Clear(); + PyObject *pystring = BPY_intern_get_io_buffer(); + BKE_reportf(reports, + RPT_INFO, + "Python output from \"%s\":\n%s", + fn ? fn : fn_dummy, + _PyUnicode_AsString(pystring)); + PyErr_Restore(error_type, error_value, error_traceback); + } + else { + PyObject *pystring = BPY_intern_get_io_buffer(); + BKE_reportf(reports, + RPT_INFO, + "Python output from \"%s\":\n%s", + fn ? fn : fn_dummy, + _PyUnicode_AsString(pystring)); + } + BPY_intern_free_io_twrapper(); + } + if (!py_result) { if (text) { if (do_jump) { @@ -246,6 +281,13 @@ static bool bpy_run_string_impl(bContext *C, py_dict = PyC_DefaultNameSpace("<blender string>"); + bool wrapper_init_ok = BPY_intern_init_io_wrapper(); + if (!wrapper_init_ok) { + CLOG_WARN( + BPY_LOG_RNA, + "Setting python IO wrapper failed! Script output will not be visible in Info Editor"); + } + if (imports && (!PyC_NameSpace_ImportArray(py_dict, imports))) { Py_DECREF(py_dict); retval = NULL; @@ -254,6 +296,37 @@ static bool bpy_run_string_impl(bContext *C, retval = PyRun_String(expr, mode, py_dict, py_dict); } + if (wrapper_init_ok) { + /* printing io buffer will fail if error is set */ + if (PyErr_Occurred()) { + PyObject *error_type, *error_value, *error_traceback; + PyErr_Fetch(&error_type, &error_value, &error_traceback); + PyErr_Clear(); + PyObject *pystring = BPY_intern_get_io_buffer(); + if (pystring != NULL) { + BKE_reportf(CTX_wm_reports(C), + RPT_INFO, + "Python output from running: \"%s\":\n%s", + expr, + _PyUnicode_AsString(pystring)); + Py_DecRef(pystring); + } + PyErr_Restore(error_type, error_value, error_traceback); + } + else { + PyObject *pystring = BPY_intern_get_io_buffer(); + if (pystring != NULL) { + BKE_reportf(CTX_wm_reports(C), + RPT_INFO, + "Python output from running \"%s\":\n%s", + expr, + _PyUnicode_AsString(pystring)); + Py_DecRef(pystring); + } + } + BPY_intern_free_io_twrapper(); + } + if (retval == NULL) { ok = false; BPy_errors_to_report(CTX_wm_reports(C)); |