Blender V2.61 - r43446
|
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 }