// Get the receiver QObject from the slot (if there is one) and its signature // (if it wraps a Qt slot). A Python exception will be raised if there was an // error. static QObject *get_receiver(qpycore_pyqtBoundSignal *bs, PyObject *slot_obj, QByteArray &name) { PyObject *rx_self, *decorations; QByteArray rx_name; bool try_qt_slot; Chimera::Signature *signature = bs->unbound_signal->signature; decorations = 0; if (PyMethod_Check(slot_obj)) { rx_self = PyMethod_GET_SELF(slot_obj); PyObject *f = PyMethod_GET_FUNCTION(slot_obj); Q_ASSERT(PyFunction_Check(f)); PyObject *f_name_obj = ((PyFunctionObject *)f)->func_name; const char *f_name = sipString_AsASCIIString(&f_name_obj); Q_ASSERT(f_name); rx_name = f_name; Py_DECREF(f_name_obj); // See if this has been decorated. decorations = PyObject_GetAttr(f, qpycore_signature_attr_name); if (decorations) { try_qt_slot = true; // It's convenient to do this here as it's not going to disappear. Py_DECREF(decorations); } else { try_qt_slot = false; } Py_XINCREF(rx_self); } else if (PyCFunction_Check(slot_obj)) { rx_self = PyCFunction_GET_SELF(slot_obj); rx_name = ((PyCFunctionObject *)slot_obj)->m_ml->ml_name; // We actually want the C++ name which may (in theory) be completely // different. However this will cope with the exec_ case which is // probably good enough. if (rx_name.endsWith('_')) rx_name.chop(1); try_qt_slot = true; Py_XINCREF(rx_self); } else { static PyObject *partial = 0; // Get the functools.partial type object if we haven't already got it. if (!partial) { PyObject *functools = PyImport_ImportModule("functools"); if (functools) { partial = PyObject_GetAttrString(functools, "partial"); Py_DECREF(functools); } } // If we know about functools.partial then remove the outer partials to // get to the original function. if (partial && PyObject_IsInstance(slot_obj, partial)) { PyObject *func = slot_obj; Py_INCREF(func); do { PyObject *subfunc = PyObject_GetAttrString(func, "func"); Py_DECREF(func); // This should never happen. if (!subfunc) return 0; func = subfunc; } while (PyObject_IsInstance(func, partial)); if (PyMethod_Check(func)) rx_self = PyMethod_GET_SELF(func); else if (PyCFunction_Check(func)) rx_self = PyCFunction_GET_SELF(func); else rx_self = 0; Py_XINCREF(rx_self); Py_DECREF(func); try_qt_slot = false; } else { rx_self = 0; } } if (!rx_self) return 0; int iserr = 0; void *rx = sipForceConvertToType(rx_self, sipType_QObject, 0, SIP_NO_CONVERTORS, 0, &iserr); Py_DECREF(rx_self); PyErr_Clear(); if (iserr) return 0; QObject *rx_qobj = reinterpret_cast<QObject *>(rx); // If there might be a Qt slot that can handle the arguments (or a subset // of them) then use it. Otherwise we will fallback to using a proxy. if (try_qt_slot) { for (int ol = signature->parsed_arguments.count(); ol >= 0; --ol) { // If there are decorations then we compare the signal's signature // against them so that we distinguish between Python types that // are passed to Qt as PyQt_PyObject objects. Qt will not make the // distinction. If there are no decorations then let Qt determine // if a slot is available. if (decorations) name = slot_signature_from_decorations(signature, decorations, ol); else name = slot_signature_from_metaobject(signature, rx_qobj->metaObject(), rx_name, ol); if (!name.isEmpty()) { // Prepend the magic slot marker. name.prepend('1'); break; } } } return rx_qobj; }
static foreign_t python_function(term_t tobj) { PyObject *obj = term_to_python(tobj, true); foreign_t rc = PyFunction_Check(obj); return rc; }
// // no point in reinventing the wheel; start_event and start_update both // need to be handled exactly the same, so here's a function to do just that PyObject *PyEvent_start(PyObject *self, PyObject *args, void *func) { void (* start_func)(void *, int, void *, void *, void *, const char *) = func; PyObject *PyOwner = NULL; // the python representation of our owner PyObject *efunc = NULL; // the event function PyObject *edata = Py_None; // the event data char *arg = NULL; // the arg we will be supplying to the function double delay = 0; // how long the event delay is (in seconds) void *owner = NULL; // actual owner supplied to the event handler char otype[20]; // is the owner a char, room, obj, or None? // try to parse all of our values if(!PyArg_ParseTuple(args, "OdO|Os", &PyOwner, &delay, &efunc, &edata, &arg)){ //PyErr_Format(PyExc_TypeError, //"Invalid arguments provided to event handler"); return NULL; } // make sure our event is a function if(!PyFunction_Check(efunc)) { PyErr_Format(PyExc_TypeError, "The event handler supplied must be a python function"); return NULL; } // figure out what type of data our owner is if(PyOwner == Py_None) { owner = NULL; sprintf(otype, "none"); } else if(PyChar_Check(PyOwner)) { owner = PyChar_AsChar(PyOwner); sprintf(otype, "char"); } else if(PyRoom_Check(PyOwner)) { owner = PyRoom_AsRoom(PyOwner); sprintf(otype, "room"); } else if(PyObj_Check(PyOwner)) { owner = PyObj_AsObj(PyOwner); sprintf(otype, "obj"); } // invalid type else { PyErr_Format(PyExc_TypeError, "An event owner must be a room, char, obj, or none"); return NULL; } // make sure the owner exists if(PyOwner != Py_None && owner == NULL) { PyErr_Format(PyExc_StandardError, "Owner supplied does not exist in game"); return NULL; } // now, queue up the action start_func(owner, (int)(delay SECONDS), PyEvent_on_complete, NULL, Py_BuildValue("sOO", otype, efunc, edata), arg); // everything seems ok. exit normally return Py_BuildValue("i", 1); }
void PythonQtSignalTarget::call(void **arguments) const { // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal int numPythonArgs = -1; if (PyFunction_Check(_callable)) { PyObject* o = _callable; PyFunctionObject* func = (PyFunctionObject*)o; PyCodeObject* code = (PyCodeObject*)func->func_code; if (!(code->co_flags & 0x04)) { numPythonArgs = code->co_argcount; } else { // variable numbers of arguments allowed } } else if (PyMethod_Check(_callable)) { PyObject* o = _callable; PyMethodObject* method = (PyMethodObject*)o; if (PyFunction_Check(method->im_func)) { PyFunctionObject* func = (PyFunctionObject*)method->im_func; PyCodeObject* code = (PyCodeObject*)func->func_code; if (!(code->co_flags & 0x04)) { numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self" } else { // variable numbers of arguments allowed } } } const PythonQtMethodInfo* m = methodInfo(); // parameterCount includes return value: int count = m->parameterCount(); if (numPythonArgs!=-1) { if (count>numPythonArgs+1) { // take less arguments count = numPythonArgs+1; } } PyObject* pargs = NULL; if (count>1) { pargs = PyTuple_New(count-1); } bool err = false; // transform Qt values to Python const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters(); for (int i = 1; i < count; i++) { const PythonQtMethodInfo::ParameterInfo& param = params.at(i); PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]); if (arg) { // steals reference, no unref PyTuple_SetItem(pargs, i-1,arg); } else { err = true; break; } } if (!err) { PyErr_Clear(); PyObject* result = PyObject_CallObject(_callable, pargs); if (result) { // ok Py_DECREF(result); } else { PythonQt::self()->handleError(); } } if (pargs) { // free the arguments again Py_DECREF(pargs); } }
static gboolean gplp_func_desc_load (GOPluginService *service, char const *name, GnmFuncDescriptor *res) { ServiceLoaderDataFunctionGroup *loader_data; PyObject *fn_info_obj; g_return_val_if_fail (IS_GNM_PLUGIN_SERVICE_FUNCTION_GROUP (service), FALSE); g_return_val_if_fail (name != NULL, FALSE); loader_data = g_object_get_data (G_OBJECT (service), "loader_data"); SWITCH_TO_PLUGIN (go_plugin_service_get_plugin (service)); fn_info_obj = PyDict_GetItemString (loader_data->python_fn_info_dict, (gchar *) name); if (fn_info_obj == NULL) { gnm_python_clear_error_if_needed (SERVICE_GET_LOADER (service)->py_object); return FALSE; } if (PyTuple_Check (fn_info_obj)) { PyObject *python_args, *python_arg_names; PyObject *python_fn; if (PyTuple_Size (fn_info_obj) == 3 && (python_args = PyTuple_GetItem (fn_info_obj, 0)) != NULL && PyString_Check (python_args) && (python_arg_names = PyTuple_GetItem (fn_info_obj, 1)) != NULL && PyString_Check (python_arg_names) && (python_fn = PyTuple_GetItem (fn_info_obj, 2)) != NULL && PyFunction_Check (python_fn)) { res->arg_spec = PyString_AsString (python_args); #if 0 res->arg_names = PyString_AsString (python_arg_names); #endif res->help = python_function_get_gnumeric_help ( loader_data->python_fn_info_dict, python_fn, name); res->fn_args = &call_python_function_args; res->fn_nodes = NULL; res->linker = NULL; res->unlinker = NULL; res->impl_status = GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC; res->test_status = GNM_FUNC_TEST_STATUS_UNKNOWN; return TRUE; } gnm_python_clear_error_if_needed (SERVICE_GET_LOADER (service)->py_object); return FALSE; } if (PyFunction_Check (fn_info_obj)) { res->arg_spec = ""; res->help = python_function_get_gnumeric_help ( loader_data->python_fn_info_dict, fn_info_obj, name); res->fn_args = NULL; res->fn_nodes = &call_python_function_nodes; res->linker = NULL; res->unlinker = NULL; res->impl_status = GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC; res->test_status = GNM_FUNC_TEST_STATUS_UNKNOWN; return TRUE; } gnm_python_clear_error_if_needed (SERVICE_GET_LOADER (service)->py_object); return FALSE; }
// Get the receiver QObject from the slot (if there is one) and its signature // (if it wraps a Qt slot). A Python exception will be raised if there was an // error. static QObject *get_receiver(Chimera::Signature *overload, PyObject *slot_obj, QByteArray &name) { PyObject *rx_self, *decorations; QByteArray rx_name; bool try_qt_slot; decorations = 0; if (PyMethod_Check(slot_obj)) { rx_self = PyMethod_GET_SELF(slot_obj); PyObject *f = PyMethod_GET_FUNCTION(slot_obj); Q_ASSERT(PyFunction_Check(f)); PyObject *f_name_obj = ((PyFunctionObject *)f)->func_name; const char *f_name = sipString_AsASCIIString(&f_name_obj); Q_ASSERT(f_name); rx_name = f_name; Py_DECREF(f_name_obj); // See if this has been decorated. decorations = PyObject_GetAttr(f, qpycore_signature_attr_name); if (decorations) { try_qt_slot = true; // It's convenient to do this here as it's not going to disappear. Py_DECREF(decorations); } else { try_qt_slot = false; } } else if (PyCFunction_Check(slot_obj)) { rx_self = PyCFunction_GET_SELF(slot_obj); rx_name = ((PyCFunctionObject *)slot_obj)->m_ml->ml_name; // We actually want the C++ name which may (in theory) be completely // different. However this will cope with the exec_ case which is // probably good enough. if (rx_name.endsWith('_')) rx_name.chop(1); try_qt_slot = true; } else { rx_self = 0; } if (!rx_self) return 0; int iserr = 0; void *rx = sipForceConvertToType(rx_self, sipType_QObject, 0, SIP_NO_CONVERTORS, 0, &iserr); PyErr_Clear(); if (iserr) return 0; QObject *rx_qobj = reinterpret_cast<QObject *>(rx); // If there might be a Qt slot that can handle the arguments (or a subset // of them) then use it. Otherwise we will fallback to using a proxy. if (try_qt_slot) { for (int ol = overload->parsed_arguments.count(); ol >= 0; --ol) { // If there are decorations then we compare the signal's signature // against them so that we distinguish between Python types that // are passed to Qt as PyQt_PyObject objects. Qt will not make the // distinction. If there are no decorations then let Qt determine // if a slot is available. if (decorations) name = slot_signature_from_decorations(overload, decorations, ol); else name = slot_signature_from_metaobject(overload, rx_qobj->metaObject(), rx_name, ol); if (!name.isEmpty()) { // Prepend the magic slot marker. name.prepend('1'); break; } } } return rx_qobj; }
static char const *GET_CALLABLE_DESC( PyObject *object ) { if ( Nuitka_Function_Check( object ) || Nuitka_Generator_Check( object ) || PyMethod_Check( object ) || PyFunction_Check( object ) || PyCFunction_Check( object ) ) { return "()"; } #if PYTHON_VERSION < 300 else if ( PyClass_Check( object ) ) { return " constructor"; } else if ( PyInstance_Check( object )) { return " instance"; } #endif else { return " object"; } }