Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/python/intern/bpy_operator.c')
-rw-r--r--source/blender/python/intern/bpy_operator.c94
1 files changed, 71 insertions, 23 deletions
diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c
index eeab1fce4b2..70aa46c1302 100644
--- a/source/blender/python/intern/bpy_operator.c
+++ b/source/blender/python/intern/bpy_operator.c
@@ -32,6 +32,8 @@
#include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
#include "bpy_util.h"
+#include "BLI_utildefines.h"
+
#include "RNA_enum_types.h"
#include "WM_api.h"
@@ -40,18 +42,26 @@
#include "MEM_guardedalloc.h"
#include "BKE_report.h"
-static PyObject *pyop_poll( PyObject * self, PyObject * args)
+static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
{
wmOperatorType *ot;
char *opname;
PyObject *context_dict= NULL; /* optional args */
PyObject *context_dict_back;
+ char *context_str= NULL;
PyObject *ret;
+ int context= WM_OP_EXEC_DEFAULT;
+
// XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
- bContext *C = BPy_GetContext();
+ bContext *C= (bContext *)BPy_GetContext();
- if (!PyArg_ParseTuple(args, "s|O:_bpy.ops.poll", &opname, &context_dict))
+ if(C==NULL) {
+ PyErr_SetString(PyExc_SystemError, "Context is None, cant poll any operators");
+ return NULL;
+ }
+
+ if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str))
return NULL;
ot= WM_operatortype_find(opname, TRUE);
@@ -61,8 +71,22 @@ static PyObject *pyop_poll( PyObject * self, PyObject * args)
return NULL;
}
- if(!PyDict_Check(context_dict))
+ if(context_str) {
+ if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
+ char *enum_str= BPy_enum_as_string(operator_context_items);
+ PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, expected a string enum in (%.200s)", opname, enum_str);
+ MEM_freeN(enum_str);
+ return NULL;
+ }
+ }
+
+ if(context_dict==NULL || context_dict==Py_None) {
context_dict= NULL;
+ }
+ else if (!PyDict_Check(context_dict)) {
+ PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name);
+ return NULL;
+ }
context_dict_back= CTX_py_dict_get(C);
@@ -70,7 +94,7 @@ static PyObject *pyop_poll( PyObject * self, PyObject * args)
Py_XINCREF(context_dict); /* so we done loose it */
/* main purpose of thsi function */
- ret= WM_operator_poll((bContext*)C, ot) ? Py_True : Py_False;
+ ret= WM_operator_poll_context((bContext*)C, ot, context) ? Py_True : Py_False;
/* restore with original context dict, probably NULL but need this for nested operator calls */
Py_XDECREF(context_dict);
@@ -80,7 +104,7 @@ static PyObject *pyop_poll( PyObject * self, PyObject * args)
return ret;
}
-static PyObject *pyop_call( PyObject * self, PyObject * args)
+static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
{
wmOperatorType *ot;
int error_val = 0;
@@ -97,7 +121,12 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
int context= WM_OP_EXEC_DEFAULT;
// XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
- bContext *C = BPy_GetContext();
+ bContext *C = (bContext *)BPy_GetContext();
+
+ if(C==NULL) {
+ PyErr_SetString(PyExc_SystemError, "Context is None, cant poll any operators");
+ return NULL;
+ }
if (!PyArg_ParseTuple(args, "sO|O!s:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str))
return NULL;
@@ -109,6 +138,11 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
return NULL;
}
+ if(!pyrna_write_check()) {
+ PyErr_Format(PyExc_SystemError, "Calling operator \"bpy.ops.%s\" error, can't modify blend data in this state (drawing/rendering)", opname);
+ return NULL;
+ }
+
if(context_str) {
if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
char *enum_str= BPy_enum_as_string(operator_context_items);
@@ -118,20 +152,28 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
}
}
- if(!PyDict_Check(context_dict))
+ if(context_dict==NULL || context_dict==Py_None) {
context_dict= NULL;
+ }
+ else if (!PyDict_Check(context_dict)) {
+ PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name);
+ return NULL;
+ }
context_dict_back= CTX_py_dict_get(C);
CTX_py_dict_set(C, (void *)context_dict);
Py_XINCREF(context_dict); /* so we done loose it */
- if(WM_operator_poll((bContext*)C, ot) == FALSE) {
- PyErr_Format( PyExc_SystemError, "Operator bpy.ops.%.200s.poll() failed, context is incorrect", opname);
+ if(WM_operator_poll_context((bContext*)C, ot, context) == FALSE) {
+ const char *msg= CTX_wm_operator_poll_msg_get(C);
+ PyErr_Format(PyExc_SystemError, "Operator bpy.ops.%.200s.poll() %.200s", opname, msg ? msg : "failed, context is incorrect");
+ CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
error_val= -1;
}
else {
WM_operator_properties_create_ptr(&ptr, ot);
+ WM_operator_properties_sanitize(&ptr, 0);
if(kw && PyDict_Size(kw))
error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
@@ -145,7 +187,7 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports);
- if(BPy_reports_to_error(reports))
+ if(BPy_reports_to_error(reports, FALSE))
error_val = -1;
/* operator output is nice to have in the terminal/console too */
@@ -189,12 +231,18 @@ static PyObject *pyop_call( PyObject * self, PyObject * args)
return NULL;
}
+ /* when calling bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
+ * further access will crash blender. setting context is not needed in this case, only calling because this
+ * function corrects bpy.data (internal Main pointer) */
+ BPY_modules_update(C);
+
+
/* return operator_ret as a bpy enum */
return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret);
}
-static PyObject *pyop_as_string( PyObject * self, PyObject * args)
+static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
{
wmOperatorType *ot;
PointerRNA ptr;
@@ -207,15 +255,20 @@ static PyObject *pyop_as_string( PyObject * self, PyObject * args)
char *buf = NULL;
PyObject *pybuf;
- bContext *C = BPy_GetContext();
+ bContext *C = (bContext *)BPy_GetContext();
+ if(C==NULL) {
+ PyErr_SetString(PyExc_SystemError, "Context is None, cant get the string representation of this object.");
+ return NULL;
+ }
+
if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
return NULL;
ot= WM_operatortype_find(opname, TRUE);
if (ot == NULL) {
- PyErr_Format( PyExc_SystemError, "_bpy.ops.as_string: operator \"%s\"could not be found", opname);
+ PyErr_Format(PyExc_SystemError, "_bpy.ops.as_string: operator \"%.200s\"could not be found", opname);
return NULL;
}
@@ -246,7 +299,7 @@ static PyObject *pyop_as_string( PyObject * self, PyObject * args)
return pybuf;
}
-static PyObject *pyop_dir(PyObject *self)
+static PyObject *pyop_dir(PyObject *UNUSED(self))
{
PyObject *list = PyList_New(0), *name;
wmOperatorType *ot;
@@ -260,7 +313,7 @@ static PyObject *pyop_dir(PyObject *self)
return list;
}
-static PyObject *pyop_getrna(PyObject *self, PyObject *value)
+static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value)
{
wmOperatorType *ot;
PointerRNA ptr;
@@ -282,6 +335,7 @@ static PyObject *pyop_getrna(PyObject *self, PyObject *value)
/* XXX - should call WM_operator_properties_free */
WM_operator_properties_create_ptr(&ptr, ot);
+ WM_operator_properties_sanitize(&ptr, 0);
pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
@@ -311,14 +365,8 @@ static struct PyModuleDef bpy_ops_module = {
PyObject *BPY_operator_module(void)
{
PyObject *submodule;
-
- submodule= PyModule_Create(&bpy_ops_module);
- PyDict_SetItemString(PyImport_GetModuleDict(), bpy_ops_module.m_name, submodule);
- /* INCREF since its its assumed that all these functions return the
- * module with a new ref like PyDict_New, since they are passed to
- * PyModule_AddObject which steals a ref */
- Py_INCREF(submodule);
+ submodule= PyModule_Create(&bpy_ops_module);
return submodule;
}