PyAPI: support evaluating an expression as a string or None

Utility functions will be used as part of !120283.
This commit is contained in:
Campbell Barton
2024-04-18 10:35:51 +10:00
parent 4666af64a6
commit c0e4de8457
4 changed files with 133 additions and 0 deletions

View File

@@ -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

View File

@@ -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 */

View File

@@ -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.
*

View File

@@ -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,