| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent fa46aa7 commit 9be7e7b
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -267,10 +267,26 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ | |||
| 267 | 267 | PyObject *args, PyObject *kw); | |
| 268 | 268 | ||
| 269 | 269 | #ifndef Py_LIMITED_API | |
| 270 | + PyAPI_FUNC(PyObject*) _PyStack_AsTuple(PyObject **stack, | ||
| 271 | + Py_ssize_t nargs); | ||
| 272 | + | ||
| 273 | + /* Call the callable object func with the "fast call" calling convention: | ||
| 274 | + args is a C array for positional parameters (nargs is the number of | ||
| 275 | + positional paramater), kwargs is a dictionary for keyword parameters. | ||
| 276 | + | ||
| 277 | + If nargs is equal to zero, args can be NULL. kwargs can be NULL. | ||
| 278 | + nargs must be greater or equal to zero. | ||
| 279 | + | ||
| 280 | + Return the result on success. Raise an exception on return NULL on | ||
| 281 | + error. */ | ||
| 282 | + PyAPI_FUNC(PyObject *) _PyObject_FastCall(PyObject *func, | ||
| 283 | + PyObject **args, int nargs, | ||
| 284 | + PyObject *kwargs); | ||
| 285 | + | ||
| 270 | 286 | PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *func, | |
| 271 | 287 | PyObject *result, | |
| 272 | 288 | const char *where); | |
| 273 | - #endif | ||
| 289 | + #endif /* Py_LIMITED_API */ | ||
| 274 | 290 | ||
| 275 | 291 | /* | |
| 276 | 292 | Call a callable Python object, callable_object, with | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -58,6 +58,13 @@ PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *); | |||
| 58 | 58 | PyAPI_FUNC(PyObject *) PyFunction_GetAnnotations(PyObject *); | |
| 59 | 59 | PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *); | |
| 60 | 60 | ||
| 61 | + #ifndef Py_LIMITED_API | ||
| 62 | + PyAPI_FUNC(PyObject *) _PyFunction_FastCall( | ||
| 63 | + PyObject *func, | ||
| 64 | + PyObject **args, int nargs, | ||
| 65 | + PyObject *kwargs); | ||
| 66 | + #endif | ||
| 67 | + | ||
| 61 | 68 | /* Macros for direct access to these values. Type checks are *not* | |
| 62 | 69 | done, so use with care. */ | |
| 63 | 70 | #define PyFunction_GET_CODE(func) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -37,6 +37,12 @@ PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *); | |||
| 37 | 37 | #endif | |
| 38 | 38 | PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); | |
| 39 | 39 | ||
| 40 | + #ifndef Py_LIMITED_API | ||
| 41 | + PyAPI_FUNC(PyObject *) _PyCFunction_FastCall(PyObject *func, | ||
| 42 | + PyObject **args, int nargs, | ||
| 43 | + PyObject *kwargs); | ||
| 44 | + #endif | ||
| 45 | + | ||
| 40 | 46 | struct PyMethodDef { | |
| 41 | 47 | const char *ml_name; /* The name of the built-in function/method */ | |
| 42 | 48 | PyCFunction ml_meth; /* The C function that implements it */ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2193,6 +2193,82 @@ PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) | |||
| 2193 | 2193 | return _Py_CheckFunctionResult(func, result, NULL); | |
| 2194 | 2194 | } | |
| 2195 | 2195 | ||
| 2196 | + PyObject* | ||
| 2197 | + _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs) | ||
| 2198 | + { | ||
| 2199 | + PyObject *args; | ||
| 2200 | + Py_ssize_t i; | ||
| 2201 | + | ||
| 2202 | + args = PyTuple_New(nargs); | ||
| 2203 | + if (args == NULL) { | ||
| 2204 | + return NULL; | ||
| 2205 | + } | ||
| 2206 | + | ||
| 2207 | + for (i=0; i < nargs; i++) { | ||
| 2208 | + PyObject *item = stack[i]; | ||
| 2209 | + Py_INCREF(item); | ||
| 2210 | + PyTuple_SET_ITEM(args, i, item); | ||
| 2211 | + } | ||
| 2212 | + | ||
| 2213 | + return args; | ||
| 2214 | + } | ||
| 2215 | + | ||
| 2216 | + PyObject * | ||
| 2217 | + _PyObject_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwargs) | ||
| 2218 | + { | ||
| 2219 | + ternaryfunc call; | ||
| 2220 | + PyObject *result = NULL; | ||
| 2221 | + | ||
| 2222 | + /* _PyObject_FastCall() must not be called with an exception set, | ||
| 2223 | + because it may clear it (directly or indirectly) and so the | ||
| 2224 | + caller loses its exception */ | ||
| 2225 | + assert(!PyErr_Occurred()); | ||
| 2226 | + | ||
| 2227 | + assert(func != NULL); | ||
| 2228 | + assert(nargs >= 0); | ||
| 2229 | + assert(nargs == 0 || args != NULL); | ||
| 2230 | + /* issue #27128: support for keywords will come later: | ||
| 2231 | + _PyFunction_FastCall() doesn't support keyword arguments yet */ | ||
| 2232 | + assert(kwargs == NULL); | ||
| 2233 | + | ||
| 2234 | + if (Py_EnterRecursiveCall(" while calling a Python object")) { | ||
| 2235 | + return NULL; | ||
| 2236 | + } | ||
| 2237 | + | ||
| 2238 | + if (PyFunction_Check(func)) { | ||
| 2239 | + result = _PyFunction_FastCall(func, args, nargs, kwargs); | ||
| 2240 | + } | ||
| 2241 | + else if (PyCFunction_Check(func)) { | ||
| 2242 | + result = _PyCFunction_FastCall(func, args, nargs, kwargs); | ||
| 2243 | + } | ||
| 2244 | + else { | ||
| 2245 | + PyObject *tuple; | ||
| 2246 | + | ||
| 2247 | + /* Slow-path: build a temporary tuple */ | ||
| 2248 | + call = func->ob_type->tp_call; | ||
| 2249 | + if (call == NULL) { | ||
| 2250 | + PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", | ||
| 2251 | + func->ob_type->tp_name); | ||
| 2252 | + goto exit; | ||
| 2253 | + } | ||
| 2254 | + | ||
| 2255 | + tuple = _PyStack_AsTuple(args, nargs); | ||
| 2256 | + if (tuple == NULL) { | ||
| 2257 | + goto exit; | ||
| 2258 | + } | ||
| 2259 | + | ||
| 2260 | + result = (*call)(func, tuple, kwargs); | ||
| 2261 | + Py_DECREF(tuple); | ||
| 2262 | + } | ||
| 2263 | + | ||
| 2264 | + result = _Py_CheckFunctionResult(func, result, NULL); | ||
| 2265 | + | ||
| 2266 | + exit: | ||
| 2267 | + Py_LeaveRecursiveCall(); | ||
| 2268 | + | ||
| 2269 | + return result; | ||
| 2270 | + } | ||
| 2271 | + | ||
| 2196 | 2272 | static PyObject* | |
| 2197 | 2273 | call_function_tail(PyObject *callable, PyObject *args) | |
| 2198 | 2274 | { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -145,6 +145,99 @@ PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds) | |||
| 145 | 145 | return _Py_CheckFunctionResult(func, res, NULL); | |
| 146 | 146 | } | |
| 147 | 147 | ||
| 148 | + PyObject * | ||
| 149 | + _PyCFunction_FastCall(PyObject *func_obj, PyObject **args, int nargs, | ||
| 150 | + PyObject *kwargs) | ||
| 151 | + { | ||
| 152 | + PyCFunctionObject* func = (PyCFunctionObject*)func_obj; | ||
| 153 | + PyCFunction meth = PyCFunction_GET_FUNCTION(func); | ||
| 154 | + PyObject *self = PyCFunction_GET_SELF(func); | ||
| 155 | + PyObject *result; | ||
| 156 | + int flags; | ||
| 157 | + | ||
| 158 | + /* _PyCFunction_FastCall() must not be called with an exception set, | ||
| 159 | + because it may clear it (directly or indirectly) and so the | ||
| 160 | + caller loses its exception */ | ||
| 161 | + assert(!PyErr_Occurred()); | ||
| 162 | + | ||
| 163 | + flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); | ||
| 164 | + | ||
| 165 | + switch (flags) | ||
| 166 | + { | ||
| 167 | + case METH_NOARGS: | ||
| 168 | + if (kwargs != NULL && PyDict_Size(kwargs) != 0) { | ||
| 169 | + PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", | ||
| 170 | + func->m_ml->ml_name); | ||
| 171 | + return NULL; | ||
| 172 | + } | ||
| 173 | + | ||
| 174 | + if (nargs != 0) { | ||
| 175 | + PyErr_Format(PyExc_TypeError, | ||
| 176 | + "%.200s() takes no arguments (%zd given)", | ||
| 177 | + func->m_ml->ml_name, nargs); | ||
| 178 | + return NULL; | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + result = (*meth) (self, NULL); | ||
| 182 | + break; | ||
| 183 | + | ||
| 184 | + case METH_O: | ||
| 185 | + if (kwargs != NULL && PyDict_Size(kwargs) != 0) { | ||
| 186 | + PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", | ||
| 187 | + func->m_ml->ml_name); | ||
| 188 | + return NULL; | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + if (nargs != 1) { | ||
| 192 | + PyErr_Format(PyExc_TypeError, | ||
| 193 | + "%.200s() takes exactly one argument (%zd given)", | ||
| 194 | + func->m_ml->ml_name, nargs); | ||
| 195 | + return NULL; | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + result = (*meth) (self, args[0]); | ||
| 199 | + break; | ||
| 200 | + | ||
| 201 | + case METH_VARARGS: | ||
| 202 | + case METH_VARARGS | METH_KEYWORDS: | ||
| 203 | + { | ||
| 204 | + /* Slow-path: create a temporary tuple */ | ||
| 205 | + PyObject *tuple; | ||
| 206 | + | ||
| 207 | + if (!(flags & METH_KEYWORDS) && kwargs != NULL && PyDict_Size(kwargs) != 0) { | ||
| 208 | + PyErr_Format(PyExc_TypeError, | ||
| 209 | + "%.200s() takes no keyword arguments", | ||
| 210 | + func->m_ml->ml_name); | ||
| 211 | + return NULL; | ||
| 212 | + } | ||
| 213 | + | ||
| 214 | + tuple = _PyStack_AsTuple(args, nargs); | ||
| 215 | + if (tuple == NULL) { | ||
| 216 | + return NULL; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + if (flags & METH_KEYWORDS) { | ||
| 220 | + result = (*(PyCFunctionWithKeywords)meth) (self, tuple, kwargs); | ||
| 221 | + } | ||
| 222 | + else { | ||
| 223 | + result = (*meth) (self, tuple); | ||
| 224 | + } | ||
| 225 | + Py_DECREF(tuple); | ||
| 226 | + break; | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + default: | ||
| 230 | + PyErr_SetString(PyExc_SystemError, | ||
| 231 | + "Bad call flags in PyCFunction_Call. " | ||
| 232 | + "METH_OLDARGS is no longer supported!"); | ||
| 233 | + return NULL; | ||
| 234 | + } | ||
| 235 | + | ||
| 236 | + result = _Py_CheckFunctionResult(func_obj, result, NULL); | ||
| 237 | + | ||
| 238 | + return result; | ||
| 239 | + } | ||
| 240 | + | ||
| 148 | 241 | /* Methods (the standard built-in methods, that is) */ | |
| 149 | 242 | ||
| 150 | 243 | static void | |
| Back | FazBrowse Home | New Git URL |
0 commit comments