Correct some types, ensure multi-line docs end with a newline, sentences end with a full stop.
147 lines
4.1 KiB
C++
147 lines
4.1 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup pythonintern
|
|
*
|
|
* This file extends `bpy.types.Operator` with C/Python API methods and attributes.
|
|
*/
|
|
|
|
#include <Python.h>
|
|
|
|
#include "BLI_string.h"
|
|
|
|
#include "BKE_context.hh"
|
|
|
|
#include "BPY_extern.hh"
|
|
#include "bpy_capi_utils.hh"
|
|
|
|
#include "bpy_rna_operator.hh" /* Own include, #BPY_rna_operator_poll_message_set_method_def. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Operator `poll_message_set` Method
|
|
* \{ */
|
|
|
|
static char *pyop_poll_message_get_fn(bContext * /*C*/, void *user_data)
|
|
{
|
|
PyGILState_STATE gilstate = PyGILState_Ensure();
|
|
|
|
PyObject *py_args = static_cast<PyObject *>(user_data);
|
|
PyObject *py_func_or_msg = PyTuple_GET_ITEM(py_args, 0);
|
|
|
|
char *msg = nullptr;
|
|
|
|
if (PyUnicode_Check(py_func_or_msg)) {
|
|
Py_ssize_t msg_len;
|
|
const char *msg_src = PyUnicode_AsUTF8AndSize(py_func_or_msg, &msg_len);
|
|
msg = BLI_strdupn(msg_src, msg_len);
|
|
}
|
|
else {
|
|
PyObject *py_args_after_first = PyTuple_GetSlice(py_args, 1, PY_SSIZE_T_MAX);
|
|
PyObject *py_msg = PyObject_CallObject(py_func_or_msg, py_args_after_first);
|
|
Py_DECREF(py_args_after_first);
|
|
|
|
bool error = false;
|
|
|
|
/* Null for no string. */
|
|
if (py_msg == nullptr) {
|
|
error = true;
|
|
}
|
|
else {
|
|
if (py_msg == Py_None) {
|
|
/* Pass. */
|
|
}
|
|
else if (PyUnicode_Check(py_msg)) {
|
|
Py_ssize_t msg_src_len;
|
|
const char *msg_src = PyUnicode_AsUTF8AndSize(py_msg, &msg_src_len);
|
|
msg = BLI_strdupn(msg_src, msg_src_len);
|
|
}
|
|
else {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"poll_message_set(function, ...): expected string or None, got %.200s",
|
|
Py_TYPE(py_msg)->tp_name);
|
|
error = true;
|
|
}
|
|
Py_DECREF(py_msg);
|
|
}
|
|
|
|
if (error) {
|
|
PyErr_Print();
|
|
}
|
|
}
|
|
|
|
PyGILState_Release(gilstate);
|
|
return msg;
|
|
}
|
|
|
|
static void pyop_poll_message_free_fn(bContext * /*C*/, void *user_data)
|
|
{
|
|
/* Handles the GIL. */
|
|
BPY_DECREF(user_data);
|
|
}
|
|
|
|
PyDoc_STRVAR(
|
|
/* Wrap. */
|
|
BPY_rna_operator_poll_message_set_doc,
|
|
".. classmethod:: poll_message_set(message, *args)\n"
|
|
"\n"
|
|
" Set the message to show in the tool-tip when poll fails.\n"
|
|
"\n"
|
|
" When message is callable, "
|
|
"additional user defined positional arguments are passed to the message function.\n"
|
|
"\n"
|
|
" :arg message: The message or a function that returns the message.\n"
|
|
" :type message: str | Callable[..., str | None]\n"
|
|
" :arg args: A sequence of arguments to pass to ``message``, if it's a callable, "
|
|
"otherwise argument is not available.\n"
|
|
" :type args: Any\n");
|
|
static PyObject *BPY_rna_operator_poll_message_set(PyObject * /*self*/, PyObject *args)
|
|
{
|
|
const Py_ssize_t args_len = PyTuple_GET_SIZE(args);
|
|
if (args_len == 0) {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"poll_message_set(message, ...): requires a message argument");
|
|
return nullptr;
|
|
}
|
|
|
|
PyObject *py_func_or_msg = PyTuple_GET_ITEM(args, 0);
|
|
|
|
if (PyUnicode_Check(py_func_or_msg)) {
|
|
if (args_len > 1) {
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"poll_message_set(message): does not support additional arguments");
|
|
return nullptr;
|
|
}
|
|
}
|
|
else if (PyCallable_Check(py_func_or_msg)) {
|
|
/* pass */
|
|
}
|
|
else {
|
|
PyErr_Format(PyExc_TypeError,
|
|
"poll_message_set(message, ...): "
|
|
"expected at least 1 string or callable argument, got %.200s",
|
|
Py_TYPE(py_func_or_msg)->tp_name);
|
|
return nullptr;
|
|
}
|
|
|
|
bContext *C = BPY_context_get();
|
|
bContextPollMsgDyn_Params params{};
|
|
params.get_fn = pyop_poll_message_get_fn;
|
|
params.free_fn = pyop_poll_message_free_fn;
|
|
params.user_data = Py_NewRef(args);
|
|
|
|
CTX_wm_operator_poll_msg_set_dynamic(C, ¶ms);
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyMethodDef BPY_rna_operator_poll_message_set_method_def = {
|
|
"poll_message_set",
|
|
(PyCFunction)BPY_rna_operator_poll_message_set,
|
|
METH_VARARGS | METH_STATIC,
|
|
BPY_rna_operator_poll_message_set_doc,
|
|
};
|
|
|
|
/** \} */
|