PageRenderTime 51ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/cpython/Objects/methodobject.c

https://github.com/replit/empythoned
C | 427 lines | 370 code | 41 blank | 16 comment | 101 complexity | 3138d115b44f10667109d82f89255efb MD5 | raw file
  1. /* Method object implementation */
  2. #include "Python.h"
  3. #include "structmember.h"
  4. /* Free list for method objects to safe malloc/free overhead
  5. * The m_self element is used to chain the objects.
  6. */
  7. static PyCFunctionObject *free_list = NULL;
  8. static int numfree = 0;
  9. #ifndef PyCFunction_MAXFREELIST
  10. #define PyCFunction_MAXFREELIST 256
  11. #endif
  12. PyObject *
  13. PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
  14. {
  15. PyCFunctionObject *op;
  16. op = free_list;
  17. if (op != NULL) {
  18. free_list = (PyCFunctionObject *)(op->m_self);
  19. PyObject_INIT(op, &PyCFunction_Type);
  20. numfree--;
  21. }
  22. else {
  23. op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
  24. if (op == NULL)
  25. return NULL;
  26. }
  27. op->m_ml = ml;
  28. Py_XINCREF(self);
  29. op->m_self = self;
  30. Py_XINCREF(module);
  31. op->m_module = module;
  32. _PyObject_GC_TRACK(op);
  33. return (PyObject *)op;
  34. }
  35. PyCFunction
  36. PyCFunction_GetFunction(PyObject *op)
  37. {
  38. if (!PyCFunction_Check(op)) {
  39. PyErr_BadInternalCall();
  40. return NULL;
  41. }
  42. return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
  43. }
  44. PyObject *
  45. PyCFunction_GetSelf(PyObject *op)
  46. {
  47. if (!PyCFunction_Check(op)) {
  48. PyErr_BadInternalCall();
  49. return NULL;
  50. }
  51. return ((PyCFunctionObject *)op) -> m_self;
  52. }
  53. int
  54. PyCFunction_GetFlags(PyObject *op)
  55. {
  56. if (!PyCFunction_Check(op)) {
  57. PyErr_BadInternalCall();
  58. return -1;
  59. }
  60. return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
  61. }
  62. PyObject *
  63. PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
  64. {
  65. PyCFunctionObject* f = (PyCFunctionObject*)func;
  66. PyCFunction meth = PyCFunction_GET_FUNCTION(func);
  67. PyObject *self = PyCFunction_GET_SELF(func);
  68. Py_ssize_t size;
  69. switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
  70. case METH_VARARGS:
  71. if (kw == NULL || PyDict_Size(kw) == 0)
  72. return (*meth)(self, arg);
  73. break;
  74. case METH_VARARGS | METH_KEYWORDS:
  75. case METH_OLDARGS | METH_KEYWORDS:
  76. return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
  77. case METH_NOARGS:
  78. if (kw == NULL || PyDict_Size(kw) == 0) {
  79. size = PyTuple_GET_SIZE(arg);
  80. if (size == 0)
  81. return (*meth)(self, NULL);
  82. PyErr_Format(PyExc_TypeError,
  83. "%.200s() takes no arguments (%zd given)",
  84. f->m_ml->ml_name, size);
  85. return NULL;
  86. }
  87. break;
  88. case METH_O:
  89. if (kw == NULL || PyDict_Size(kw) == 0) {
  90. size = PyTuple_GET_SIZE(arg);
  91. if (size == 1)
  92. return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
  93. PyErr_Format(PyExc_TypeError,
  94. "%.200s() takes exactly one argument (%zd given)",
  95. f->m_ml->ml_name, size);
  96. return NULL;
  97. }
  98. break;
  99. case METH_OLDARGS:
  100. /* the really old style */
  101. if (kw == NULL || PyDict_Size(kw) == 0) {
  102. size = PyTuple_GET_SIZE(arg);
  103. if (size == 1)
  104. arg = PyTuple_GET_ITEM(arg, 0);
  105. else if (size == 0)
  106. arg = NULL;
  107. return (*meth)(self, arg);
  108. }
  109. break;
  110. default:
  111. PyErr_BadInternalCall();
  112. return NULL;
  113. }
  114. PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
  115. f->m_ml->ml_name);
  116. return NULL;
  117. }
  118. /* Methods (the standard built-in methods, that is) */
  119. static void
  120. meth_dealloc(PyCFunctionObject *m)
  121. {
  122. _PyObject_GC_UNTRACK(m);
  123. Py_XDECREF(m->m_self);
  124. Py_XDECREF(m->m_module);
  125. if (numfree < PyCFunction_MAXFREELIST) {
  126. m->m_self = (PyObject *)free_list;
  127. free_list = m;
  128. numfree++;
  129. }
  130. else {
  131. PyObject_GC_Del(m);
  132. }
  133. }
  134. static PyObject *
  135. meth_get__doc__(PyCFunctionObject *m, void *closure)
  136. {
  137. const char *doc = m->m_ml->ml_doc;
  138. if (doc != NULL)
  139. return PyString_FromString(doc);
  140. Py_INCREF(Py_None);
  141. return Py_None;
  142. }
  143. static PyObject *
  144. meth_get__name__(PyCFunctionObject *m, void *closure)
  145. {
  146. return PyString_FromString(m->m_ml->ml_name);
  147. }
  148. static int
  149. meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
  150. {
  151. Py_VISIT(m->m_self);
  152. Py_VISIT(m->m_module);
  153. return 0;
  154. }
  155. static PyObject *
  156. meth_get__self__(PyCFunctionObject *m, void *closure)
  157. {
  158. PyObject *self;
  159. if (PyEval_GetRestricted()) {
  160. PyErr_SetString(PyExc_RuntimeError,
  161. "method.__self__ not accessible in restricted mode");
  162. return NULL;
  163. }
  164. self = m->m_self;
  165. if (self == NULL)
  166. self = Py_None;
  167. Py_INCREF(self);
  168. return self;
  169. }
  170. static PyGetSetDef meth_getsets [] = {
  171. {"__doc__", (getter)meth_get__doc__, NULL, NULL},
  172. {"__name__", (getter)meth_get__name__, NULL, NULL},
  173. {"__self__", (getter)meth_get__self__, NULL, NULL},
  174. {0}
  175. };
  176. #define OFF(x) offsetof(PyCFunctionObject, x)
  177. static PyMemberDef meth_members[] = {
  178. {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
  179. {NULL}
  180. };
  181. static PyObject *
  182. meth_repr(PyCFunctionObject *m)
  183. {
  184. if (m->m_self == NULL)
  185. return PyString_FromFormat("<built-in function %s>",
  186. m->m_ml->ml_name);
  187. return PyString_FromFormat("<built-in method %s of %s object at %p>",
  188. m->m_ml->ml_name,
  189. m->m_self->ob_type->tp_name,
  190. m->m_self);
  191. }
  192. static int
  193. meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
  194. {
  195. if (a->m_self != b->m_self)
  196. return (a->m_self < b->m_self) ? -1 : 1;
  197. if (a->m_ml->ml_meth == b->m_ml->ml_meth)
  198. return 0;
  199. if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
  200. return -1;
  201. else
  202. return 1;
  203. }
  204. static PyObject *
  205. meth_richcompare(PyObject *self, PyObject *other, int op)
  206. {
  207. PyCFunctionObject *a, *b;
  208. PyObject *res;
  209. int eq;
  210. if (op != Py_EQ && op != Py_NE) {
  211. /* Py3K warning if comparison isn't == or !=. */
  212. if (PyErr_WarnPy3k("builtin_function_or_method order "
  213. "comparisons not supported in 3.x", 1) < 0) {
  214. return NULL;
  215. }
  216. Py_INCREF(Py_NotImplemented);
  217. return Py_NotImplemented;
  218. }
  219. else if (!PyCFunction_Check(self) || !PyCFunction_Check(other)) {
  220. Py_INCREF(Py_NotImplemented);
  221. return Py_NotImplemented;
  222. }
  223. a = (PyCFunctionObject *)self;
  224. b = (PyCFunctionObject *)other;
  225. eq = a->m_self == b->m_self;
  226. if (eq)
  227. eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
  228. if (op == Py_EQ)
  229. res = eq ? Py_True : Py_False;
  230. else
  231. res = eq ? Py_False : Py_True;
  232. Py_INCREF(res);
  233. return res;
  234. }
  235. static long
  236. meth_hash(PyCFunctionObject *a)
  237. {
  238. long x,y;
  239. if (a->m_self == NULL)
  240. x = 0;
  241. else {
  242. x = PyObject_Hash(a->m_self);
  243. if (x == -1)
  244. return -1;
  245. }
  246. y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
  247. if (y == -1)
  248. return -1;
  249. x ^= y;
  250. if (x == -1)
  251. x = -2;
  252. return x;
  253. }
  254. PyTypeObject PyCFunction_Type = {
  255. PyVarObject_HEAD_INIT(&PyType_Type, 0)
  256. "builtin_function_or_method",
  257. sizeof(PyCFunctionObject),
  258. 0,
  259. (destructor)meth_dealloc, /* tp_dealloc */
  260. 0, /* tp_print */
  261. 0, /* tp_getattr */
  262. 0, /* tp_setattr */
  263. (cmpfunc)meth_compare, /* tp_compare */
  264. (reprfunc)meth_repr, /* tp_repr */
  265. 0, /* tp_as_number */
  266. 0, /* tp_as_sequence */
  267. 0, /* tp_as_mapping */
  268. (hashfunc)meth_hash, /* tp_hash */
  269. PyCFunction_Call, /* tp_call */
  270. 0, /* tp_str */
  271. PyObject_GenericGetAttr, /* tp_getattro */
  272. 0, /* tp_setattro */
  273. 0, /* tp_as_buffer */
  274. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
  275. 0, /* tp_doc */
  276. (traverseproc)meth_traverse, /* tp_traverse */
  277. 0, /* tp_clear */
  278. meth_richcompare, /* tp_richcompare */
  279. 0, /* tp_weaklistoffset */
  280. 0, /* tp_iter */
  281. 0, /* tp_iternext */
  282. 0, /* tp_methods */
  283. meth_members, /* tp_members */
  284. meth_getsets, /* tp_getset */
  285. 0, /* tp_base */
  286. 0, /* tp_dict */
  287. };
  288. /* List all methods in a chain -- helper for findmethodinchain */
  289. static PyObject *
  290. listmethodchain(PyMethodChain *chain)
  291. {
  292. PyMethodChain *c;
  293. PyMethodDef *ml;
  294. int i, n;
  295. PyObject *v;
  296. n = 0;
  297. for (c = chain; c != NULL; c = c->link) {
  298. for (ml = c->methods; ml->ml_name != NULL; ml++)
  299. n++;
  300. }
  301. v = PyList_New(n);
  302. if (v == NULL)
  303. return NULL;
  304. i = 0;
  305. for (c = chain; c != NULL; c = c->link) {
  306. for (ml = c->methods; ml->ml_name != NULL; ml++) {
  307. PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
  308. i++;
  309. }
  310. }
  311. if (PyErr_Occurred()) {
  312. Py_DECREF(v);
  313. return NULL;
  314. }
  315. PyList_Sort(v);
  316. return v;
  317. }
  318. /* Find a method in a method chain */
  319. PyObject *
  320. Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
  321. {
  322. if (name[0] == '_' && name[1] == '_') {
  323. if (strcmp(name, "__methods__") == 0) {
  324. if (PyErr_WarnPy3k("__methods__ not supported in 3.x",
  325. 1) < 0)
  326. return NULL;
  327. return listmethodchain(chain);
  328. }
  329. if (strcmp(name, "__doc__") == 0) {
  330. const char *doc = self->ob_type->tp_doc;
  331. if (doc != NULL)
  332. return PyString_FromString(doc);
  333. }
  334. }
  335. while (chain != NULL) {
  336. PyMethodDef *ml = chain->methods;
  337. for (; ml->ml_name != NULL; ml++) {
  338. if (name[0] == ml->ml_name[0] &&
  339. strcmp(name+1, ml->ml_name+1) == 0)
  340. /* XXX */
  341. return PyCFunction_New(ml, self);
  342. }
  343. chain = chain->link;
  344. }
  345. PyErr_SetString(PyExc_AttributeError, name);
  346. return NULL;
  347. }
  348. /* Find a method in a single method list */
  349. PyObject *
  350. Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
  351. {
  352. PyMethodChain chain;
  353. chain.methods = methods;
  354. chain.link = NULL;
  355. return Py_FindMethodInChain(&chain, self, name);
  356. }
  357. /* Clear out the free list */
  358. int
  359. PyCFunction_ClearFreeList(void)
  360. {
  361. int freelist_size = numfree;
  362. while (free_list) {
  363. PyCFunctionObject *v = free_list;
  364. free_list = (PyCFunctionObject *)(v->m_self);
  365. PyObject_GC_Del(v);
  366. numfree--;
  367. }
  368. assert(numfree == 0);
  369. return freelist_size;
  370. }
  371. void
  372. PyCFunction_Fini(void)
  373. {
  374. (void)PyCFunction_ClearFreeList();
  375. }
  376. /* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
  377. but it's part of the API so we need to keep a function around that
  378. existing C extensions can call.
  379. */
  380. #undef PyCFunction_New
  381. PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
  382. PyObject *
  383. PyCFunction_New(PyMethodDef *ml, PyObject *self)
  384. {
  385. return PyCFunction_NewEx(ml, self, NULL);
  386. }