/* A custom, fast, inlinable version of PyCFunction_Call() */ static PyObject * call_cfunc(DispatcherObject *self, PyObject *cfunc, PyObject *args, PyObject *kws, PyObject *locals) { PyCFunctionWithKeywords fn; PyThreadState *tstate; assert(PyCFunction_Check(cfunc)); assert(PyCFunction_GET_FLAGS(cfunc) == METH_VARARGS | METH_KEYWORDS); fn = (PyCFunctionWithKeywords) PyCFunction_GET_FUNCTION(cfunc); tstate = PyThreadState_GET(); if (tstate->use_tracing && tstate->c_profilefunc) { /* * The following code requires some explaining: * * We want the jit-compiled function to be visible to the profiler, so we * need to synthesize a frame for it. * The PyFrame_New() constructor doesn't do anything with the 'locals' value if the 'code's * 'CO_NEWLOCALS' flag is set (which is always the case nowadays). * So, to get local variables into the frame, we have to manually set the 'f_locals' * member, then call `PyFrame_LocalsToFast`, where a subsequent call to the `frame.f_locals` * property (by virtue of the `frame_getlocals` function in frameobject.c) will find them. */ PyCodeObject *code = (PyCodeObject*)PyObject_GetAttrString((PyObject*)self, "__code__"); PyObject *globals = PyDict_New(); PyObject *builtins = PyEval_GetBuiltins(); PyFrameObject *frame = NULL; PyObject *result = NULL; if (!code) { PyErr_Format(PyExc_RuntimeError, "No __code__ attribute found."); goto error; } /* Populate builtins, which is required by some JITted functions */ if (PyDict_SetItemString(globals, "__builtins__", builtins)) { goto error; } frame = PyFrame_New(tstate, code, globals, NULL); if (frame == NULL) { goto error; } /* Populate the 'fast locals' in `frame` */ Py_XDECREF(frame->f_locals); frame->f_locals = locals; Py_XINCREF(frame->f_locals); PyFrame_LocalsToFast(frame, 0); tstate->frame = frame; C_TRACE(result, fn(PyCFunction_GET_SELF(cfunc), args, kws)); tstate->frame = frame->f_back; error: Py_XDECREF(frame); Py_XDECREF(globals); Py_XDECREF(code); return result; } else return fn(PyCFunction_GET_SELF(cfunc), args, kws); }
static bool getReceiver(QObject *source, PyObject* callback, QObject** receiver, PyObject** self) { bool forceGlobalReceiver = false; if (PyMethod_Check(callback)) { *self = PyMethod_GET_SELF(callback); if (Shiboken::Converter<QObject*>::checkType(*self)) *receiver = Shiboken::Converter<QObject*>::toCpp(*self); forceGlobalReceiver = isDecorator(callback, *self); } else if (PyCFunction_Check(callback)) { *self = PyCFunction_GET_SELF(callback); if (*self && Shiboken::Converter<QObject*>::checkType(*self)) *receiver = Shiboken::Converter<QObject*>::toCpp(*self); } else if (PyCallable_Check(callback)) { // Ok, just a callable object *receiver = 0; *self = 0; } bool usingGlobalReceiver = !*receiver || forceGlobalReceiver; if (usingGlobalReceiver) { PySide::SignalManager& signalManager = PySide::SignalManager::instance(); *receiver = signalManager.globalReceiver(source, callback); } return usingGlobalReceiver; }
SlotConnectorBase::SlotConnectorBase(PyObject* slot, int n_sig_args) { function = 0; klass = 0; PyObject* instance = 0; cfunction = 0; if (PyMethod_Check(slot)) { instance = PyMethod_GET_SELF(slot); klass = PyMethod_GET_CLASS(slot); function = PyMethod_GET_FUNCTION(slot); Py_INCREF(klass); Py_INCREF(function); PyObject* func_code = PyObject_GetAttrString(function, "func_code"); PyObject* co_argcount = PyObject_GetAttrString(func_code, "co_argcount"); n_slot_args = PyInt_AsLong(co_argcount)-1; if (n_slot_args == -1) { PyErr_SetString(PyExc_TypeError, "Slot method should at least have a 'self' argument"); return; } core = ((Wt::WObject*)(((PyCPPClassInstance*)instance)->proxy->getCoreAsVoid())); Py_DECREF(func_code); Py_DECREF(co_argcount); } else if PyCFunction_Check(slot) { instance = PyCFunction_GET_SELF(slot); cfunction = PyCFunction_GET_FUNCTION(slot); flags = PyCFunction_GET_FLAGS(slot); n_slot_args = PyCFunction_GET_NARGS(slot); core = ((Wt::WObject*)(((PyCPPClassInstance*)instance)->proxy->getCoreAsVoid())); } else {
PyObject * PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); Py_ssize_t size; switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) return (*meth)(self, arg); break; case METH_VARARGS | METH_KEYWORDS: case METH_OLDARGS | METH_KEYWORDS: return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 0) return (*meth)(self, NULL); PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); return NULL; } break; case METH_O: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) return (*meth)(self, PyTuple_GET_ITEM(arg, 0)); PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); return NULL; } break; case METH_OLDARGS: /* the really old style */ if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) arg = PyTuple_GET_ITEM(arg, 0); else if (size == 0) arg = NULL; return (*meth)(self, arg); } break; default: PyErr_BadInternalCall(); return NULL; } PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; }
PyObject * PyCFunction_GetSelf(PyObject *op) { if (!PyCFunction_Check(op)) { PyErr_BadInternalCall(); return NULL; } return PyCFunction_GET_SELF(op); }
static PyObject * meth_get__self__(PyCFunctionObject *m, void *closure) { PyObject *self; self = PyCFunction_GET_SELF(m); if (self == NULL) self = Py_None; Py_INCREF(self); return self; }
PyObject * PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); Py_ssize_t size; switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) return (*meth)(self, arg); break; case METH_VARARGS | METH_KEYWORDS: return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 0) return (*meth)(self, NULL); PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); return NULL; } break; case METH_O: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) return (*meth)(self, PyTuple_GET_ITEM(arg, 0)); PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); return NULL; } break; default: PyErr_SetString(PyExc_SystemError, "Bad call flags in " "PyCFunction_Call. METH_OLDARGS is no " "longer supported!"); return NULL; } PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; }
/* * Compare two slots to see if they are the same. */ int sip_api_same_slot(const sipSlot *sp, PyObject *rxObj, const char *slot) { assert(sipQtSupport); assert(sipQtSupport->qt_same_name); /* See if they are signals or Qt slots, ie. they have a name. */ if (slot != NULL) { if (sp->name == NULL || sp->name[0] == '\0') return 0; return (sipQtSupport->qt_same_name(sp->name, slot) && sp->pyobj == rxObj); } /* See if they are pure Python methods. */ if (PyMethod_Check(rxObj)) { if (sp->pyobj != NULL) return 0; return (sp->meth.mfunc == PyMethod_GET_FUNCTION(rxObj) && sp->meth.mself == PyMethod_GET_SELF(rxObj) #if PY_MAJOR_VERSION < 3 && sp->meth.mclass == PyMethod_GET_CLASS(rxObj) #endif ); } /* See if they are wrapped C++ methods. */ if (PyCFunction_Check(rxObj)) { if (sp->name == NULL || sp->name[0] != '\0') return 0; return (sp->pyobj == PyCFunction_GET_SELF(rxObj) && strcmp(&sp->name[1], ((PyCFunctionObject *)rxObj)->m_ml->ml_name) == 0); } /* The objects must be the same. */ return (sp->pyobj == rxObj); }
/* * Initialise a slot, returning 0 if there was no error. If the signal was a * Qt signal, then the slot may be a Python signal or a Python slot. If the * signal was a Python signal, then the slot may be anything. */ int sip_api_save_slot(sipSlot *sp, PyObject *rxObj, const char *slot) { sp -> weakSlot = NULL; if (slot == NULL) { sp -> name = NULL; if (PyMethod_Check(rxObj)) { /* * Python creates methods on the fly. We could increment the * reference count to keep it alive, but that would keep "self" * alive as well and would probably be a circular reference. * Instead we remember the component parts and hope they are still * valid when we re-create the method when we need it. */ sipSaveMethod(&sp -> meth,rxObj); /* Notice if the class instance disappears. */ sp -> weakSlot = getWeakRef(sp -> meth.mself); /* This acts a flag to say that the slot is a method. */ sp -> pyobj = NULL; } else { PyObject *self; /* * We know that it is another type of callable, ie. a * function/builtin. */ if (PyCFunction_Check(rxObj) && (self = PyCFunction_GET_SELF(rxObj)) != NULL && PyObject_TypeCheck(self, (PyTypeObject *)&sipSimpleWrapper_Type)) { /* * It is a wrapped C++ class method. We can't keep a copy * because they are generated on the fly and we can't take a * reference as that may keep the instance (ie. self) alive. * We therefore treat it as if the user had specified the slot * at "obj, SLOT('meth()')" rather than "obj.meth" (see below). */ const char *meth; /* Get the method name. */ meth = ((PyCFunctionObject *)rxObj) -> m_ml -> ml_name; if ((sp -> name = (char *)sip_api_malloc(strlen(meth) + 2)) == NULL) return -1; /* * Copy the name and set the marker that it needs converting to * a built-in method. */ sp -> name[0] = '\0'; strcpy(&sp -> name[1],meth); sp -> pyobj = self; sp -> weakSlot = getWeakRef(self); } else { /* * Give the slot an extra reference to keep it alive and * remember we have done so by treating weakSlot specially. */ Py_INCREF(rxObj); sp->pyobj = rxObj; Py_INCREF(Py_True); sp->weakSlot = Py_True; } } } else if ((sp -> name = sipStrdup(slot)) == NULL) return -1; else if (isQtSlot(slot)) { /* * The user has decided to connect a Python signal to a Qt slot and * specified the slot as "obj, SLOT('meth()')" rather than "obj.meth". */ char *tail; /* Remove any arguments. */ if ((tail = strchr(sp -> name,'(')) != NULL) *tail = '\0'; /* * A bit of a hack to indicate that this needs converting to a built-in * method. */ sp -> name[0] = '\0'; /* Notice if the class instance disappears. */ sp -> weakSlot = getWeakRef(rxObj); sp -> pyobj = rxObj; } else /* It's a Qt signal. */ sp -> pyobj = rxObj; return 0; }
static PyObject * call_function(PyObject ***pp_stack, int oparg) { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; int n = na + 2 * nk; PyObject **pfunc = (*pp_stack) - n - 1; PyObject *func = *pfunc; PyObject *x, *w; /* Always dispatch PyCFunction first, because these are presumed to be the most frequent callable object. */ if (PyCFunction_Check(func) && nk == 0) { int flags = PyCFunction_GET_FLAGS(func); if (flags & (METH_NOARGS | METH_O)) { PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); if (flags & METH_NOARGS && na == 0) x = (*meth)(self, NULL); else if (flags & METH_O && na == 1) { PyObject *arg = EXT_POP(*pp_stack); x = (*meth)(self, arg); Py_DECREF(arg); } else { err_args(func, flags, na); x = NULL; } } else { PyObject *callargs; callargs = load_args(pp_stack, na); x = PyCFunction_Call(func, callargs, NULL); Py_XDECREF(callargs); } } else { if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) { /* optimize access to bound methods */ PyObject *self = PyMethod_GET_SELF(func); Py_INCREF(self); func = PyMethod_GET_FUNCTION(func); Py_INCREF(func); Py_DECREF(*pfunc); *pfunc = self; na++; n++; } else Py_INCREF(func); if (PyFunction_Check(func)) x = fast_function(func, pp_stack, n, na, nk); else x = do_call(func, pp_stack, na, nk); Py_DECREF(func); } /* What does this do? */ while ((*pp_stack) > pfunc) { w = EXT_POP(*pp_stack); Py_DECREF(w); } return x; }
// 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; }
PyObject * PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); Py_ssize_t size; switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) return (*meth)(self, arg); break; case METH_VARARGS | METH_KEYWORDS: case METH_OLDARGS | METH_KEYWORDS: return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); case METH_ARG_RANGE: { if (kw == NULL || PyDict_Size(kw) == 0) { PyObject *args[PY_MAX_ARITY] = {NULL}; int min_arity = PyCFunction_GET_MIN_ARITY(func); int max_arity = PyCFunction_GET_MAX_ARITY(func); size = PyTuple_GET_SIZE(arg); switch (size) { default: PyErr_BadInternalCall(); return NULL; case 3: args[2] = PyTuple_GET_ITEM(arg, 2); case 2: args[1] = PyTuple_GET_ITEM(arg, 1); case 1: args[0] = PyTuple_GET_ITEM(arg, 0); case 0: break; } /* But wait, you ask, what about {un,bin}ary functions? Aren't we passing more arguments than it expects? Yes, but C allows this. Go C. */ if (min_arity <= size && size <= max_arity) return (*(PyCFunctionThreeArgs)meth) (self, args[0], args[1], args[2]); if (max_arity == min_arity) PyErr_Format(PyExc_TypeError, "%.200s() takes exactly %d argument(s)" " (%zd given)", f->m_ml->ml_name, max_arity, size); else PyErr_Format(PyExc_TypeError, "%.200s() takes %d-%d arguments" " (%zd given)", f->m_ml->ml_name, min_arity, max_arity, size); return NULL; } break; } case METH_OLDARGS: /* the really old style */ if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) arg = PyTuple_GET_ITEM(arg, 0); else if (size == 0) arg = NULL; return (*meth)(self, arg); } break; /* METH_O is deprecated; PyCFunction_NewEx is supposed to convert it to METH_ARG_RANGE and set ml_{min,max}_arity correctly. */ case METH_O: default: PyErr_BadInternalCall(); return NULL; } PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; }
// 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; }
PyObject * PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds) { PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); PyObject *arg, *res; Py_ssize_t size; int flags; /* PyCFunction_Call() must not be called with an exception set, because it may clear it (directly or indirectly) and so the caller loses its exception */ assert(!PyErr_Occurred()); flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); if (flags == (METH_VARARGS | METH_KEYWORDS)) { res = (*(PyCFunctionWithKeywords)meth)(self, args, kwds); } else { if (kwds != NULL && PyDict_Size(kwds) != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; } switch (flags) { case METH_VARARGS: res = (*meth)(self, args); break; case METH_NOARGS: size = PyTuple_GET_SIZE(args); if (size != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); return NULL; } res = (*meth)(self, NULL); break; case METH_O: size = PyTuple_GET_SIZE(args); if (size != 1) { PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); return NULL; } arg = PyTuple_GET_ITEM(args, 0); res = (*meth)(self, arg); break; default: PyErr_SetString(PyExc_SystemError, "Bad call flags in PyCFunction_Call. " "METH_OLDARGS is no longer supported!"); return NULL; } } return _Py_CheckFunctionResult(func, res, NULL); }
PyObject * PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { STACKLESS_GETARG(); PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); Py_ssize_t size; #ifdef STACKLESS switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS)) { #else switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { #endif case METH_VARARGS: if (kw == NULL || PyDict_Size(kw) == 0) WRAP_RETURN( (*meth)(self, arg) ) break; case METH_VARARGS | METH_KEYWORDS: WRAP_RETURN( (*(PyCFunctionWithKeywords)meth)(self, arg, kw) ) case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 0) WRAP_RETURN( (*meth)(self, NULL) ) PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); return NULL; } break; case METH_O: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); if (size == 1) WRAP_RETURN( (*meth)(self, PyTuple_GET_ITEM(arg, 0)) ) PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); return NULL; } break; default: PyErr_SetString(PyExc_SystemError, "Bad call flags in " "PyCFunction_Call. METH_OLDARGS is no " "longer supported!"); return NULL; } PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; } /* Methods (the standard built-in methods, that is) */ static void meth_dealloc(PyCFunctionObject *m) { _PyObject_GC_UNTRACK(m); Py_XDECREF(m->m_self); Py_XDECREF(m->m_module); if (numfree < PyCFunction_MAXFREELIST) { m->m_self = (PyObject *)free_list; free_list = m; numfree++; } else { PyObject_GC_Del(m); } }