/Modules/operator.c

http://unladen-swallow.googlecode.com/ · C · 783 lines · 672 code · 100 blank · 11 comment · 87 complexity · 9969509e2c8f28a22a708684720093f9 MD5 · raw file

  1. #include "Python.h"
  2. PyDoc_STRVAR(operator_doc,
  3. "Operator interface.\n\
  4. \n\
  5. This module exports a set of functions implemented in C corresponding\n\
  6. to the intrinsic operators of Python. For example, operator.add(x, y)\n\
  7. is equivalent to the expression x+y. The function names are those\n\
  8. used for special class methods; variants without leading and trailing\n\
  9. '__' are also provided for convenience.");
  10. #define spam1(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \
  11. return AOP(a1); }
  12. #define spam2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  13. PyObject *a1, *a2; \
  14. if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
  15. return AOP(a1,a2); }
  16. #define spamoi(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  17. PyObject *a1; int a2; \
  18. if(! PyArg_ParseTuple(a,"Oi:" #OP,&a1,&a2)) return NULL; \
  19. return AOP(a1,a2); }
  20. #define spam2n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  21. PyObject *a1, *a2; \
  22. if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
  23. if(-1 == AOP(a1,a2)) return NULL; \
  24. Py_INCREF(Py_None); \
  25. return Py_None; }
  26. #define spam3n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  27. PyObject *a1, *a2, *a3; \
  28. if(! PyArg_UnpackTuple(a,#OP,3,3,&a1,&a2,&a3)) return NULL; \
  29. if(-1 == AOP(a1,a2,a3)) return NULL; \
  30. Py_INCREF(Py_None); \
  31. return Py_None; }
  32. #define spami(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \
  33. long r; \
  34. if(-1 == (r=AOP(a1))) return NULL; \
  35. return PyBool_FromLong(r); }
  36. #define spami2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  37. PyObject *a1, *a2; long r; \
  38. if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
  39. if(-1 == (r=AOP(a1,a2))) return NULL; \
  40. return PyInt_FromLong(r); }
  41. #define spamn2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  42. PyObject *a1, *a2; Py_ssize_t r; \
  43. if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
  44. if(-1 == (r=AOP(a1,a2))) return NULL; \
  45. return PyInt_FromSsize_t(r); }
  46. #define spami2b(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
  47. PyObject *a1, *a2; long r; \
  48. if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
  49. if(-1 == (r=AOP(a1,a2))) return NULL; \
  50. return PyBool_FromLong(r); }
  51. #define spamrc(OP,A) static PyObject *OP(PyObject *s, PyObject *a) { \
  52. PyObject *a1, *a2; \
  53. if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
  54. return PyObject_RichCompare(a1,a2,A); }
  55. spami(isCallable , PyCallable_Check)
  56. spami(isNumberType , PyNumber_Check)
  57. spami(truth , PyObject_IsTrue)
  58. spam2(op_add , PyNumber_Add)
  59. spam2(op_sub , PyNumber_Subtract)
  60. spam2(op_mul , PyNumber_Multiply)
  61. spam2(op_div , PyNumber_Divide)
  62. spam2(op_floordiv , PyNumber_FloorDivide)
  63. spam2(op_truediv , PyNumber_TrueDivide)
  64. spam2(op_mod , PyNumber_Remainder)
  65. spam1(op_neg , PyNumber_Negative)
  66. spam1(op_pos , PyNumber_Positive)
  67. spam1(op_abs , PyNumber_Absolute)
  68. spam1(op_inv , PyNumber_Invert)
  69. spam1(op_invert , PyNumber_Invert)
  70. spam2(op_lshift , PyNumber_Lshift)
  71. spam2(op_rshift , PyNumber_Rshift)
  72. spami(op_not_ , PyObject_Not)
  73. spam2(op_and_ , PyNumber_And)
  74. spam2(op_xor , PyNumber_Xor)
  75. spam2(op_or_ , PyNumber_Or)
  76. spam2(op_iadd , PyNumber_InPlaceAdd)
  77. spam2(op_isub , PyNumber_InPlaceSubtract)
  78. spam2(op_imul , PyNumber_InPlaceMultiply)
  79. spam2(op_idiv , PyNumber_InPlaceDivide)
  80. spam2(op_ifloordiv , PyNumber_InPlaceFloorDivide)
  81. spam2(op_itruediv , PyNumber_InPlaceTrueDivide)
  82. spam2(op_imod , PyNumber_InPlaceRemainder)
  83. spam2(op_ilshift , PyNumber_InPlaceLshift)
  84. spam2(op_irshift , PyNumber_InPlaceRshift)
  85. spam2(op_iand , PyNumber_InPlaceAnd)
  86. spam2(op_ixor , PyNumber_InPlaceXor)
  87. spam2(op_ior , PyNumber_InPlaceOr)
  88. spami(isSequenceType , PySequence_Check)
  89. spam2(op_concat , PySequence_Concat)
  90. spamoi(op_repeat , PySequence_Repeat)
  91. spam2(op_iconcat , PySequence_InPlaceConcat)
  92. spamoi(op_irepeat , PySequence_InPlaceRepeat)
  93. spami2b(op_contains , PySequence_Contains)
  94. spami2b(sequenceIncludes, PySequence_Contains)
  95. spamn2(indexOf , PySequence_Index)
  96. spamn2(countOf , PySequence_Count)
  97. spami(isMappingType , PyMapping_Check)
  98. spam2(op_getitem , PyObject_GetItem)
  99. spam2n(op_delitem , PyObject_DelItem)
  100. spam3n(op_setitem , PyObject_SetItem)
  101. spamrc(op_lt , Py_LT)
  102. spamrc(op_le , Py_LE)
  103. spamrc(op_eq , Py_EQ)
  104. spamrc(op_ne , Py_NE)
  105. spamrc(op_gt , Py_GT)
  106. spamrc(op_ge , Py_GE)
  107. static PyObject*
  108. op_pow(PyObject *s, PyObject *a)
  109. {
  110. PyObject *a1, *a2;
  111. if (PyArg_UnpackTuple(a,"pow", 2, 2, &a1, &a2))
  112. return PyNumber_Power(a1, a2, Py_None);
  113. return NULL;
  114. }
  115. static PyObject*
  116. op_ipow(PyObject *s, PyObject *a)
  117. {
  118. PyObject *a1, *a2;
  119. if (PyArg_UnpackTuple(a,"ipow", 2, 2, &a1, &a2))
  120. return PyNumber_InPlacePower(a1, a2, Py_None);
  121. return NULL;
  122. }
  123. static PyObject *
  124. op_index(PyObject *s, PyObject *a)
  125. {
  126. return PyNumber_Index(a);
  127. }
  128. static PyObject*
  129. is_(PyObject *s, PyObject *a)
  130. {
  131. PyObject *a1, *a2, *result = NULL;
  132. if (PyArg_UnpackTuple(a,"is_", 2, 2, &a1, &a2)) {
  133. result = (a1 == a2) ? Py_True : Py_False;
  134. Py_INCREF(result);
  135. }
  136. return result;
  137. }
  138. static PyObject*
  139. is_not(PyObject *s, PyObject *a)
  140. {
  141. PyObject *a1, *a2, *result = NULL;
  142. if (PyArg_UnpackTuple(a,"is_not", 2, 2, &a1, &a2)) {
  143. result = (a1 != a2) ? Py_True : Py_False;
  144. Py_INCREF(result);
  145. }
  146. return result;
  147. }
  148. static PyObject*
  149. op_getslice(PyObject *s, PyObject *a)
  150. {
  151. PyObject *a1;
  152. Py_ssize_t a2, a3;
  153. if (!PyArg_ParseTuple(a, "Onn:getslice", &a1, &a2, &a3))
  154. return NULL;
  155. return PySequence_GetSlice(a1, a2, a3);
  156. }
  157. static PyObject*
  158. op_setslice(PyObject *s, PyObject *a)
  159. {
  160. PyObject *a1, *a4;
  161. Py_ssize_t a2, a3;
  162. if (!PyArg_ParseTuple(a, "OnnO:setslice", &a1, &a2, &a3, &a4))
  163. return NULL;
  164. if (-1 == PySequence_SetSlice(a1, a2, a3, a4))
  165. return NULL;
  166. Py_RETURN_NONE;
  167. }
  168. static PyObject*
  169. op_delslice(PyObject *s, PyObject *a)
  170. {
  171. PyObject *a1;
  172. Py_ssize_t a2, a3;
  173. if (!PyArg_ParseTuple(a, "Onn:delslice", &a1, &a2, &a3))
  174. return NULL;
  175. if (-1 == PySequence_DelSlice(a1, a2, a3))
  176. return NULL;
  177. Py_RETURN_NONE;
  178. }
  179. #undef spam1
  180. #undef spam2
  181. #undef spam1o
  182. #undef spam1o
  183. #define spam1(OP,DOC) {#OP, OP, METH_VARARGS, PyDoc_STR(DOC)},
  184. #define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \
  185. {#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},
  186. #define spam1o(OP,DOC) {#OP, OP, METH_O, PyDoc_STR(DOC)},
  187. #define spam2o(OP,ALTOP,DOC) {#OP, op_##OP, METH_O, PyDoc_STR(DOC)}, \
  188. {#ALTOP, op_##OP, METH_O, PyDoc_STR(DOC)},
  189. static struct PyMethodDef operator_methods[] = {
  190. spam1o(isCallable,
  191. "isCallable(a) -- Same as callable(a).")
  192. spam1o(isNumberType,
  193. "isNumberType(a) -- Return True if a has a numeric type, False otherwise.")
  194. spam1o(isSequenceType,
  195. "isSequenceType(a) -- Return True if a has a sequence type, False otherwise.")
  196. spam1o(truth,
  197. "truth(a) -- Return True if a is true, False otherwise.")
  198. spam2(contains,__contains__,
  199. "contains(a, b) -- Same as b in a (note reversed operands).")
  200. spam1(sequenceIncludes,
  201. "sequenceIncludes(a, b) -- Same as b in a (note reversed operands; deprecated).")
  202. spam1(indexOf,
  203. "indexOf(a, b) -- Return the first index of b in a.")
  204. spam1(countOf,
  205. "countOf(a, b) -- Return the number of times b occurs in a.")
  206. spam1o(isMappingType,
  207. "isMappingType(a) -- Return True if a has a mapping type, False otherwise.")
  208. spam1(is_, "is_(a, b) -- Same as a is b.")
  209. spam1(is_not, "is_not(a, b) -- Same as a is not b.")
  210. spam2o(index, __index__, "index(a) -- Same as a.__index__()")
  211. spam2(add,__add__, "add(a, b) -- Same as a + b.")
  212. spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
  213. spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
  214. spam2(div,__div__, "div(a, b) -- Same as a / b when __future__.division is not in effect.")
  215. spam2(floordiv,__floordiv__, "floordiv(a, b) -- Same as a // b.")
  216. spam2(truediv,__truediv__, "truediv(a, b) -- Same as a / b when __future__.division is in effect.")
  217. spam2(mod,__mod__, "mod(a, b) -- Same as a % b.")
  218. spam2o(neg,__neg__, "neg(a) -- Same as -a.")
  219. spam2o(pos,__pos__, "pos(a) -- Same as +a.")
  220. spam2o(abs,__abs__, "abs(a) -- Same as abs(a).")
  221. spam2o(inv,__inv__, "inv(a) -- Same as ~a.")
  222. spam2o(invert,__invert__, "invert(a) -- Same as ~a.")
  223. spam2(lshift,__lshift__, "lshift(a, b) -- Same as a << b.")
  224. spam2(rshift,__rshift__, "rshift(a, b) -- Same as a >> b.")
  225. spam2o(not_,__not__, "not_(a) -- Same as not a.")
  226. spam2(and_,__and__, "and_(a, b) -- Same as a & b.")
  227. spam2(xor,__xor__, "xor(a, b) -- Same as a ^ b.")
  228. spam2(or_,__or__, "or_(a, b) -- Same as a | b.")
  229. spam2(iadd,__iadd__, "iadd(a, b) -- Same as a += b.")
  230. spam2(isub,__isub__, "isub(a, b) -- Same as a -= b.")
  231. spam2(imul,__imul__, "imul(a, b) -- Same as a *= b.")
  232. spam2(idiv,__idiv__, "idiv(a, b) -- Same as a /= b when __future__.division is not in effect.")
  233. spam2(ifloordiv,__ifloordiv__, "ifloordiv(a, b) -- Same as a //= b.")
  234. spam2(itruediv,__itruediv__, "itruediv(a, b) -- Same as a /= b when __future__.division is in effect.")
  235. spam2(imod,__imod__, "imod(a, b) -- Same as a %= b.")
  236. spam2(ilshift,__ilshift__, "ilshift(a, b) -- Same as a <<= b.")
  237. spam2(irshift,__irshift__, "irshift(a, b) -- Same as a >>= b.")
  238. spam2(iand,__iand__, "iand(a, b) -- Same as a &= b.")
  239. spam2(ixor,__ixor__, "ixor(a, b) -- Same as a ^= b.")
  240. spam2(ior,__ior__, "ior(a, b) -- Same as a |= b.")
  241. spam2(concat,__concat__,
  242. "concat(a, b) -- Same as a + b, for a and b sequences.")
  243. spam2(repeat,__repeat__,
  244. "repeat(a, b) -- Return a * b, where a is a sequence, and b is an integer.")
  245. spam2(iconcat,__iconcat__,
  246. "iconcat(a, b) -- Same as a += b, for a and b sequences.")
  247. spam2(irepeat,__irepeat__,
  248. "irepeat(a, b) -- Same as a *= b, where a is a sequence, and b is an integer.")
  249. spam2(getitem,__getitem__,
  250. "getitem(a, b) -- Same as a[b].")
  251. spam2(setitem,__setitem__,
  252. "setitem(a, b, c) -- Same as a[b] = c.")
  253. spam2(delitem,__delitem__,
  254. "delitem(a, b) -- Same as del a[b].")
  255. spam2(pow,__pow__, "pow(a, b) -- Same as a ** b.")
  256. spam2(ipow,__ipow__, "ipow(a, b) -- Same as a **= b.")
  257. spam2(getslice,__getslice__,
  258. "getslice(a, b, c) -- Same as a[b:c].")
  259. spam2(setslice,__setslice__,
  260. "setslice(a, b, c, d) -- Same as a[b:c] = d.")
  261. spam2(delslice,__delslice__,
  262. "delslice(a, b, c) -- Same as del a[b:c].")
  263. spam2(lt,__lt__, "lt(a, b) -- Same as a<b.")
  264. spam2(le,__le__, "le(a, b) -- Same as a<=b.")
  265. spam2(eq,__eq__, "eq(a, b) -- Same as a==b.")
  266. spam2(ne,__ne__, "ne(a, b) -- Same as a!=b.")
  267. spam2(gt,__gt__, "gt(a, b) -- Same as a>b.")
  268. spam2(ge,__ge__, "ge(a, b) -- Same as a>=b.")
  269. {NULL, NULL} /* sentinel */
  270. };
  271. /* itemgetter object **********************************************************/
  272. typedef struct {
  273. PyObject_HEAD
  274. Py_ssize_t nitems;
  275. PyObject *item;
  276. } itemgetterobject;
  277. static PyTypeObject itemgetter_type;
  278. static PyObject *
  279. itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  280. {
  281. itemgetterobject *ig;
  282. PyObject *item;
  283. Py_ssize_t nitems;
  284. if (!_PyArg_NoKeywords("itemgetter()", kwds))
  285. return NULL;
  286. nitems = PyTuple_GET_SIZE(args);
  287. if (nitems <= 1) {
  288. if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item))
  289. return NULL;
  290. } else
  291. item = args;
  292. /* create itemgetterobject structure */
  293. ig = PyObject_GC_New(itemgetterobject, &itemgetter_type);
  294. if (ig == NULL)
  295. return NULL;
  296. Py_INCREF(item);
  297. ig->item = item;
  298. ig->nitems = nitems;
  299. PyObject_GC_Track(ig);
  300. return (PyObject *)ig;
  301. }
  302. static void
  303. itemgetter_dealloc(itemgetterobject *ig)
  304. {
  305. PyObject_GC_UnTrack(ig);
  306. Py_XDECREF(ig->item);
  307. PyObject_GC_Del(ig);
  308. }
  309. static int
  310. itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
  311. {
  312. Py_VISIT(ig->item);
  313. return 0;
  314. }
  315. static PyObject *
  316. itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)
  317. {
  318. PyObject *obj, *result;
  319. Py_ssize_t i, nitems=ig->nitems;
  320. if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
  321. return NULL;
  322. if (nitems == 1)
  323. return PyObject_GetItem(obj, ig->item);
  324. assert(PyTuple_Check(ig->item));
  325. assert(PyTuple_GET_SIZE(ig->item) == nitems);
  326. result = PyTuple_New(nitems);
  327. if (result == NULL)
  328. return NULL;
  329. for (i=0 ; i < nitems ; i++) {
  330. PyObject *item, *val;
  331. item = PyTuple_GET_ITEM(ig->item, i);
  332. val = PyObject_GetItem(obj, item);
  333. if (val == NULL) {
  334. Py_DECREF(result);
  335. return NULL;
  336. }
  337. PyTuple_SET_ITEM(result, i, val);
  338. }
  339. return result;
  340. }
  341. PyDoc_STRVAR(itemgetter_doc,
  342. "itemgetter(item, ...) --> itemgetter object\n\
  343. \n\
  344. Return a callable object that fetches the given item(s) from its operand.\n\
  345. After, f=itemgetter(2), the call f(r) returns r[2].\n\
  346. After, g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])");
  347. static PyTypeObject itemgetter_type = {
  348. PyVarObject_HEAD_INIT(NULL, 0)
  349. "operator.itemgetter", /* tp_name */
  350. sizeof(itemgetterobject), /* tp_basicsize */
  351. 0, /* tp_itemsize */
  352. /* methods */
  353. (destructor)itemgetter_dealloc, /* tp_dealloc */
  354. 0, /* tp_print */
  355. 0, /* tp_getattr */
  356. 0, /* tp_setattr */
  357. 0, /* tp_compare */
  358. 0, /* tp_repr */
  359. 0, /* tp_as_number */
  360. 0, /* tp_as_sequence */
  361. 0, /* tp_as_mapping */
  362. 0, /* tp_hash */
  363. (ternaryfunc)itemgetter_call, /* tp_call */
  364. 0, /* tp_str */
  365. PyObject_GenericGetAttr, /* tp_getattro */
  366. 0, /* tp_setattro */
  367. 0, /* tp_as_buffer */
  368. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  369. itemgetter_doc, /* tp_doc */
  370. (traverseproc)itemgetter_traverse, /* tp_traverse */
  371. 0, /* tp_clear */
  372. 0, /* tp_richcompare */
  373. 0, /* tp_weaklistoffset */
  374. 0, /* tp_iter */
  375. 0, /* tp_iternext */
  376. 0, /* tp_methods */
  377. 0, /* tp_members */
  378. 0, /* tp_getset */
  379. 0, /* tp_base */
  380. 0, /* tp_dict */
  381. 0, /* tp_descr_get */
  382. 0, /* tp_descr_set */
  383. 0, /* tp_dictoffset */
  384. 0, /* tp_init */
  385. 0, /* tp_alloc */
  386. itemgetter_new, /* tp_new */
  387. 0, /* tp_free */
  388. };
  389. /* attrgetter object **********************************************************/
  390. typedef struct {
  391. PyObject_HEAD
  392. Py_ssize_t nattrs;
  393. PyObject *attr;
  394. } attrgetterobject;
  395. static PyTypeObject attrgetter_type;
  396. static PyObject *
  397. attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  398. {
  399. attrgetterobject *ag;
  400. PyObject *attr;
  401. Py_ssize_t nattrs;
  402. if (!_PyArg_NoKeywords("attrgetter()", kwds))
  403. return NULL;
  404. nattrs = PyTuple_GET_SIZE(args);
  405. if (nattrs <= 1) {
  406. if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))
  407. return NULL;
  408. } else
  409. attr = args;
  410. /* create attrgetterobject structure */
  411. ag = PyObject_GC_New(attrgetterobject, &attrgetter_type);
  412. if (ag == NULL)
  413. return NULL;
  414. Py_INCREF(attr);
  415. ag->attr = attr;
  416. ag->nattrs = nattrs;
  417. PyObject_GC_Track(ag);
  418. return (PyObject *)ag;
  419. }
  420. static void
  421. attrgetter_dealloc(attrgetterobject *ag)
  422. {
  423. PyObject_GC_UnTrack(ag);
  424. Py_XDECREF(ag->attr);
  425. PyObject_GC_Del(ag);
  426. }
  427. static int
  428. attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
  429. {
  430. Py_VISIT(ag->attr);
  431. return 0;
  432. }
  433. static PyObject *
  434. dotted_getattr(PyObject *obj, PyObject *attr)
  435. {
  436. char *s, *p;
  437. #ifdef Py_USING_UNICODE
  438. if (PyUnicode_Check(attr)) {
  439. attr = _PyUnicode_AsDefaultEncodedString(attr, NULL);
  440. if (attr == NULL)
  441. return NULL;
  442. }
  443. #endif
  444. if (!PyString_Check(attr)) {
  445. PyErr_SetString(PyExc_TypeError,
  446. "attribute name must be a string");
  447. return NULL;
  448. }
  449. s = PyString_AS_STRING(attr);
  450. Py_INCREF(obj);
  451. for (;;) {
  452. PyObject *newobj, *str;
  453. p = strchr(s, '.');
  454. str = p ? PyString_FromStringAndSize(s, (p-s)) :
  455. PyString_FromString(s);
  456. if (str == NULL) {
  457. Py_DECREF(obj);
  458. return NULL;
  459. }
  460. newobj = PyObject_GetAttr(obj, str);
  461. Py_DECREF(str);
  462. Py_DECREF(obj);
  463. if (newobj == NULL)
  464. return NULL;
  465. obj = newobj;
  466. if (p == NULL) break;
  467. s = p+1;
  468. }
  469. return obj;
  470. }
  471. static PyObject *
  472. attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
  473. {
  474. PyObject *obj, *result;
  475. Py_ssize_t i, nattrs=ag->nattrs;
  476. if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
  477. return NULL;
  478. if (ag->nattrs == 1)
  479. return dotted_getattr(obj, ag->attr);
  480. assert(PyTuple_Check(ag->attr));
  481. assert(PyTuple_GET_SIZE(ag->attr) == nattrs);
  482. result = PyTuple_New(nattrs);
  483. if (result == NULL)
  484. return NULL;
  485. for (i=0 ; i < nattrs ; i++) {
  486. PyObject *attr, *val;
  487. attr = PyTuple_GET_ITEM(ag->attr, i);
  488. val = dotted_getattr(obj, attr);
  489. if (val == NULL) {
  490. Py_DECREF(result);
  491. return NULL;
  492. }
  493. PyTuple_SET_ITEM(result, i, val);
  494. }
  495. return result;
  496. }
  497. PyDoc_STRVAR(attrgetter_doc,
  498. "attrgetter(attr, ...) --> attrgetter object\n\
  499. \n\
  500. Return a callable object that fetches the given attribute(s) from its operand.\n\
  501. After, f=attrgetter('name'), the call f(r) returns r.name.\n\
  502. After, g=attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
  503. After, h=attrgetter('name.first', 'name.last'), the call h(r) returns\n\
  504. (r.name.first, r.name.last).");
  505. static PyTypeObject attrgetter_type = {
  506. PyVarObject_HEAD_INIT(NULL, 0)
  507. "operator.attrgetter", /* tp_name */
  508. sizeof(attrgetterobject), /* tp_basicsize */
  509. 0, /* tp_itemsize */
  510. /* methods */
  511. (destructor)attrgetter_dealloc, /* tp_dealloc */
  512. 0, /* tp_print */
  513. 0, /* tp_getattr */
  514. 0, /* tp_setattr */
  515. 0, /* tp_compare */
  516. 0, /* tp_repr */
  517. 0, /* tp_as_number */
  518. 0, /* tp_as_sequence */
  519. 0, /* tp_as_mapping */
  520. 0, /* tp_hash */
  521. (ternaryfunc)attrgetter_call, /* tp_call */
  522. 0, /* tp_str */
  523. PyObject_GenericGetAttr, /* tp_getattro */
  524. 0, /* tp_setattro */
  525. 0, /* tp_as_buffer */
  526. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
  527. attrgetter_doc, /* tp_doc */
  528. (traverseproc)attrgetter_traverse, /* tp_traverse */
  529. 0, /* tp_clear */
  530. 0, /* tp_richcompare */
  531. 0, /* tp_weaklistoffset */
  532. 0, /* tp_iter */
  533. 0, /* tp_iternext */
  534. 0, /* tp_methods */
  535. 0, /* tp_members */
  536. 0, /* tp_getset */
  537. 0, /* tp_base */
  538. 0, /* tp_dict */
  539. 0, /* tp_descr_get */
  540. 0, /* tp_descr_set */
  541. 0, /* tp_dictoffset */
  542. 0, /* tp_init */
  543. 0, /* tp_alloc */
  544. attrgetter_new, /* tp_new */
  545. 0, /* tp_free */
  546. };
  547. /* methodcaller object **********************************************************/
  548. typedef struct {
  549. PyObject_HEAD
  550. PyObject *name;
  551. PyObject *args;
  552. PyObject *kwds;
  553. } methodcallerobject;
  554. static PyTypeObject methodcaller_type;
  555. static PyObject *
  556. methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
  557. {
  558. methodcallerobject *mc;
  559. PyObject *name, *newargs;
  560. if (PyTuple_GET_SIZE(args) < 1) {
  561. PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "
  562. "one argument, the method name");
  563. return NULL;
  564. }
  565. /* create methodcallerobject structure */
  566. mc = PyObject_GC_New(methodcallerobject, &methodcaller_type);
  567. if (mc == NULL)
  568. return NULL;
  569. newargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
  570. if (newargs == NULL) {
  571. Py_DECREF(mc);
  572. return NULL;
  573. }
  574. mc->args = newargs;
  575. name = PyTuple_GET_ITEM(args, 0);
  576. Py_INCREF(name);
  577. mc->name = name;
  578. Py_XINCREF(kwds);
  579. mc->kwds = kwds;
  580. PyObject_GC_Track(mc);
  581. return (PyObject *)mc;
  582. }
  583. static void
  584. methodcaller_dealloc(methodcallerobject *mc)
  585. {
  586. PyObject_GC_UnTrack(mc);
  587. Py_XDECREF(mc->name);
  588. Py_XDECREF(mc->args);
  589. Py_XDECREF(mc->kwds);
  590. PyObject_GC_Del(mc);
  591. }
  592. static int
  593. methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
  594. {
  595. Py_VISIT(mc->args);
  596. Py_VISIT(mc->kwds);
  597. return 0;
  598. }
  599. static PyObject *
  600. methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
  601. {
  602. PyObject *method, *obj, *result;
  603. if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
  604. return NULL;
  605. method = PyObject_GetAttr(obj, mc->name);
  606. if (method == NULL)
  607. return NULL;
  608. result = PyObject_Call(method, mc->args, mc->kwds);
  609. Py_DECREF(method);
  610. return result;
  611. }
  612. PyDoc_STRVAR(methodcaller_doc,
  613. "methodcaller(name, ...) --> methodcaller object\n\
  614. \n\
  615. Return a callable object that calls the given method on its operand.\n\
  616. After, f = methodcaller('name'), the call f(r) returns r.name().\n\
  617. After, g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
  618. r.name('date', foo=1).");
  619. static PyTypeObject methodcaller_type = {
  620. PyVarObject_HEAD_INIT(NULL, 0)
  621. "operator.methodcaller", /* tp_name */
  622. sizeof(methodcallerobject), /* tp_basicsize */
  623. 0, /* tp_itemsize */
  624. /* methods */
  625. (destructor)methodcaller_dealloc, /* tp_dealloc */
  626. 0, /* tp_print */
  627. 0, /* tp_getattr */
  628. 0, /* tp_setattr */
  629. 0, /* tp_compare */
  630. 0, /* tp_repr */
  631. 0, /* tp_as_number */
  632. 0, /* tp_as_sequence */
  633. 0, /* tp_as_mapping */
  634. 0, /* tp_hash */
  635. (ternaryfunc)methodcaller_call, /* tp_call */
  636. 0, /* tp_str */
  637. PyObject_GenericGetAttr, /* tp_getattro */
  638. 0, /* tp_setattro */
  639. 0, /* tp_as_buffer */
  640. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
  641. methodcaller_doc, /* tp_doc */
  642. (traverseproc)methodcaller_traverse, /* tp_traverse */
  643. 0, /* tp_clear */
  644. 0, /* tp_richcompare */
  645. 0, /* tp_weaklistoffset */
  646. 0, /* tp_iter */
  647. 0, /* tp_iternext */
  648. 0, /* tp_methods */
  649. 0, /* tp_members */
  650. 0, /* tp_getset */
  651. 0, /* tp_base */
  652. 0, /* tp_dict */
  653. 0, /* tp_descr_get */
  654. 0, /* tp_descr_set */
  655. 0, /* tp_dictoffset */
  656. 0, /* tp_init */
  657. 0, /* tp_alloc */
  658. methodcaller_new, /* tp_new */
  659. 0, /* tp_free */
  660. };
  661. /* Initialization function for the module (*must* be called initoperator) */
  662. PyMODINIT_FUNC
  663. initoperator(void)
  664. {
  665. PyObject *m;
  666. /* Create the module and add the functions */
  667. m = Py_InitModule4("operator", operator_methods, operator_doc,
  668. (PyObject*)NULL, PYTHON_API_VERSION);
  669. if (m == NULL)
  670. return;
  671. if (PyType_Ready(&itemgetter_type) < 0)
  672. return;
  673. Py_INCREF(&itemgetter_type);
  674. PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);
  675. if (PyType_Ready(&attrgetter_type) < 0)
  676. return;
  677. Py_INCREF(&attrgetter_type);
  678. PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);
  679. if (PyType_Ready(&methodcaller_type) < 0)
  680. return;
  681. Py_INCREF(&methodcaller_type);
  682. PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);
  683. }