PyAPI: support evaluating an expression as a string or None
Utility functions will be used as part of !120283.
This commit is contained in:
@@ -183,6 +183,31 @@ bool BPY_run_string_as_string(struct bContext *C,
|
||||
struct BPy_RunErrInfo *err_info,
|
||||
char **r_value) ATTR_NONNULL(1, 3, 5);
|
||||
|
||||
/**
|
||||
* Evaluate `expr` as a string or None.
|
||||
* Where a success return value with `*r_value == nullptr` indicates a value of None.
|
||||
*
|
||||
* \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_len_or_none(struct bContext *C,
|
||||
const char *imports[],
|
||||
const char *expr,
|
||||
struct BPy_RunErrInfo *err_info,
|
||||
char **r_value,
|
||||
size_t *r_value_len) ATTR_NONNULL(1, 3, 5, 6);
|
||||
|
||||
/** See #BPY_run_string_as_string_and_len */
|
||||
bool BPY_run_string_as_string_or_none(struct bContext *C,
|
||||
const char *imports[],
|
||||
const char *expr,
|
||||
struct BPy_RunErrInfo *err_info,
|
||||
char **r_value) ATTR_NONNULL(1, 3, 5);
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1624,6 +1624,64 @@ bool PyC_RunString_AsString(const char *imports[],
|
||||
return PyC_RunString_AsStringAndSize(imports, expr, filename, r_value, &value_size);
|
||||
}
|
||||
|
||||
bool PyC_RunString_AsStringAndSizeOrNone(const char *imports[],
|
||||
const char *expr,
|
||||
const char *filename,
|
||||
char **r_value,
|
||||
size_t *r_value_size)
|
||||
{
|
||||
PyObject *py_dict, *retval;
|
||||
bool ok = true;
|
||||
PyObject *main_mod = nullptr;
|
||||
|
||||
PyC_MainModule_Backup(&main_mod);
|
||||
|
||||
py_dict = PyC_DefaultNameSpace(filename);
|
||||
|
||||
if (imports && !PyC_NameSpace_ImportArray(py_dict, imports)) {
|
||||
ok = false;
|
||||
}
|
||||
else if ((retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict)) == nullptr) {
|
||||
ok = false;
|
||||
}
|
||||
else {
|
||||
if (retval == Py_None) {
|
||||
*r_value = nullptr;
|
||||
*r_value_size = 0;
|
||||
}
|
||||
else {
|
||||
const char *val;
|
||||
Py_ssize_t val_len;
|
||||
|
||||
val = PyUnicode_AsUTF8AndSize(retval, &val_len);
|
||||
if (val == nullptr && PyErr_Occurred()) {
|
||||
ok = false;
|
||||
}
|
||||
else {
|
||||
char *val_alloc = static_cast<char *>(MEM_mallocN(val_len + 1, __func__));
|
||||
memcpy(val_alloc, val, val_len + 1);
|
||||
*r_value = val_alloc;
|
||||
*r_value_size = val_len;
|
||||
}
|
||||
}
|
||||
|
||||
Py_DECREF(retval);
|
||||
}
|
||||
|
||||
PyC_MainModule_Restore(main_mod);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool PyC_RunString_AsStringOrNone(const char *imports[],
|
||||
const char *expr,
|
||||
const char *filename,
|
||||
char **r_value)
|
||||
{
|
||||
size_t value_size;
|
||||
return PyC_RunString_AsStringAndSizeOrNone(imports, expr, filename, r_value, &value_size);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
#endif /* #ifndef MATH_STANDALONE */
|
||||
|
||||
@@ -241,6 +241,19 @@ bool PyC_RunString_AsString(const char **imports,
|
||||
const char *filename,
|
||||
char **r_value);
|
||||
|
||||
/**
|
||||
* \param r_value_size: The length of the string assigned: `strlen(*r_value)`.
|
||||
*/
|
||||
bool PyC_RunString_AsStringAndSizeOrNone(const char **imports,
|
||||
const char *expr,
|
||||
const char *filename,
|
||||
char **r_value,
|
||||
size_t *r_value_size);
|
||||
bool PyC_RunString_AsStringOrNone(const char **imports,
|
||||
const char *expr,
|
||||
const char *filename,
|
||||
char **r_value);
|
||||
|
||||
/**
|
||||
* Use with PyArg_ParseTuple's "O&" formatting.
|
||||
*
|
||||
|
||||
@@ -445,6 +445,43 @@ bool BPY_run_string_as_string(
|
||||
return BPY_run_string_as_string_and_len(C, imports, expr, err_info, r_value, &value_dummy_len);
|
||||
}
|
||||
|
||||
bool BPY_run_string_as_string_and_len_or_none(bContext *C,
|
||||
const char *imports[],
|
||||
const char *expr,
|
||||
BPy_RunErrInfo *err_info,
|
||||
char **r_value,
|
||||
size_t *r_value_len)
|
||||
{
|
||||
PyGILState_STATE gilstate;
|
||||
bool ok = true;
|
||||
|
||||
if (expr[0] == '\0') {
|
||||
*r_value = nullptr;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bpy_context_set(C, &gilstate);
|
||||
|
||||
ok = PyC_RunString_AsStringAndSizeOrNone(
|
||||
imports, expr, "<expr as str or none>", r_value, r_value_len);
|
||||
|
||||
if (ok == false) {
|
||||
run_string_handle_error(err_info);
|
||||
}
|
||||
|
||||
bpy_context_clear(C, &gilstate);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool BPY_run_string_as_string_or_none(
|
||||
bContext *C, const char *imports[], const char *expr, BPy_RunErrInfo *err_info, char **r_value)
|
||||
{
|
||||
size_t value_dummy_len;
|
||||
return BPY_run_string_as_string_and_len_or_none(
|
||||
C, imports, expr, err_info, r_value, &value_dummy_len);
|
||||
}
|
||||
|
||||
bool BPY_run_string_as_intptr(bContext *C,
|
||||
const char *imports[],
|
||||
const char *expr,
|
||||
|
||||
Reference in New Issue
Block a user