Blender V2.61 - r43446

bpy_operator.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Campbell Barton
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00034 #include <Python.h>
00035 
00036 #include "RNA_types.h"
00037 
00038 #include "BPY_extern.h"
00039 #include "bpy_operator.h"
00040 #include "bpy_operator_wrap.h"
00041 #include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
00042 #include "bpy_util.h"
00043 #include "../generic/bpy_internal_import.h"
00044 
00045 #include "BLI_utildefines.h"
00046 #include "BLI_string.h"
00047 
00048 #include "RNA_access.h"
00049 #include "RNA_enum_types.h"
00050 
00051 #include "WM_api.h"
00052 #include "WM_types.h"
00053 
00054 #include "MEM_guardedalloc.h"
00055 
00056 #include "BLI_ghash.h"
00057 
00058 #include "BKE_report.h"
00059 #include "BKE_context.h"
00060 
00061 /* so operators called can spawn threads which aquire the GIL */
00062 #define BPY_RELEASE_GIL
00063 
00064 
00065 static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
00066 {
00067     wmOperatorType *ot;
00068     char        *opname;
00069     PyObject    *context_dict = NULL; /* optional args */
00070     PyObject    *context_dict_back;
00071     char        *context_str = NULL;
00072     PyObject    *ret;
00073 
00074     int context = WM_OP_EXEC_DEFAULT;
00075 
00076     /* XXX Todo, work out a better solution for passing on context,
00077      * could make a tuple from self and pack the name and Context into it... */
00078     bContext *C = (bContext *)BPy_GetContext();
00079     
00080     if (C == NULL) {
00081         PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
00082         return NULL;
00083     }
00084 
00085     if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str))
00086         return NULL;
00087     
00088     ot = WM_operatortype_find(opname, TRUE);
00089 
00090     if (ot == NULL) {
00091         PyErr_Format(PyExc_AttributeError,
00092                      "Polling operator \"bpy.ops.%s\" error, "
00093                      "could not be found", opname);
00094         return NULL;
00095     }
00096 
00097     if (context_str) {
00098         if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) {
00099             char *enum_str = BPy_enum_as_string(operator_context_items);
00100             PyErr_Format(PyExc_TypeError,
00101                          "Calling operator \"bpy.ops.%s.poll\" error, "
00102                          "expected a string enum in (%.200s)",
00103                          opname, enum_str);
00104             MEM_freeN(enum_str);
00105             return NULL;
00106         }
00107     }
00108     
00109     if (context_dict == NULL || context_dict == Py_None) {
00110         context_dict = NULL;
00111     }
00112     else if (!PyDict_Check(context_dict)) {
00113         PyErr_Format(PyExc_TypeError,
00114                      "Calling operator \"bpy.ops.%s.poll\" error, "
00115                      "custom context expected a dict or None, got a %.200s",
00116                      opname, Py_TYPE(context_dict)->tp_name);
00117         return NULL;
00118     }
00119 
00120     context_dict_back = CTX_py_dict_get(C);
00121     CTX_py_dict_set(C, (void *)context_dict);
00122     Py_XINCREF(context_dict); /* so we done loose it */
00123     
00124     /* main purpose of thsi function */
00125     ret = WM_operator_poll_context((bContext *)C, ot, context) ? Py_True : Py_False;
00126     
00127     /* restore with original context dict, probably NULL but need this for nested operator calls */
00128     Py_XDECREF(context_dict);
00129     CTX_py_dict_set(C, (void *)context_dict_back);
00130     
00131     Py_INCREF(ret);
00132     return ret;
00133 }
00134 
00135 static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
00136 {
00137     wmOperatorType *ot;
00138     int error_val = 0;
00139     PointerRNA ptr;
00140     int operator_ret = OPERATOR_CANCELLED;
00141 
00142     char        *opname;
00143     char        *context_str = NULL;
00144     PyObject    *kw = NULL; /* optional args */
00145     PyObject    *context_dict = NULL; /* optional args */
00146     PyObject    *context_dict_back;
00147 
00148     /* note that context is an int, python does the conversion in this case */
00149     int context = WM_OP_EXEC_DEFAULT;
00150 
00151     /* XXX Todo, work out a better solution for passing on context,
00152      * could make a tuple from self and pack the name and Context into it... */
00153     bContext *C = (bContext *)BPy_GetContext();
00154     
00155     if (C == NULL) {
00156         PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
00157         return NULL;
00158     }
00159     
00160     if (!PyArg_ParseTuple(args, "sO|O!s:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str))
00161         return NULL;
00162 
00163     ot = WM_operatortype_find(opname, TRUE);
00164 
00165     if (ot == NULL) {
00166         PyErr_Format(PyExc_AttributeError,
00167                      "Calling operator \"bpy.ops.%s\" error, "
00168                      "could not be found", opname);
00169         return NULL;
00170     }
00171     
00172     if (!pyrna_write_check()) {
00173         PyErr_Format(PyExc_RuntimeError,
00174                      "Calling operator \"bpy.ops.%s\" error, "
00175                      "can't modify blend data in this state (drawing/rendering)",
00176                      opname);
00177         return NULL;
00178     }
00179 
00180     if (context_str) {
00181         if (RNA_enum_value_from_id(operator_context_items, context_str, &context) == 0) {
00182             char *enum_str = BPy_enum_as_string(operator_context_items);
00183             PyErr_Format(PyExc_TypeError,
00184                          "Calling operator \"bpy.ops.%s\" error, "
00185                          "expected a string enum in (%.200s)",
00186                          opname, enum_str);
00187             MEM_freeN(enum_str);
00188             return NULL;
00189         }
00190     }
00191 
00192     if (context_dict == NULL || context_dict == Py_None) {
00193         context_dict = NULL;
00194     }
00195     else if (!PyDict_Check(context_dict)) {
00196         PyErr_Format(PyExc_TypeError,
00197                      "Calling operator \"bpy.ops.%s\" error, "
00198                      "custom context expected a dict or None, got a %.200s",
00199                      opname, Py_TYPE(context_dict)->tp_name);
00200         return NULL;
00201     }
00202 
00203     context_dict_back = CTX_py_dict_get(C);
00204 
00205     CTX_py_dict_set(C, (void *)context_dict);
00206     Py_XINCREF(context_dict); /* so we done loose it */
00207 
00208     if (WM_operator_poll_context((bContext *)C, ot, context) == FALSE) {
00209         const char *msg = CTX_wm_operator_poll_msg_get(C);
00210         PyErr_Format(PyExc_RuntimeError,
00211                      "Operator bpy.ops.%.200s.poll() %.200s",
00212                      opname, msg ? msg : "failed, context is incorrect");
00213         CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
00214         error_val = -1;
00215     }
00216     else {
00217         WM_operator_properties_create_ptr(&ptr, ot);
00218         WM_operator_properties_sanitize(&ptr, 0);
00219 
00220         if (kw && PyDict_Size(kw))
00221             error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
00222 
00223 
00224         if (error_val == 0) {
00225             ReportList *reports;
00226 
00227             reports = MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
00228             BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these dont move into global reports */
00229 
00230 #ifdef BPY_RELEASE_GIL
00231             /* release GIL, since a thread could be started from an operator
00232              * that updates a driver */
00233             /* note: I havve not seen any examples of code that does this
00234              * so it may not be officially supported but seems to work ok. */
00235             {
00236                 PyThreadState *ts = PyEval_SaveThread();
00237 #endif
00238 
00239                 operator_ret = WM_operator_call_py(C, ot, context, &ptr, reports);
00240 
00241 #ifdef BPY_RELEASE_GIL
00242                 /* regain GIL */
00243                 PyEval_RestoreThread(ts);
00244             }
00245 #endif
00246 
00247             error_val = BPy_reports_to_error(reports, PyExc_RuntimeError, FALSE);
00248 
00249             /* operator output is nice to have in the terminal/console too */
00250             if (reports->list.first) {
00251                 char *report_str = BKE_reports_string(reports, 0); /* all reports */
00252     
00253                 if (report_str) {
00254                     PySys_WriteStdout("%s\n", report_str);
00255                     MEM_freeN(report_str);
00256                 }
00257             }
00258     
00259             BKE_reports_clear(reports);
00260             if ((reports->flag & RPT_FREE) == 0)
00261             {
00262                 MEM_freeN(reports);
00263             }
00264         }
00265 
00266         WM_operator_properties_free(&ptr);
00267 
00268 #if 0
00269         /* if there is some way to know an operator takes args we should use this */
00270         {
00271             /* no props */
00272             if (kw != NULL) {
00273                 PyErr_Format(PyExc_AttributeError,
00274                              "Operator \"%s\" does not take any args",
00275                              opname);
00276                 return NULL;
00277             }
00278 
00279             WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
00280         }
00281 #endif
00282     }
00283 
00284     /* restore with original context dict, probably NULL but need this for nested operator calls */
00285     Py_XDECREF(context_dict);
00286     CTX_py_dict_set(C, (void *)context_dict_back);
00287 
00288     if (error_val == -1) {
00289         return NULL;
00290     }
00291 
00292     /* when calling  bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
00293      * further access will crash blender. setting context is not needed in this case, only calling because this
00294      * function corrects bpy.data (internal Main pointer) */
00295     BPY_modules_update(C);
00296 
00297     /* needed for when WM_OT_read_factory_settings us called from within a script */
00298     bpy_import_main_set(CTX_data_main(C));
00299 
00300     /* return operator_ret as a bpy enum */
00301     return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret);
00302 
00303 }
00304 
00305 static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
00306 {
00307     wmOperatorType *ot;
00308     PointerRNA ptr;
00309 
00310     char        *opname;
00311     PyObject    *kw = NULL; /* optional args */
00312     int all_args = 1;
00313     int error_val = 0;
00314 
00315     char *buf = NULL;
00316     PyObject *pybuf;
00317 
00318     bContext *C = (bContext *)BPy_GetContext();
00319 
00320     if (C == NULL) {
00321         PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object.");
00322         return NULL;
00323     }
00324     
00325     if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
00326         return NULL;
00327 
00328     ot = WM_operatortype_find(opname, TRUE);
00329 
00330     if (ot == NULL) {
00331         PyErr_Format(PyExc_AttributeError,
00332                      "_bpy.ops.as_string: operator \"%.200s\" "
00333                      "could not be found", opname);
00334         return NULL;
00335     }
00336 
00337     /* WM_operator_properties_create(&ptr, opname); */
00338     /* Save another lookup */
00339     RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
00340 
00341     if (kw && PyDict_Size(kw))
00342         error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
00343 
00344     if (error_val == 0)
00345         buf = WM_operator_pystring(C, ot, &ptr, all_args);
00346 
00347     WM_operator_properties_free(&ptr);
00348 
00349     if (error_val == -1) {
00350         return NULL;
00351     }
00352 
00353     if (buf) {
00354         pybuf = PyUnicode_FromString(buf);
00355         MEM_freeN(buf);
00356     }
00357     else {
00358         pybuf = PyUnicode_FromString("");
00359     }
00360 
00361     return pybuf;
00362 }
00363 
00364 static PyObject *pyop_dir(PyObject *UNUSED(self))
00365 {
00366     GHashIterator *iter = WM_operatortype_iter();
00367     PyObject *list = PyList_New(0), *name;
00368 
00369     for ( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
00370         wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
00371 
00372         name = PyUnicode_FromString(ot->idname);
00373         PyList_Append(list, name);
00374         Py_DECREF(name);
00375     }
00376     BLI_ghashIterator_free(iter);
00377 
00378     return list;
00379 }
00380 
00381 static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value)
00382 {
00383     wmOperatorType *ot;
00384     PointerRNA ptr;
00385     const char *opname = _PyUnicode_AsString(value);
00386     BPy_StructRNA *pyrna = NULL;
00387     
00388     if (opname == NULL) {
00389         PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_rna() expects a string argument");
00390         return NULL;
00391     }
00392     ot = WM_operatortype_find(opname, TRUE);
00393     if (ot  == NULL) {
00394         PyErr_Format(PyExc_KeyError, "_bpy.ops.get_rna(\"%s\") not found", opname);
00395         return NULL;
00396     }
00397     
00398     /* type */
00399     //RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr);
00400 
00401     /* XXX - should call WM_operator_properties_free */
00402     WM_operator_properties_create_ptr(&ptr, ot);
00403     WM_operator_properties_sanitize(&ptr, 0);
00404 
00405     
00406     pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
00407 #ifdef PYRNA_FREE_SUPPORT
00408     pyrna->freeptr = TRUE;
00409 #endif
00410     return (PyObject *)pyrna;
00411 }
00412 
00413 static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value)
00414 {
00415     wmOperatorType *ot;
00416     wmOperator *op;
00417     PointerRNA ptr;
00418     const char *opname = _PyUnicode_AsString(value);
00419     BPy_StructRNA *pyrna = NULL;
00420 
00421     if (opname == NULL) {
00422         PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_instance() expects a string argument");
00423         return NULL;
00424     }
00425     ot = WM_operatortype_find(opname, TRUE);
00426     if (ot == NULL) {
00427         PyErr_Format(PyExc_KeyError, "_bpy.ops.get_instance(\"%s\") not found", opname);
00428         return NULL;
00429     }
00430 
00431 #ifdef PYRNA_FREE_SUPPORT
00432     op = MEM_callocN(sizeof(wmOperator), __func__);
00433 #else
00434     op = PyMem_MALLOC(sizeof(wmOperator));
00435     memset(op, 0, sizeof(wmOperator));
00436 #endif
00437     BLI_strncpy(op->idname, op->idname, sizeof(op->idname)); /* incase its needed */
00438     op->type = ot;
00439 
00440     RNA_pointer_create(NULL, &RNA_Operator, op, &ptr);
00441 
00442     pyrna = (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
00443 #ifdef PYRNA_FREE_SUPPORT
00444     pyrna->freeptr = TRUE;
00445 #endif
00446     op->ptr = &pyrna->ptr;
00447 
00448     return (PyObject *)pyrna;
00449 }
00450 
00451 static struct PyMethodDef bpy_ops_methods[] = {
00452     {"poll", (PyCFunction) pyop_poll, METH_VARARGS, NULL},
00453     {"call", (PyCFunction) pyop_call, METH_VARARGS, NULL},
00454     {"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL},
00455     {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL},
00456     {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL},           /* only for introspection, leaks memory */
00457     {"get_instance", (PyCFunction) pyop_getinstance, METH_O, NULL}, /* only for introspection, leaks memory */
00458     {"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL},
00459     {NULL, NULL, 0, NULL}
00460 };
00461 
00462 static struct PyModuleDef bpy_ops_module = {
00463     PyModuleDef_HEAD_INIT,
00464     "_bpy.ops",
00465     NULL,
00466     -1,/* multiple "initialization" just copies the module dict. */
00467     bpy_ops_methods,
00468     NULL, NULL, NULL, NULL
00469 };
00470 
00471 PyObject *BPY_operator_module(void)
00472 {
00473     PyObject *submodule;
00474 
00475     submodule = PyModule_Create(&bpy_ops_module);
00476 
00477     return submodule;
00478 }