Blender V4.3
bpy_rna_operator.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <Python.h>
12
13#include "BLI_string.h"
14
15#include "BKE_context.hh"
16
18
19#include "BPY_extern.hh"
20#include "bpy_capi_utils.hh"
21
22#include "bpy_rna_operator.hh" /* Own include, #BPY_rna_operator_poll_message_set_method_def. */
23
24/* -------------------------------------------------------------------- */
28static char *pyop_poll_message_get_fn(bContext * /*C*/, void *user_data)
29{
30 PyGILState_STATE gilstate = PyGILState_Ensure();
31
32 PyObject *py_args = static_cast<PyObject *>(user_data);
33 PyObject *py_func_or_msg = PyTuple_GET_ITEM(py_args, 0);
34
35 char *msg = nullptr;
36
37 if (PyUnicode_Check(py_func_or_msg)) {
38 Py_ssize_t msg_len;
39 const char *msg_src = PyUnicode_AsUTF8AndSize(py_func_or_msg, &msg_len);
40 msg = BLI_strdupn(msg_src, msg_len);
41 }
42 else {
43 PyObject *py_args_after_first = PyTuple_GetSlice(py_args, 1, PY_SSIZE_T_MAX);
44 PyObject *py_msg = PyObject_CallObject(py_func_or_msg, py_args_after_first);
45 Py_DECREF(py_args_after_first);
46
47 bool error = false;
48
49 /* Null for no string. */
50 if (py_msg == nullptr) {
51 error = true;
52 }
53 else {
54 if (py_msg == Py_None) {
55 /* Pass. */
56 }
57 else if (PyUnicode_Check(py_msg)) {
58 Py_ssize_t msg_src_len;
59 const char *msg_src = PyUnicode_AsUTF8AndSize(py_msg, &msg_src_len);
60 msg = BLI_strdupn(msg_src, msg_src_len);
61 }
62 else {
63 PyErr_Format(PyExc_TypeError,
64 "poll_message_set(function, ...): expected string or None, got %.200s",
65 Py_TYPE(py_msg)->tp_name);
66 error = true;
67 }
68 Py_DECREF(py_msg);
69 }
70
71 if (error) {
72 PyErr_Print();
73 PyErr_Clear();
74 }
75 }
76
77 PyGILState_Release(gilstate);
78 return msg;
79}
80
81static void pyop_poll_message_free_fn(bContext * /*C*/, void *user_data)
82{
83 /* Handles the GIL. */
84 BPY_DECREF(user_data);
85}
86
88 /* Wrap. */
89 BPY_rna_operator_poll_message_set_doc,
90 ".. classmethod:: poll_message_set(message, *args)\n"
91 "\n"
92 " Set the message to show in the tool-tip when poll fails.\n"
93 "\n"
94 " When message is callable, "
95 "additional user defined positional arguments are passed to the message function.\n"
96 "\n"
97 " :arg message: The message or a function that returns the message.\n"
98 " :type message: str | Callable[[Any, ...], str | None]\n");
99
100static PyObject *BPY_rna_operator_poll_message_set(PyObject * /*self*/, PyObject *args)
101{
102 const Py_ssize_t args_len = PyTuple_GET_SIZE(args);
103 if (args_len == 0) {
104 PyErr_SetString(PyExc_ValueError,
105 "poll_message_set(message, ...): requires a message argument");
106 return nullptr;
107 }
108
109 PyObject *py_func_or_msg = PyTuple_GET_ITEM(args, 0);
110
111 if (PyUnicode_Check(py_func_or_msg)) {
112 if (args_len > 1) {
113 PyErr_SetString(PyExc_ValueError,
114 "poll_message_set(message): does not support additional arguments");
115 return nullptr;
116 }
117 }
118 else if (PyCallable_Check(py_func_or_msg)) {
119 /* pass */
120 }
121 else {
122 PyErr_Format(PyExc_TypeError,
123 "poll_message_set(message, ...): "
124 "expected at least 1 string or callable argument, got %.200s",
125 Py_TYPE(py_func_or_msg)->tp_name);
126 return nullptr;
127 }
128
133 params.user_data = Py_NewRef(args);
134
136
137 Py_RETURN_NONE;
138}
139
141 "poll_message_set",
143 METH_VARARGS | METH_STATIC,
144 BPY_rna_operator_poll_message_set_doc,
145};
146
void CTX_wm_operator_poll_msg_set_dynamic(bContext *C, const bContextPollMsgDyn_Params *params)
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.c:29
void BPY_DECREF(void *pyob_ptr)
struct bContext * BPY_context_get(void)
static char * pyop_poll_message_get_fn(bContext *, void *user_data)
static PyObject * BPY_rna_operator_poll_message_set(PyObject *, PyObject *args)
static void pyop_poll_message_free_fn(bContext *, void *user_data)
PyDoc_STRVAR(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[[Any, ...], str | None]\n")
PyMethodDef BPY_rna_operator_poll_message_set_method_def
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
static void error(const char *str)
header-only utilities