diff options
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/BPY_extern.h | 8 | ||||
-rw-r--r-- | source/blender/python/generic/py_capi_utils.c | 42 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_api.c | 4 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_api.h | 6 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_batch.c | 7 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_capi_utils.c | 39 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_capi_utils.h | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_driver.c | 19 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 52 |
9 files changed, 101 insertions, 78 deletions
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 5c6e0b0a308..049b919b4a4 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -82,23 +82,23 @@ bool BPY_execute_text(struct bContext *C, bool BPY_execute_string_as_number(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, double *r_value); bool BPY_execute_string_as_intptr(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, intptr_t *r_value); bool BPY_execute_string_as_string_and_size(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, char **r_value, size_t *r_value_size); bool BPY_execute_string_as_string(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, char **r_value); bool BPY_execute_string_ex(struct bContext *C, diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 9c84a4bb824..406dbdafe22 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -634,7 +634,7 @@ error_cleanup: PyObject *PyC_ExceptionBuffer_Simple(void) { - PyObject *string_io_buf; + PyObject *string_io_buf = NULL; PyObject *error_type, *error_value, *error_traceback; @@ -648,7 +648,19 @@ PyObject *PyC_ExceptionBuffer_Simple(void) return NULL; } - string_io_buf = PyObject_Str(error_value); + if (PyErr_GivenExceptionMatches(error_type, PyExc_SyntaxError)) { + /* Special exception for syntax errors, + * in these cases the full error is verbose and not very useful, + * just use the initial text so we know what the error is. */ + if (PyTuple_CheckExact(error_value) && PyTuple_GET_SIZE(error_value) >= 1) { + string_io_buf = PyObject_Str(PyTuple_GET_ITEM(error_value, 0)); + } + } + + if (string_io_buf == NULL) { + string_io_buf = PyObject_Str(error_value); + } + /* Python does this too */ if (UNLIKELY(string_io_buf == NULL)) { string_io_buf = PyUnicode_FromFormat("<unprintable %s object>", Py_TYPE(error_value)->tp_name); @@ -804,8 +816,12 @@ void PyC_MainModule_Restore(PyObject *main_mod) Py_XDECREF(main_mod); } -/* Must be called before Py_Initialize, - * expects output of BKE_appdir_folder_id(BLENDER_PYTHON, NULL). */ +/** + * - Must be called before #Py_Initialize. + * - Expects output of `BKE_appdir_folder_id(BLENDER_PYTHON, NULL)`. + * - Note that the `PYTHONPATH` environment variable isn't reliable, see T31506. + Use #Py_SetPythonHome instead. + */ void PyC_SetHomePath(const char *py_path_bundle) { if (py_path_bundle == NULL) { @@ -824,24 +840,14 @@ void PyC_SetHomePath(const char *py_path_bundle) /* OSX allow file/directory names to contain : character (represented as / in the Finder) * but current Python lib (release 3.1.1) doesn't handle these correctly */ if (strchr(py_path_bundle, ':')) { - printf( - "Warning : Blender application is located in a path containing : or / chars\ - \nThis may make python import function fail\n"); - } -# endif - -# if 0 /* disable for now [#31506] - campbell */ -# ifdef _WIN32 - /* cmake/MSVC debug build crashes without this, why only - * in this case is unknown.. */ - { - /*BLI_setenv("PYTHONPATH", py_path_bundle)*/; + fprintf(stderr, + "Warning! Blender application is located in a path containing ':' or '/' chars\n" + "This may make python import function fail\n"); } -# endif # endif { - static wchar_t py_path_bundle_wchar[1024]; + wchar_t py_path_bundle_wchar[1024]; /* Can't use this, on linux gives bug: #23018, * TODO: try LANG="en_US.UTF-8" /usr/bin/blender, suggested 2008 */ diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c index 1379c0e557a..da7674eb7f9 100644 --- a/source/blender/python/gpu/gpu_py_api.c +++ b/source/blender/python/gpu/gpu_py_api.c @@ -43,9 +43,9 @@ /** \name Utils to invalidate functions * \{ */ -bool bpygpu_is_initialized_or_error(void) +bool bpygpu_is_init_or_error(void) { - if (!GPU_is_initialized()) { + if (!GPU_is_init()) { PyErr_SetString(PyExc_SystemError, "GPU functions for drawing are not available in background mode"); diff --git a/source/blender/python/gpu/gpu_py_api.h b/source/blender/python/gpu/gpu_py_api.h index e278bb63a49..916b1ac6e49 100644 --- a/source/blender/python/gpu/gpu_py_api.h +++ b/source/blender/python/gpu/gpu_py_api.h @@ -25,14 +25,14 @@ int bpygpu_ParsePrimType(PyObject *o, void *p); PyObject *BPyInit_gpu(void); -bool bpygpu_is_initialized_or_error(void); +bool bpygpu_is_init_or_error(void); #define BPYGPU_IS_INIT_OR_ERROR_OBJ \ - if (UNLIKELY(!bpygpu_is_initialized_or_error())) { \ + if (UNLIKELY(!bpygpu_is_init_or_error())) { \ return NULL; \ } \ ((void)0) #define BPYGPU_IS_INIT_OR_ERROR_INT \ - if (UNLIKELY(!bpygpu_is_initialized_or_error())) { \ + if (UNLIKELY(!bpygpu_is_init_or_error())) { \ return -1; \ } \ ((void)0) diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c index b3df991cf12..f9fe1654db0 100644 --- a/source/blender/python/gpu/gpu_py_batch.c +++ b/source/blender/python/gpu/gpu_py_batch.c @@ -184,8 +184,7 @@ static PyObject *bpygpu_Batch_program_set(BPyGPUBatch *self, BPyGPUShader *py_sh } GPUShader *shader = py_shader->shader; - GPU_batch_program_set( - self->batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader)); + GPU_batch_set_shader(self->batch, shader); #ifdef USE_GPU_PY_REFERENCES /* Remove existing user (if any), hold new user. */ @@ -229,9 +228,7 @@ static PyObject *bpygpu_Batch_draw(BPyGPUBatch *self, PyObject *args) } } else if (self->batch->program != GPU_shader_get_program(py_program->shader)) { - GPU_batch_program_set(self->batch, - GPU_shader_get_program(py_program->shader), - GPU_shader_get_interface(py_program->shader)); + GPU_batch_set_shader(self->batch, py_program->shader); } GPU_batch_draw(self->batch); diff --git a/source/blender/python/intern/bpy_capi_utils.c b/source/blender/python/intern/bpy_capi_utils.c index 89ef2f40a30..27eea80f1f6 100644 --- a/source/blender/python/intern/bpy_capi_utils.c +++ b/source/blender/python/intern/bpy_capi_utils.c @@ -97,7 +97,10 @@ void BPy_reports_write_stdout(const ReportList *reports, const char *header) } } -bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location) +bool BPy_errors_to_report_ex(ReportList *reports, + const char *error_prefix, + const bool use_full, + const bool use_location) { PyObject *pystring; @@ -124,40 +127,38 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo return 0; } + if (error_prefix == NULL) { + /* Not very helpful, better than nothing. */ + error_prefix = "Python"; + } + if (use_location) { const char *filename; int lineno; - PyObject *pystring_format; /* workaround, see below */ - const char *cstring; - PyC_FileAndNum(&filename, &lineno); if (filename == NULL) { filename = "<unknown location>"; } -#if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */ BKE_reportf(reports, RPT_ERROR, - "%s\nlocation: %s:%d\n", + TIP_("%s: %s\nlocation: %s:%d\n"), + error_prefix, _PyUnicode_AsString(pystring), filename, lineno); -#else - pystring_format = PyUnicode_FromFormat( - TIP_("%s\nlocation: %s:%d\n"), _PyUnicode_AsString(pystring), filename, lineno); - - cstring = _PyUnicode_AsString(pystring_format); - BKE_report(reports, RPT_ERROR, cstring); - - /* not exactly needed. just for testing */ - fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); - Py_DECREF(pystring_format); /* workaround */ -#endif + /* Not exactly needed. Useful for developers tracking down issues. */ + fprintf(stderr, + TIP_("%s: %s\nlocation: %s:%d\n"), + error_prefix, + _PyUnicode_AsString(pystring), + filename, + lineno); } else { - BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring)); + BKE_reportf(reports, RPT_ERROR, "%s: %s", error_prefix, _PyUnicode_AsString(pystring)); } Py_DECREF(pystring); @@ -166,5 +167,5 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo bool BPy_errors_to_report(ReportList *reports) { - return BPy_errors_to_report_ex(reports, true, true); + return BPy_errors_to_report_ex(reports, NULL, true, true); } diff --git a/source/blender/python/intern/bpy_capi_utils.h b/source/blender/python/intern/bpy_capi_utils.h index 46206f134ba..11409397028 100644 --- a/source/blender/python/intern/bpy_capi_utils.h +++ b/source/blender/python/intern/bpy_capi_utils.h @@ -43,8 +43,10 @@ char *BPy_enum_as_string(const struct EnumPropertyItem *item); short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear); void BPy_reports_write_stdout(const struct ReportList *reports, const char *header); bool BPy_errors_to_report_ex(struct ReportList *reports, + const char *error_prefix, const bool use_full, const bool use_location); +bool BPy_errors_to_report_brief_with_prefix(struct ReportList *reports, const char *error_prefix); bool BPy_errors_to_report(struct ReportList *reports); /* TODO - find a better solution! */ diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 5e2162c9e2d..d48ad2b197c 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -411,8 +411,10 @@ static PyObject *bpy_pydriver_depsgraph_as_pyobject(struct Depsgraph *depsgraph) return pyrna_struct_CreatePyObject(&depsgraph_ptr); } -/* Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated - * datablocks, and the current view layer and scene. See T75553. */ +/** + * Adds a variable 'depsgraph' to the driver variables. This can then be used to obtain evaluated + * data-blocks, and the current view layer and scene. See T75553. + */ static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars, struct Depsgraph *depsgraph) { @@ -428,17 +430,18 @@ static void bpy_pydriver_namespace_add_depsgraph(PyObject *driver_vars, } } -/* This evals py driver expressions, 'expr' is a Python expression that - * should evaluate to a float number, which is returned. +/** + * This evaluates Python driver expressions, `driver_orig->expression` + * is a Python expression that should evaluate to a float number, which is returned. * * (old)note: PyGILState_Ensure() isn't always called because python can call * the bake operator which intern starts a thread which calls scene update - * which does a driver update. to avoid a deadlock check PyC_IsInterpreterActive() - * if PyGILState_Ensure() is needed - see [#27683] + * which does a driver update. to avoid a deadlock check #PyC_IsInterpreterActive() + * if #PyGILState_Ensure() is needed, see T27683. * - * (new)note: checking if python is running is not threadsafe [#28114] + * (new)note: checking if python is running is not thread-safe T28114 * now release the GIL on python operator execution instead, using - * PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender. + * #PyEval_SaveThread() / #PyEval_RestoreThread() so we don't lock up blender. * * For copy-on-write we always cache expressions and write errors in the * original driver, otherwise these would get freed while editing. Due to diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index a880d2cd285..585119a0eae 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -258,11 +258,13 @@ void BPY_python_start(int argc, const char **argv) PyThreadState *py_tstate = NULL; const char *py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL); - /* not essential but nice to set our name */ - static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */ - BLI_strncpy_wchar_from_utf8( - program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar)); - Py_SetProgramName(program_path_wchar); + /* Not essential but nice to set our name. */ + { + const char *program_path = BKE_appdir_program_path(); + wchar_t program_path_wchar[FILE_MAX]; + BLI_strncpy_wchar_from_utf8(program_path_wchar, program_path, ARRAY_SIZE(program_path_wchar)); + Py_SetProgramName(program_path_wchar); + } /* must run before python initializes */ PyImport_ExtendInittab(bpy_internal_modules); @@ -615,8 +617,11 @@ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr) /** * \return success */ -bool BPY_execute_string_as_number( - bContext *C, const char *imports[], const char *expr, const bool verbose, double *r_value) +bool BPY_execute_string_as_number(bContext *C, + const char *imports[], + const char *expr, + const char *report_prefix, + double *r_value) { PyGILState_STATE gilstate; bool ok = true; @@ -635,8 +640,8 @@ bool BPY_execute_string_as_number( ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value); if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + if (report_prefix != NULL) { + BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false); } else { PyErr_Clear(); @@ -654,7 +659,7 @@ bool BPY_execute_string_as_number( bool BPY_execute_string_as_string_and_size(bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, char **r_value, size_t *r_value_size) { @@ -672,8 +677,8 @@ bool BPY_execute_string_as_string_and_size(bContext *C, ok = PyC_RunString_AsStringAndSize(imports, expr, "<expr as str>", r_value, r_value_size); if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + if (report_prefix != NULL) { + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false, report_prefix); } else { PyErr_Clear(); @@ -685,12 +690,15 @@ bool BPY_execute_string_as_string_and_size(bContext *C, return ok; } -bool BPY_execute_string_as_string( - bContext *C, const char *imports[], const char *expr, const bool verbose, char **r_value) +bool BPY_execute_string_as_string(bContext *C, + const char *imports[], + const char *expr, + const char *report_prefix, + char **r_value) { size_t value_dummy_size; return BPY_execute_string_as_string_and_size( - C, imports, expr, verbose, r_value, &value_dummy_size); + C, imports, expr, report_prefix, r_value, &value_dummy_size); } /** @@ -698,8 +706,11 @@ bool BPY_execute_string_as_string( * * \return success */ -bool BPY_execute_string_as_intptr( - bContext *C, const char *imports[], const char *expr, const bool verbose, intptr_t *r_value) +bool BPY_execute_string_as_intptr(bContext *C, + const char *imports[], + const char *expr, + const char *report_prefix, + intptr_t *r_value) { BLI_assert(r_value && expr); PyGILState_STATE gilstate; @@ -715,8 +726,8 @@ bool BPY_execute_string_as_intptr( ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value); if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + if (report_prefix != NULL) { + BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false); } else { PyErr_Clear(); @@ -910,8 +921,11 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * /* TODO, reloading the module isn't functional at the moment. */ static void bpy_module_free(void *mod); + +/* Defined in 'creator.c' when building as a Python module. */ extern int main_python_enter(int argc, const char **argv); extern void main_python_exit(void); + static struct PyModuleDef bpy_proxy_def = { PyModuleDef_HEAD_INIT, "bpy", /* m_name */ |