diff options
-rw-r--r-- | source/blender/python/BPY_extern_run.h | 121 | ||||
-rw-r--r-- | source/blender/python/generic/py_capi_utils.h | 8 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface_run.c | 8 |
3 files changed, 121 insertions, 16 deletions
diff --git a/source/blender/python/BPY_extern_run.h b/source/blender/python/BPY_extern_run.h index 8eb8674d058..30740d7fb60 100644 --- a/source/blender/python/BPY_extern_run.h +++ b/source/blender/python/BPY_extern_run.h @@ -16,6 +16,20 @@ /** \file * \ingroup python + * + * \subsection common_args Common Arguments + * + * - `C` the #bContext (never NULL). + * + * - `imports`: This is simply supported for convenience since imports can make constructing + * strings more cumbersome as otherwise small expressions become multi-line code-blocks. + * Optional (ignored when NULL), otherwise this is a NULL terminated array of module names. + * + Failure to import any modules prevents any further execution. + * + * - `err_info` #BPy_RunErrInfo is passed to some functions so errors can be forwarded to the UI. + * Option (when NULL errors are printed to the `stdout` and cleared). + * However this should be used in any case the error would be useful to show to the user. */ #pragma once @@ -26,33 +40,85 @@ extern "C" { #include "BLI_sys_types.h" +#include "BLI_compiler_attrs.h" + struct ReportList; struct Text; struct bContext; /* bpy_interface_run.c */ +/* -------------------------------------------------------------------- */ +/** \name Run File/Text as a Script + * + * \note #BPY_run_filepath and #BPY_run_filepath have almost identical behavior + * one operates on a file-path, the other on a blender text-block. + * \{ */ + /** - * Can run a file or text block. + * Execute `filepath` as a Python script. + * + * Wrapper for `PyRun_File` (similar to calling python with a script argument). + * Used for the `--python` command line argument. + * + * \param C: The context (never NULL). + * \param filepath: The file path to execute. + * \param reports: Failure to execute the script will report the exception here (may be NULL). + * \return true on success, otherwise false with an error reported to `reports`. + * + * \note Python scripts could consider `bpy.utils.execfile`, which has the advantage of returning + * the object as a module for data access & caching `pyc` file for faster re-execution. + */ +bool BPY_run_filepath(struct bContext *C, const char *filepath, struct ReportList *reports) + ATTR_NONNULL(1, 2); +/** + * Execute a Blender `text` block as a Python script. + * + * Wrapper for `Py_CompileStringObject` & `PyEval_EvalCode`. + * Used for the `--python-text` command line argument. + * + * \param C: The context (never NULL). + * \param text: The text-block to execute. + * \param reports: Failure to execute the script will report the exception here (may be NULL). + * \param do_jump: When true, any error moves the cursor to the location of that error. + * Useful for executing scripts interactively from the text editor. + * \return true on success, otherwise false with an error reported to `reports`. + * + * \note The `__file__` is constructed by joining the blend file-path to the name of the text. + * This is done so error messages give useful output however there are rare cases causes problems + * with introspection tools which attempt to load `__file__`. */ -bool BPY_run_filepath(struct bContext *C, const char *filepath, struct ReportList *reports); bool BPY_run_text(struct bContext *C, struct Text *text, struct ReportList *reports, - const bool do_jump); + const bool do_jump) ATTR_NONNULL(1, 2); -/* Use the 'eval' for simple single-line expressions, - * otherwise 'exec' for full multi-line scripts. */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Run a String as a Script + * + * - Use 'eval' for simple single-line expressions. + * - Use 'exec' for full multi-line scripts. + * \{ */ /** * Run an entire script, matches: `exec(compile(..., "exec"))` */ bool BPY_run_string_exec(struct bContext *C, const char *imports[], const char *expr); /** - * Run an expression, matches: `exec(compile(..., "eval"))` + * Run an expression, matches: `exec(compile(..., "eval"))`. */ bool BPY_run_string_eval(struct bContext *C, const char *imports[], const char *expr); +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Run a String as a Script & Return the Result + * + * Convenience functions for executing a script and returning the result as an expected type. + * \{ */ + /** * \note When this struct is passed in as NULL, * print errors to the `stdout` and clear. @@ -69,40 +135,63 @@ struct BPy_RunErrInfo { char **r_string; }; -/* Run, evaluating to fixed type result. */ - /** - * \return success + * Evaluate `expr` as a number (double). + * + * \param C: See \ref common_args. + * \param imports: See \ref common_args. + * \param expr: The expression to evaluate. + * \param err_info: See \ref common_args. + * \param r_value: The resulting value. + * \return Success. */ bool BPY_run_string_as_number(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, - double *r_value); + double *r_value) ATTR_NONNULL(1, 3, 5); /** - * Support both int and pointers. + * Evaluate `expr` as an integer or pointer. + * + * \note Support both int and pointers. * - * \return success + * \param C: See \ref common_args. + * \param imports: See \ref common_args. + * \param expr: The expression to evaluate. + * \param err_info: See \ref common_args. + * \param r_value: The resulting value. + * \return Success. */ bool BPY_run_string_as_intptr(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, - intptr_t *r_value); + intptr_t *r_value) ATTR_NONNULL(1, 3, 5); /** - * \return success + * Evaluate `expr` as a string. + * + * \param C: See \ref common_args. + * \param imports: See \ref common_args. + * \param expr: The expression to evaluate. + * \param err_info: See \ref common_args. + * \param r_value: The resulting value. + * \return Success. */ bool BPY_run_string_as_string_and_size(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, char **r_value, - size_t *r_value_size); + size_t *r_value_size) ATTR_NONNULL(1, 3, 5, 6); + +/** See #BPY_run_string_as_string_and_size */ bool BPY_run_string_as_string(struct bContext *C, const char *imports[], const char *expr, struct BPy_RunErrInfo *err_info, - char **r_value); + char **r_value) ATTR_NONNULL(1, 3, 5); + +/** \} */ #ifdef __cplusplus } /* extern "C" */ diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 09eade9c477..f6d8d7298af 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -138,6 +138,14 @@ const char *PyC_UnicodeAsByteAndSize(PyObject *py_str, Py_ssize_t *size, PyObjec */ PyObject *PyC_DefaultNameSpace(const char *filename); void PyC_RunQuicky(const char *filepath, int n, ...); +/** + * Import `imports` into `py_dict`. + * + * \param py_dict: A Python dictionary, typically used as a name-space for script execution. + * \param imports: A NULL terminated array of strings. + * \return true when all modules import without errors, otherwise return false. + * The caller is expected to handle the exception. + */ bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[]); /** diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c index e9e5e9634d6..a4d54a4ce83 100644 --- a/source/blender/python/intern/bpy_interface_run.c +++ b/source/blender/python/intern/bpy_interface_run.c @@ -80,6 +80,14 @@ typedef struct { } PyModuleObject; #endif +/** + * Execute a file-path or text-block. + * + * \param reports: Report exceptions as errors (may be NULL). + * \param do_jump: See #BPY_run_text. + * + * \note Share a function for this since setup/cleanup logic is the same. + */ static bool python_script_exec( bContext *C, const char *fn, struct Text *text, struct ReportList *reports, const bool do_jump) { |