Blender  V2.93
bpy_operator.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
28 #include <Python.h>
29 
30 #include "RNA_types.h"
31 
32 #include "BLI_listbase.h"
33 #include "BLI_utildefines.h"
34 
35 #include "../generic/py_capi_utils.h"
36 #include "../generic/python_utildefines.h"
37 #include "BPY_extern.h"
38 #include "bpy_capi_utils.h"
39 #include "bpy_operator.h"
40 #include "bpy_operator_wrap.h"
41 #include "bpy_rna.h" /* for setting argument properties & type method `get_rna_type`. */
42 
43 #include "RNA_access.h"
44 #include "RNA_enum_types.h"
45 
46 #include "WM_api.h"
47 #include "WM_types.h"
48 
49 #include "MEM_guardedalloc.h"
50 
51 #include "BLI_ghash.h"
52 
53 #include "BKE_context.h"
54 #include "BKE_report.h"
55 
56 /* so operators called can spawn threads which acquire the GIL */
57 #define BPY_RELEASE_GIL
58 
59 static wmOperatorType *ot_lookup_from_py_string(PyObject *value, const char *py_fn_id)
60 {
61  const char *opname = PyUnicode_AsUTF8(value);
62  if (opname == NULL) {
63  PyErr_Format(PyExc_TypeError, "%s() expects a string argument", py_fn_id);
64  return NULL;
65  }
66 
67  wmOperatorType *ot = WM_operatortype_find(opname, true);
68  if (ot == NULL) {
69  PyErr_Format(PyExc_KeyError, "%s(\"%s\") not found", py_fn_id, opname);
70  return NULL;
71  }
72  return ot;
73 }
74 
75 static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
76 {
78  const char *opname;
79  PyObject *context_dict = NULL; /* optional args */
80  const char *context_str = NULL;
81  PyObject *ret;
82 
84 
85  /* XXX Todo, work out a better solution for passing on context,
86  * could make a tuple from self and pack the name and Context into it... */
88 
89  if (C == NULL) {
90  PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
91  return NULL;
92  }
93 
94  if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str)) {
95  return NULL;
96  }
97 
98  ot = WM_operatortype_find(opname, true);
99 
100  if (ot == NULL) {
101  PyErr_Format(PyExc_AttributeError,
102  "Polling operator \"bpy.ops.%s\" error, "
103  "could not be found",
104  opname);
105  return NULL;
106  }
107 
108  if (context_str) {
111  PyErr_Format(PyExc_TypeError,
112  "Calling operator \"bpy.ops.%s.poll\" error, "
113  "expected a string enum in (%s)",
114  opname,
115  enum_str);
116  MEM_freeN(enum_str);
117  return NULL;
118  }
119  }
120 
121  if (ELEM(context_dict, NULL, Py_None)) {
122  context_dict = NULL;
123  }
124  else if (!PyDict_Check(context_dict)) {
125  PyErr_Format(PyExc_TypeError,
126  "Calling operator \"bpy.ops.%s.poll\" error, "
127  "custom context expected a dict or None, got a %.200s",
128  opname,
129  Py_TYPE(context_dict)->tp_name);
130  return NULL;
131  }
132 
133  struct bContext_PyState context_py_state;
134  if (context_dict != NULL) {
135  CTX_py_state_push(C, &context_py_state, (void *)context_dict);
136  Py_INCREF(context_dict); /* so we don't lose it */
137  }
138 
139  /* main purpose of this function */
140  ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False;
141 
142  if (context_dict != NULL) {
143  PyObject *context_dict_test = CTX_py_dict_get(C);
144  if (context_dict_test != context_dict) {
145  Py_DECREF(context_dict_test);
146  }
147  /* Restore with original context dict,
148  * probably NULL but need this for nested operator calls. */
149  Py_DECREF(context_dict);
150  CTX_py_state_pop(C, &context_py_state);
151  }
152 
153  return Py_INCREF_RET(ret);
154 }
155 
156 static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
157 {
159  int error_val = 0;
160  PointerRNA ptr;
161  int operator_ret = OPERATOR_CANCELLED;
162 
163  const char *opname;
164  const char *context_str = NULL;
165  PyObject *kw = NULL; /* optional args */
166  PyObject *context_dict = NULL; /* optional args */
167 
168  /* note that context is an int, python does the conversion in this case */
170  int is_undo = false;
171 
172  /* XXX Todo, work out a better solution for passing on context,
173  * could make a tuple from self and pack the name and Context into it... */
175 
176  if (C == NULL) {
177  PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
178  return NULL;
179  }
180 
181  if (!PyArg_ParseTuple(args,
182  "sO|O!si:_bpy.ops.call",
183  &opname,
184  &context_dict,
185  &PyDict_Type,
186  &kw,
187  &context_str,
188  &is_undo)) {
189  return NULL;
190  }
191 
192  ot = WM_operatortype_find(opname, true);
193 
194  if (ot == NULL) {
195  PyErr_Format(PyExc_AttributeError,
196  "Calling operator \"bpy.ops.%s\" error, "
197  "could not be found",
198  opname);
199  return NULL;
200  }
201 
202  if (!pyrna_write_check()) {
203  PyErr_Format(PyExc_RuntimeError,
204  "Calling operator \"bpy.ops.%s\" error, "
205  "can't modify blend data in this state (drawing/rendering)",
206  opname);
207  return NULL;
208  }
209 
210  if (context_str) {
213  PyErr_Format(PyExc_TypeError,
214  "Calling operator \"bpy.ops.%s\" error, "
215  "expected a string enum in (%s)",
216  opname,
217  enum_str);
218  MEM_freeN(enum_str);
219  return NULL;
220  }
221  }
222 
223  if (ELEM(context_dict, NULL, Py_None)) {
224  context_dict = NULL;
225  }
226  else if (!PyDict_Check(context_dict)) {
227  PyErr_Format(PyExc_TypeError,
228  "Calling operator \"bpy.ops.%s\" error, "
229  "custom context expected a dict or None, got a %.200s",
230  opname,
231  Py_TYPE(context_dict)->tp_name);
232  return NULL;
233  }
234 
240  struct bContext_PyState context_py_state;
241  if (context_dict != NULL) {
242  CTX_py_state_push(C, &context_py_state, (void *)context_dict);
243  Py_INCREF(context_dict); /* so we don't lose it */
244  }
245 
246  if (WM_operator_poll_context((bContext *)C, ot, context) == false) {
247  const char *msg = CTX_wm_operator_poll_msg_get(C);
248  PyErr_Format(PyExc_RuntimeError,
249  "Operator bpy.ops.%.200s.poll() %.200s",
250  opname,
251  msg ? msg : "failed, context is incorrect");
252  CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
253  error_val = -1;
254  }
255  else {
258 
259  if (kw && PyDict_Size(kw)) {
260  error_val = pyrna_pydict_to_props(
261  &ptr, kw, false, "Converting py args to operator properties: ");
262  }
263 
264  if (error_val == 0) {
265  ReportList *reports;
266 
267  reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
268 
269  /* Own so these don't move into global reports. */
271 
272 #ifdef BPY_RELEASE_GIL
273  /* release GIL, since a thread could be started from an operator
274  * that updates a driver */
275  /* note: I have not seen any examples of code that does this
276  * so it may not be officially supported but seems to work ok. */
277  {
278  PyThreadState *ts = PyEval_SaveThread();
279 #endif
280 
281  operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports, is_undo);
282 
283 #ifdef BPY_RELEASE_GIL
284  /* regain GIL */
285  PyEval_RestoreThread(ts);
286  }
287 #endif
288 
289  error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, false);
290 
291  /* operator output is nice to have in the terminal/console too */
292  if (!BLI_listbase_is_empty(&reports->list)) {
293  BPy_reports_write_stdout(reports, NULL);
294  }
295 
296  BKE_reports_clear(reports);
297  if ((reports->flag & RPT_FREE) == 0) {
298  MEM_freeN(reports);
299  }
300  else {
301  /* The WM is now responsible for running the modal operator,
302  * show reports in the info window. */
303  reports->flag &= ~RPT_OP_HOLD;
304  }
305  }
306 
308 
309 #if 0
310  /* if there is some way to know an operator takes args we should use this */
311  {
312  /* no props */
313  if (kw != NULL) {
314  PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
315  return NULL;
316  }
317 
319  }
320 #endif
321  }
322 
323  if (context_dict != NULL) {
324  PyObject *context_dict_test = CTX_py_dict_get(C);
325  if (context_dict_test != context_dict) {
326  Py_DECREF(context_dict_test);
327  }
328  /* Restore with original context dict,
329  * probably NULL but need this for nested operator calls. */
330  Py_DECREF(context_dict);
331  CTX_py_state_pop(C, &context_py_state);
332  }
333 
334  if (error_val == -1) {
335  return NULL;
336  }
337 
338  /* When calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer
339  * is freed by clear_globals(), further access will crash blender.
340  * Setting context is not needed in this case, only calling because this
341  * function corrects bpy.data (internal Main pointer) */
343 
344  /* return operator_ret as a bpy enum */
346 }
347 
348 static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
349 {
351  PointerRNA ptr;
352 
353  const char *opname;
354  PyObject *kw = NULL; /* optional args */
355  bool all_args = true;
356  bool macro_args = true;
357  int error_val = 0;
358 
359  char *buf = NULL;
360  PyObject *pybuf;
361 
363 
364  if (C == NULL) {
365  PyErr_SetString(PyExc_RuntimeError,
366  "Context is None, cant get the string representation of this object.");
367  return NULL;
368  }
369 
370  if (!PyArg_ParseTuple(args,
371  "s|O!O&O&:_bpy.ops.as_string",
372  &opname,
373  &PyDict_Type,
374  &kw,
376  &all_args,
378  &macro_args)) {
379  return NULL;
380  }
381 
382  ot = WM_operatortype_find(opname, true);
383 
384  if (ot == NULL) {
385  PyErr_Format(PyExc_AttributeError,
386  "_bpy.ops.as_string: operator \"%.200s\" "
387  "could not be found",
388  opname);
389  return NULL;
390  }
391 
392  /* WM_operator_properties_create(&ptr, opname); */
393  /* Save another lookup */
395 
396  if (kw && PyDict_Size(kw)) {
397  error_val = pyrna_pydict_to_props(
398  &ptr, kw, false, "Converting py args to operator properties: ");
399  }
400 
401  if (error_val == 0) {
402  buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr);
403  }
404 
406 
407  if (error_val == -1) {
408  return NULL;
409  }
410 
411  if (buf) {
412  pybuf = PyUnicode_FromString(buf);
413  MEM_freeN(buf);
414  }
415  else {
416  pybuf = PyUnicode_FromString("");
417  }
418 
419  return pybuf;
420 }
421 
422 static PyObject *pyop_dir(PyObject *UNUSED(self))
423 {
424  GHashIterator iter;
425  PyObject *list;
426  int i;
427 
428  WM_operatortype_iter(&iter);
429  list = PyList_New(BLI_ghash_len(iter.gh));
430 
431  for (i = 0; !BLI_ghashIterator_done(&iter); BLI_ghashIterator_step(&iter), i++) {
433  PyList_SET_ITEM(list, i, PyUnicode_FromString(ot->idname));
434  }
435 
436  return list;
437 }
438 
439 static PyObject *pyop_getrna_type(PyObject *UNUSED(self), PyObject *value)
440 {
442  if ((ot = ot_lookup_from_py_string(value, "get_rna_type")) == NULL) {
443  return NULL;
444  }
445 
446  PointerRNA ptr;
449  return (PyObject *)pyrna;
450 }
451 
452 static PyObject *pyop_get_bl_options(PyObject *UNUSED(self), PyObject *value)
453 {
455  if ((ot = ot_lookup_from_py_string(value, "get_bl_options")) == NULL) {
456  return NULL;
457  }
459 }
460 
461 static struct PyMethodDef bpy_ops_methods[] = {
462  {"poll", (PyCFunction)pyop_poll, METH_VARARGS, NULL},
463  {"call", (PyCFunction)pyop_call, METH_VARARGS, NULL},
464  {"as_string", (PyCFunction)pyop_as_string, METH_VARARGS, NULL},
465  {"dir", (PyCFunction)pyop_dir, METH_NOARGS, NULL},
466  {"get_rna_type", (PyCFunction)pyop_getrna_type, METH_O, NULL},
467  {"get_bl_options", (PyCFunction)pyop_get_bl_options, METH_O, NULL},
468  {"macro_define", (PyCFunction)PYOP_wrap_macro_define, METH_VARARGS, NULL},
469  {NULL, NULL, 0, NULL},
470 };
471 
472 static struct PyModuleDef bpy_ops_module = {
473  PyModuleDef_HEAD_INIT,
474  "_bpy.ops",
475  NULL,
476  -1, /* multiple "initialization" just copies the module dict. */
478  NULL,
479  NULL,
480  NULL,
481  NULL,
482 };
483 
484 PyObject *BPY_operator_module(void)
485 {
486  PyObject *submodule;
487 
488  submodule = PyModule_Create(&bpy_ops_module);
489 
490  return submodule;
491 }
void CTX_py_state_push(bContext *C, struct bContext_PyState *pystate, void *value)
Definition: context.c:233
void * CTX_py_dict_get(const bContext *C)
Definition: context.c:224
const char * CTX_wm_operator_poll_msg_get(struct bContext *C)
Definition: context.c:1011
void CTX_py_state_pop(bContext *C, struct bContext_PyState *pystate)
Definition: context.c:241
void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg)
Definition: context.c:1006
void BKE_reports_clear(ReportList *reports)
Definition: report.c:84
void BKE_reports_init(ReportList *reports, int flag)
Definition: report.c:66
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition: BLI_ghash.c:1086
BLI_INLINE bool BLI_ghashIterator_done(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:158
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:150
unsigned int BLI_ghash_len(GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:744
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define UNUSED(x)
#define ELEM(...)
void BPY_modules_update(void)
@ OPERATOR_CANCELLED
Read Guarded memory(de)allocation.
StructRNA RNA_Struct
#define C
Definition: RandGen.cpp:39
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:204
char * BPy_enum_as_string(const EnumPropertyItem *item)
void BPy_reports_write_stdout(const ReportList *reports, const char *header)
short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
struct bContext * BPY_context_get(void)
static wmOperatorType * ot_lookup_from_py_string(PyObject *value, const char *py_fn_id)
Definition: bpy_operator.c:59
static PyObject * pyop_getrna_type(PyObject *UNUSED(self), PyObject *value)
Definition: bpy_operator.c:439
static struct PyModuleDef bpy_ops_module
Definition: bpy_operator.c:472
static PyObject * pyop_as_string(PyObject *UNUSED(self), PyObject *args)
Definition: bpy_operator.c:348
static PyObject * pyop_dir(PyObject *UNUSED(self))
Definition: bpy_operator.c:422
static struct PyMethodDef bpy_ops_methods[]
Definition: bpy_operator.c:461
PyObject * BPY_operator_module(void)
Definition: bpy_operator.c:484
static PyObject * pyop_poll(PyObject *UNUSED(self), PyObject *args)
Definition: bpy_operator.c:75
static PyObject * pyop_call(PyObject *UNUSED(self), PyObject *args)
Definition: bpy_operator.c:156
static PyObject * pyop_get_bl_options(PyObject *UNUSED(self), PyObject *value)
Definition: bpy_operator.c:452
PyObject * PYOP_wrap_macro_define(PyObject *UNUSED(self), PyObject *args)
PyObject * pyrna_enum_bitfield_to_py(const EnumPropertyItem *items, int value)
Definition: bpy_rna.c:1444
bool pyrna_write_check(void)
Definition: bpy_rna.c:362
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
Definition: bpy_rna.c:7469
int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const bool all_args, const char *error_prefix)
Definition: bpy_rna.c:1622
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
int PyC_ParseBool(PyObject *o, void *p)
return ret
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
Definition: rna_access.c:6474
const EnumPropertyItem rna_enum_operator_context_items[]
Definition: rna_ui.c:44
const EnumPropertyItem rna_enum_operator_type_flag_items[]
Definition: rna_wm.c:449
const EnumPropertyItem rna_enum_operator_return_items[]
Definition: rna_wm.c:476
struct SELECTID_Context context
Definition: select_engine.c:47
GHash * gh
Definition: BLI_ghash.h:57
const char * idname
Definition: WM_types.h:723
struct StructRNA * srna
Definition: WM_types.h:802
bool WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
int WM_operator_name_call(bContext *C, const char *opstring, short context, PointerRNA *properties)
int WM_operator_call_py(bContext *C, wmOperatorType *ot, short context, PointerRNA *properties, ReportList *reports, const bool is_undo)
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
void WM_operatortype_iter(GHashIterator *ghi)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
char * WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, const bool macro_args, wmOperatorType *ot, PointerRNA *opptr)
Definition: wm_operators.c:228
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:584
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:711
void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context)
Definition: wm_operators.c:620