fix to allow [#24009] to be fixed.

WM_operator_poll() could fail in cases WM_operator_name_call() would succeed because calling the operator would setup the context before calling poll.
this would result in python raising an invalid error or menu items being greyed out.

now python can also check with an operator context:
  bpy.ops.object.editmode_toggle.poll('INVOKE_SCREEN')
This commit is contained in:
2010-11-04 12:59:03 +00:00
parent 0e81723683
commit 64ff9d6de4
6 changed files with 64 additions and 39 deletions

View File

@@ -46,12 +46,15 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
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();
if (!PyArg_ParseTuple(args, "s|O:_bpy.ops.poll", &opname, &context_dict))
if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str))
return NULL;
ot= WM_operatortype_find(opname, TRUE);
@@ -61,6 +64,15 @@ static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
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);
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(!PyDict_Check(context_dict))
context_dict= NULL;
@@ -70,7 +82,7 @@ static PyObject *pyop_poll(PyObject *UNUSED(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);
@@ -126,7 +138,7 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
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) {
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() %s", 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 */