blob: 8f524a6449b8f8e1cea6b66b440f751b242e8825 [file] [log] [blame]
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001
2#include "Python.h"
3
4PyDoc_STRVAR(operator_doc,
5"Operator interface.\n\
Guido van Rossum037b9401996-07-30 16:55:54 +00006\n\
7This module exports a set of functions implemented in C corresponding\n\
8to the intrinsic operators of Python. For example, operator.add(x, y)\n\
9is equivalent to the expression x+y. The function names are those\n\
Benjamin Petersona0dfa822009-11-13 02:25:08 +000010used for special methods; variants without leading and trailing\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000011'__' are also provided for convenience.");
Guido van Rossum037b9401996-07-30 16:55:54 +000012
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +000013#define spam1(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \
Guido van Rossum037b9401996-07-30 16:55:54 +000014 return AOP(a1); }
15
Fred Drake5639ba42000-07-08 04:12:08 +000016#define spam2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
Guido van Rossum037b9401996-07-30 16:55:54 +000017 PyObject *a1, *a2; \
Raymond Hettingerea3fdf42002-12-29 16:33:45 +000018 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
Guido van Rossum037b9401996-07-30 16:55:54 +000019 return AOP(a1,a2); }
20
Fred Drake5639ba42000-07-08 04:12:08 +000021#define spamoi(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
Guido van Rossum037b9401996-07-30 16:55:54 +000022 PyObject *a1; int a2; \
Fred Drakeea4d3f02000-09-17 16:09:27 +000023 if(! PyArg_ParseTuple(a,"Oi:" #OP,&a1,&a2)) return NULL; \
Guido van Rossum037b9401996-07-30 16:55:54 +000024 return AOP(a1,a2); }
25
Fred Drake5639ba42000-07-08 04:12:08 +000026#define spam2n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
Guido van Rossum037b9401996-07-30 16:55:54 +000027 PyObject *a1, *a2; \
Raymond Hettingerea3fdf42002-12-29 16:33:45 +000028 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
Guido van Rossum037b9401996-07-30 16:55:54 +000029 if(-1 == AOP(a1,a2)) return NULL; \
30 Py_INCREF(Py_None); \
31 return Py_None; }
32
Fred Drake5639ba42000-07-08 04:12:08 +000033#define spam3n(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
Guido van Rossum037b9401996-07-30 16:55:54 +000034 PyObject *a1, *a2, *a3; \
Raymond Hettingerea3fdf42002-12-29 16:33:45 +000035 if(! PyArg_UnpackTuple(a,#OP,3,3,&a1,&a2,&a3)) return NULL; \
Guido van Rossum037b9401996-07-30 16:55:54 +000036 if(-1 == AOP(a1,a2,a3)) return NULL; \
37 Py_INCREF(Py_None); \
38 return Py_None; }
39
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +000040#define spami(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a1) { \
41 long r; \
Guido van Rossum037b9401996-07-30 16:55:54 +000042 if(-1 == (r=AOP(a1))) return NULL; \
Guido van Rossum77f6a652002-04-03 22:41:51 +000043 return PyBool_FromLong(r); }
Guido van Rossum037b9401996-07-30 16:55:54 +000044
Fred Drake5639ba42000-07-08 04:12:08 +000045#define spami2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
Guido van Rossum037b9401996-07-30 16:55:54 +000046 PyObject *a1, *a2; long r; \
Raymond Hettingerea3fdf42002-12-29 16:33:45 +000047 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
Guido van Rossum037b9401996-07-30 16:55:54 +000048 if(-1 == (r=AOP(a1,a2))) return NULL; \
Christian Heimes217cfd12007-12-02 14:31:20 +000049 return PyLong_FromLong(r); }
Guido van Rossum037b9401996-07-30 16:55:54 +000050
Thomas Wouters477c8d52006-05-27 19:21:47 +000051#define spamn2(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
52 PyObject *a1, *a2; Py_ssize_t r; \
53 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
54 if(-1 == (r=AOP(a1,a2))) return NULL; \
Christian Heimes217cfd12007-12-02 14:31:20 +000055 return PyLong_FromSsize_t(r); }
Thomas Wouters477c8d52006-05-27 19:21:47 +000056
Guido van Rossum77f6a652002-04-03 22:41:51 +000057#define spami2b(OP,AOP) static PyObject *OP(PyObject *s, PyObject *a) { \
58 PyObject *a1, *a2; long r; \
Raymond Hettingerea3fdf42002-12-29 16:33:45 +000059 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
Guido van Rossum77f6a652002-04-03 22:41:51 +000060 if(-1 == (r=AOP(a1,a2))) return NULL; \
61 return PyBool_FromLong(r); }
62
Fred Drake428e75f2001-08-09 20:14:34 +000063#define spamrc(OP,A) static PyObject *OP(PyObject *s, PyObject *a) { \
64 PyObject *a1, *a2; \
Raymond Hettingerea3fdf42002-12-29 16:33:45 +000065 if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
Fred Drake428e75f2001-08-09 20:14:34 +000066 return PyObject_RichCompare(a1,a2,A); }
67
Guido van Rossum037b9401996-07-30 16:55:54 +000068spami(truth , PyObject_IsTrue)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000069spam2(op_add , PyNumber_Add)
70spam2(op_sub , PyNumber_Subtract)
71spam2(op_mul , PyNumber_Multiply)
Benjamin Petersond51374e2014-04-09 23:55:56 -040072spam2(op_matmul , PyNumber_MatrixMultiply)
Fred Drake428e75f2001-08-09 20:14:34 +000073spam2(op_floordiv , PyNumber_FloorDivide)
74spam2(op_truediv , PyNumber_TrueDivide)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000075spam2(op_mod , PyNumber_Remainder)
76spam1(op_neg , PyNumber_Negative)
77spam1(op_pos , PyNumber_Positive)
78spam1(op_abs , PyNumber_Absolute)
79spam1(op_inv , PyNumber_Invert)
Fred Drakeea4d3f02000-09-17 16:09:27 +000080spam1(op_invert , PyNumber_Invert)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000081spam2(op_lshift , PyNumber_Lshift)
82spam2(op_rshift , PyNumber_Rshift)
Guido van Rossum99c185e1998-04-09 17:54:26 +000083spami(op_not_ , PyObject_Not)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000084spam2(op_and_ , PyNumber_And)
85spam2(op_xor , PyNumber_Xor)
86spam2(op_or_ , PyNumber_Or)
Armin Rigof5bd3b42005-12-29 16:50:42 +000087spam2(op_iadd , PyNumber_InPlaceAdd)
88spam2(op_isub , PyNumber_InPlaceSubtract)
89spam2(op_imul , PyNumber_InPlaceMultiply)
Benjamin Petersond51374e2014-04-09 23:55:56 -040090spam2(op_imatmul , PyNumber_InPlaceMatrixMultiply)
Armin Rigof5bd3b42005-12-29 16:50:42 +000091spam2(op_ifloordiv , PyNumber_InPlaceFloorDivide)
92spam2(op_itruediv , PyNumber_InPlaceTrueDivide)
93spam2(op_imod , PyNumber_InPlaceRemainder)
94spam2(op_ilshift , PyNumber_InPlaceLshift)
95spam2(op_irshift , PyNumber_InPlaceRshift)
96spam2(op_iand , PyNumber_InPlaceAnd)
97spam2(op_ixor , PyNumber_InPlaceXor)
98spam2(op_ior , PyNumber_InPlaceOr)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000099spam2(op_concat , PySequence_Concat)
Armin Rigof5bd3b42005-12-29 16:50:42 +0000100spam2(op_iconcat , PySequence_InPlaceConcat)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000101spami2b(op_contains , PySequence_Contains)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000102spamn2(indexOf , PySequence_Index)
103spamn2(countOf , PySequence_Count)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +0000104spam2(op_getitem , PyObject_GetItem)
105spam2n(op_delitem , PyObject_DelItem)
106spam3n(op_setitem , PyObject_SetItem)
Fred Drake428e75f2001-08-09 20:14:34 +0000107spamrc(op_lt , Py_LT)
108spamrc(op_le , Py_LE)
109spamrc(op_eq , Py_EQ)
110spamrc(op_ne , Py_NE)
111spamrc(op_gt , Py_GT)
112spamrc(op_ge , Py_GE)
Guido van Rossum037b9401996-07-30 16:55:54 +0000113
114static PyObject*
Raymond Hettinger5959c552002-08-19 03:19:09 +0000115op_pow(PyObject *s, PyObject *a)
116{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000117 PyObject *a1, *a2;
118 if (PyArg_UnpackTuple(a,"pow", 2, 2, &a1, &a2))
119 return PyNumber_Power(a1, a2, Py_None);
120 return NULL;
Raymond Hettinger5959c552002-08-19 03:19:09 +0000121}
122
123static PyObject*
Armin Rigof5bd3b42005-12-29 16:50:42 +0000124op_ipow(PyObject *s, PyObject *a)
125{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 PyObject *a1, *a2;
127 if (PyArg_UnpackTuple(a,"ipow", 2, 2, &a1, &a2))
128 return PyNumber_InPlacePower(a1, a2, Py_None);
129 return NULL;
Armin Rigof5bd3b42005-12-29 16:50:42 +0000130}
131
Guido van Rossum38fff8c2006-03-07 18:50:55 +0000132static PyObject *
133op_index(PyObject *s, PyObject *a)
134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 return PyNumber_Index(a);
Guido van Rossum38fff8c2006-03-07 18:50:55 +0000136}
137
Armin Rigof5bd3b42005-12-29 16:50:42 +0000138static PyObject*
Raymond Hettinger9543b342003-01-18 23:22:20 +0000139is_(PyObject *s, PyObject *a)
140{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000141 PyObject *a1, *a2, *result = NULL;
142 if (PyArg_UnpackTuple(a,"is_", 2, 2, &a1, &a2)) {
143 result = (a1 == a2) ? Py_True : Py_False;
144 Py_INCREF(result);
145 }
146 return result;
Raymond Hettinger9543b342003-01-18 23:22:20 +0000147}
148
149static PyObject*
150is_not(PyObject *s, PyObject *a)
151{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000152 PyObject *a1, *a2, *result = NULL;
153 if (PyArg_UnpackTuple(a,"is_not", 2, 2, &a1, &a2)) {
154 result = (a1 != a2) ? Py_True : Py_False;
155 Py_INCREF(result);
156 }
157 return result;
Raymond Hettinger9543b342003-01-18 23:22:20 +0000158}
159
Guido van Rossum037b9401996-07-30 16:55:54 +0000160#undef spam1
161#undef spam2
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +0000162#undef spam1o
163#undef spam1o
Christian Heimes6cea6552012-06-24 13:48:32 +0200164
165/* compare_digest **********************************************************/
166
167/*
168 * timing safe compare
169 *
170 * Returns 1 of the strings are equal.
171 * In case of len(a) != len(b) the function tries to keep the timing
172 * dependent on the length of b. CPU cache locally may still alter timing
173 * a bit.
174 */
175static int
176_tscmp(const unsigned char *a, const unsigned char *b,
177 Py_ssize_t len_a, Py_ssize_t len_b)
178{
179 /* The volatile type declarations make sure that the compiler has no
180 * chance to optimize and fold the code in any way that may change
181 * the timing.
182 */
183 volatile Py_ssize_t length;
184 volatile const unsigned char *left;
185 volatile const unsigned char *right;
186 Py_ssize_t i;
187 unsigned char result;
188
189 /* loop count depends on length of b */
190 length = len_b;
191 left = NULL;
192 right = b;
193
194 /* don't use else here to keep the amount of CPU instructions constant,
195 * volatile forces re-evaluation
196 * */
197 if (len_a == length) {
198 left = *((volatile const unsigned char**)&a);
199 result = 0;
200 }
201 if (len_a != length) {
202 left = b;
203 result = 1;
204 }
205
206 for (i=0; i < length; i++) {
207 result |= *left++ ^ *right++;
208 }
209
210 return (result == 0);
211}
212
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200213PyDoc_STRVAR(length_hint__doc__,
214"length_hint(obj, default=0) -> int\n"
215"Return an estimate of the number of items in obj.\n"
216"This is useful for presizing containers when building from an\n"
217"iterable.\n"
218"\n"
219"If the object supports len(), the result will be\n"
220"exact. Otherwise, it may over- or under-estimate by an\n"
221"arbitrary amount. The result will be an integer >= 0.");
222
223static PyObject *length_hint(PyObject *self, PyObject *args)
224{
225 PyObject *obj;
226 Py_ssize_t defaultvalue = 0, res;
227 if (!PyArg_ParseTuple(args, "O|n:length_hint", &obj, &defaultvalue)) {
228 return NULL;
229 }
230 res = PyObject_LengthHint(obj, defaultvalue);
231 if (res == -1 && PyErr_Occurred()) {
232 return NULL;
233 }
234 return PyLong_FromSsize_t(res);
235}
236
237
Christian Heimes6cea6552012-06-24 13:48:32 +0200238PyDoc_STRVAR(compare_digest__doc__,
239"compare_digest(a, b) -> bool\n"
240"\n"
Georg Brandla1bc35f2012-06-24 16:07:33 +0200241"Return 'a == b'. This function uses an approach designed to prevent\n"
242"timing analysis, making it appropriate for cryptography.\n"
243"a and b must both be of the same type: either str (ASCII only),\n"
R David Murray861470c2014-10-05 11:47:01 -0400244"or any bytes-like object.\n"
Christian Heimes6cea6552012-06-24 13:48:32 +0200245"\n"
Georg Brandla1bc35f2012-06-24 16:07:33 +0200246"Note: If a and b are of different lengths, or if an error occurs,\n"
Larry Hastings48986d62012-06-25 00:59:34 -0700247"a timing attack could theoretically reveal information about the\n"
248"types and lengths of a and b--but not their values.\n");
Christian Heimes6cea6552012-06-24 13:48:32 +0200249
250static PyObject*
251compare_digest(PyObject *self, PyObject *args)
252{
253 PyObject *a, *b;
254 int rc;
Christian Heimes6cea6552012-06-24 13:48:32 +0200255
256 if (!PyArg_ParseTuple(args, "OO:compare_digest", &a, &b)) {
257 return NULL;
258 }
259
260 /* ASCII unicode string */
261 if(PyUnicode_Check(a) && PyUnicode_Check(b)) {
262 if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
263 return NULL;
264 }
265 if (!PyUnicode_IS_ASCII(a) || !PyUnicode_IS_ASCII(b)) {
266 PyErr_SetString(PyExc_TypeError,
267 "comparing strings with non-ASCII characters is "
268 "not supported");
269 return NULL;
270 }
271
272 rc = _tscmp(PyUnicode_DATA(a),
273 PyUnicode_DATA(b),
274 PyUnicode_GET_LENGTH(a),
275 PyUnicode_GET_LENGTH(b));
276 }
277 /* fallback to buffer interface for bytes, bytesarray and other */
278 else {
279 Py_buffer view_a;
280 Py_buffer view_b;
281
Benjamin Peterson23a192d2014-05-11 16:17:02 -0700282 if (PyObject_CheckBuffer(a) == 0 && PyObject_CheckBuffer(b) == 0) {
Christian Heimes6cea6552012-06-24 13:48:32 +0200283 PyErr_Format(PyExc_TypeError,
284 "unsupported operand types(s) or combination of types: "
285 "'%.100s' and '%.100s'",
286 Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
287 return NULL;
288 }
289
290 if (PyObject_GetBuffer(a, &view_a, PyBUF_SIMPLE) == -1) {
291 return NULL;
292 }
293 if (view_a.ndim > 1) {
294 PyErr_SetString(PyExc_BufferError,
295 "Buffer must be single dimension");
296 PyBuffer_Release(&view_a);
297 return NULL;
298 }
299
300 if (PyObject_GetBuffer(b, &view_b, PyBUF_SIMPLE) == -1) {
301 PyBuffer_Release(&view_a);
302 return NULL;
303 }
304 if (view_b.ndim > 1) {
305 PyErr_SetString(PyExc_BufferError,
306 "Buffer must be single dimension");
307 PyBuffer_Release(&view_a);
308 PyBuffer_Release(&view_b);
309 return NULL;
310 }
311
312 rc = _tscmp((const unsigned char*)view_a.buf,
313 (const unsigned char*)view_b.buf,
314 view_a.len,
315 view_b.len);
316
317 PyBuffer_Release(&view_a);
318 PyBuffer_Release(&view_b);
319 }
320
Georg Brandl93b7d7e2012-06-24 13:54:51 +0200321 return PyBool_FromLong(rc);
Christian Heimes6cea6552012-06-24 13:48:32 +0200322}
323
324/* operator methods **********************************************************/
325
Neal Norwitz200788c2002-08-13 22:20:41 +0000326#define spam1(OP,DOC) {#OP, OP, METH_VARARGS, PyDoc_STR(DOC)},
Antoine Pitroua85017f2013-04-20 19:21:44 +0200327#define spam2(OP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +0000328#define spam1o(OP,DOC) {#OP, OP, METH_O, PyDoc_STR(DOC)},
Antoine Pitroua85017f2013-04-20 19:21:44 +0200329#define spam2o(OP,DOC) {#OP, op_##OP, METH_O, PyDoc_STR(DOC)},
Guido van Rossum037b9401996-07-30 16:55:54 +0000330
331static struct PyMethodDef operator_methods[] = {
Guido van Rossum037b9401996-07-30 16:55:54 +0000332
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +0000333spam1o(truth,
Guido van Rossum77f6a652002-04-03 22:41:51 +0000334 "truth(a) -- Return True if a is true, False otherwise.")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200335spam2(contains,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000336 "contains(a, b) -- Same as b in a (note reversed operands).")
Guido van Rossum17202301996-08-19 22:01:39 +0000337spam1(indexOf,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000338 "indexOf(a, b) -- Return the first index of b in a.")
Guido van Rossum17202301996-08-19 22:01:39 +0000339spam1(countOf,
340 "countOf(a, b) -- Return the number of times b occurs in a.")
Guido van Rossum037b9401996-07-30 16:55:54 +0000341
Raymond Hettinger9543b342003-01-18 23:22:20 +0000342spam1(is_, "is_(a, b) -- Same as a is b.")
343spam1(is_not, "is_not(a, b) -- Same as a is not b.")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200344spam2o(index, "index(a) -- Same as a.__index__()")
345spam2(add, "add(a, b) -- Same as a + b.")
346spam2(sub, "sub(a, b) -- Same as a - b.")
347spam2(mul, "mul(a, b) -- Same as a * b.")
Benjamin Petersond51374e2014-04-09 23:55:56 -0400348spam2(matmul, "matmul(a, b) -- Same as a @ b.")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200349spam2(floordiv, "floordiv(a, b) -- Same as a // b.")
350spam2(truediv, "truediv(a, b) -- Same as a / b.")
351spam2(mod, "mod(a, b) -- Same as a % b.")
352spam2o(neg, "neg(a) -- Same as -a.")
353spam2o(pos, "pos(a) -- Same as +a.")
354spam2o(abs, "abs(a) -- Same as abs(a).")
355spam2o(inv, "inv(a) -- Same as ~a.")
356spam2o(invert, "invert(a) -- Same as ~a.")
357spam2(lshift, "lshift(a, b) -- Same as a << b.")
358spam2(rshift, "rshift(a, b) -- Same as a >> b.")
359spam2o(not_, "not_(a) -- Same as not a.")
360spam2(and_, "and_(a, b) -- Same as a & b.")
361spam2(xor, "xor(a, b) -- Same as a ^ b.")
362spam2(or_, "or_(a, b) -- Same as a | b.")
363spam2(iadd, "a = iadd(a, b) -- Same as a += b.")
364spam2(isub, "a = isub(a, b) -- Same as a -= b.")
365spam2(imul, "a = imul(a, b) -- Same as a *= b.")
Benjamin Petersond51374e2014-04-09 23:55:56 -0400366spam2(imatmul, "a = imatmul(a, b) -- Same as a @= b.")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200367spam2(ifloordiv, "a = ifloordiv(a, b) -- Same as a //= b.")
368spam2(itruediv, "a = itruediv(a, b) -- Same as a /= b")
369spam2(imod, "a = imod(a, b) -- Same as a %= b.")
370spam2(ilshift, "a = ilshift(a, b) -- Same as a <<= b.")
371spam2(irshift, "a = irshift(a, b) -- Same as a >>= b.")
372spam2(iand, "a = iand(a, b) -- Same as a &= b.")
373spam2(ixor, "a = ixor(a, b) -- Same as a ^= b.")
374spam2(ior, "a = ior(a, b) -- Same as a |= b.")
375spam2(concat,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000376 "concat(a, b) -- Same as a + b, for a and b sequences.")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200377spam2(iconcat,
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000378 "a = iconcat(a, b) -- Same as a += b, for a and b sequences.")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200379spam2(getitem,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000380 "getitem(a, b) -- Same as a[b].")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200381spam2(setitem,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000382 "setitem(a, b, c) -- Same as a[b] = c.")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200383spam2(delitem,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000384 "delitem(a, b) -- Same as del a[b].")
Antoine Pitroua85017f2013-04-20 19:21:44 +0200385spam2(pow, "pow(a, b) -- Same as a ** b.")
386spam2(ipow, "a = ipow(a, b) -- Same as a **= b.")
387spam2(lt, "lt(a, b) -- Same as a<b.")
388spam2(le, "le(a, b) -- Same as a<=b.")
389spam2(eq, "eq(a, b) -- Same as a==b.")
390spam2(ne, "ne(a, b) -- Same as a!=b.")
391spam2(gt, "gt(a, b) -- Same as a>b.")
392spam2(ge, "ge(a, b) -- Same as a>=b.")
Guido van Rossum037b9401996-07-30 16:55:54 +0000393
Christian Heimes6cea6552012-06-24 13:48:32 +0200394 {"_compare_digest", (PyCFunction)compare_digest, METH_VARARGS,
395 compare_digest__doc__},
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200396 {"length_hint", (PyCFunction)length_hint, METH_VARARGS,
397 length_hint__doc__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000398 {NULL, NULL} /* sentinel */
Guido van Rossum037b9401996-07-30 16:55:54 +0000399
Guido van Rossum037b9401996-07-30 16:55:54 +0000400};
401
Raymond Hettinger166958b2003-12-01 13:18:39 +0000402/* itemgetter object **********************************************************/
Guido van Rossum037b9401996-07-30 16:55:54 +0000403
Raymond Hettinger166958b2003-12-01 13:18:39 +0000404typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000405 PyObject_HEAD
406 Py_ssize_t nitems;
407 PyObject *item;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000408} itemgetterobject;
409
410static PyTypeObject itemgetter_type;
411
412static PyObject *
413itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
414{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 itemgetterobject *ig;
416 PyObject *item;
417 Py_ssize_t nitems;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000418
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000419 if (!_PyArg_NoKeywords("itemgetter()", kwds))
420 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000421
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000422 nitems = PyTuple_GET_SIZE(args);
423 if (nitems <= 1) {
424 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item))
425 return NULL;
426 } else
427 item = args;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000428
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000429 /* create itemgetterobject structure */
430 ig = PyObject_GC_New(itemgetterobject, &itemgetter_type);
431 if (ig == NULL)
432 return NULL;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000433
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 Py_INCREF(item);
435 ig->item = item;
436 ig->nitems = nitems;
437
438 PyObject_GC_Track(ig);
439 return (PyObject *)ig;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000440}
441
442static void
443itemgetter_dealloc(itemgetterobject *ig)
444{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000445 PyObject_GC_UnTrack(ig);
446 Py_XDECREF(ig->item);
447 PyObject_GC_Del(ig);
Raymond Hettinger166958b2003-12-01 13:18:39 +0000448}
449
450static int
451itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
452{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000453 Py_VISIT(ig->item);
454 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000455}
456
457static PyObject *
458itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)
459{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 PyObject *obj, *result;
461 Py_ssize_t i, nitems=ig->nitems;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000462
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000463 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
464 return NULL;
465 if (nitems == 1)
466 return PyObject_GetItem(obj, ig->item);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000468 assert(PyTuple_Check(ig->item));
469 assert(PyTuple_GET_SIZE(ig->item) == nitems);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000470
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000471 result = PyTuple_New(nitems);
472 if (result == NULL)
473 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000475 for (i=0 ; i < nitems ; i++) {
476 PyObject *item, *val;
477 item = PyTuple_GET_ITEM(ig->item, i);
478 val = PyObject_GetItem(obj, item);
479 if (val == NULL) {
480 Py_DECREF(result);
481 return NULL;
482 }
483 PyTuple_SET_ITEM(result, i, val);
484 }
485 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000486}
487
488PyDoc_STRVAR(itemgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000489"itemgetter(item, ...) --> itemgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000490\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000491Return a callable object that fetches the given item(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +0300492After f = itemgetter(2), the call f(r) returns r[2].\n\
493After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000494
495static PyTypeObject itemgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496 PyVarObject_HEAD_INIT(NULL, 0)
497 "operator.itemgetter", /* tp_name */
498 sizeof(itemgetterobject), /* tp_basicsize */
499 0, /* tp_itemsize */
500 /* methods */
501 (destructor)itemgetter_dealloc, /* tp_dealloc */
502 0, /* tp_print */
503 0, /* tp_getattr */
504 0, /* tp_setattr */
505 0, /* tp_reserved */
506 0, /* tp_repr */
507 0, /* tp_as_number */
508 0, /* tp_as_sequence */
509 0, /* tp_as_mapping */
510 0, /* tp_hash */
511 (ternaryfunc)itemgetter_call, /* tp_call */
512 0, /* tp_str */
513 PyObject_GenericGetAttr, /* tp_getattro */
514 0, /* tp_setattro */
515 0, /* tp_as_buffer */
516 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
517 itemgetter_doc, /* tp_doc */
518 (traverseproc)itemgetter_traverse, /* tp_traverse */
519 0, /* tp_clear */
520 0, /* tp_richcompare */
521 0, /* tp_weaklistoffset */
522 0, /* tp_iter */
523 0, /* tp_iternext */
524 0, /* tp_methods */
525 0, /* tp_members */
526 0, /* tp_getset */
527 0, /* tp_base */
528 0, /* tp_dict */
529 0, /* tp_descr_get */
530 0, /* tp_descr_set */
531 0, /* tp_dictoffset */
532 0, /* tp_init */
533 0, /* tp_alloc */
534 itemgetter_new, /* tp_new */
535 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000536};
537
538
539/* attrgetter object **********************************************************/
540
541typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 PyObject_HEAD
543 Py_ssize_t nattrs;
544 PyObject *attr;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000545} attrgetterobject;
546
547static PyTypeObject attrgetter_type;
548
549static PyObject *
550attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
551{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000552 attrgetterobject *ag;
553 PyObject *attr;
Antoine Pitroue9745712010-10-31 15:26:04 +0000554 Py_ssize_t nattrs, idx, char_idx;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 if (!_PyArg_NoKeywords("attrgetter()", kwds))
557 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000558
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 nattrs = PyTuple_GET_SIZE(args);
560 if (nattrs <= 1) {
561 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))
562 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000563 }
564
565 attr = PyTuple_New(nattrs);
566 if (attr == NULL)
567 return NULL;
568
569 /* prepare attr while checking args */
570 for (idx = 0; idx < nattrs; ++idx) {
571 PyObject *item = PyTuple_GET_ITEM(args, idx);
572 Py_ssize_t item_len;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200573 void *data;
574 unsigned int kind;
Antoine Pitroue9745712010-10-31 15:26:04 +0000575 int dot_count;
576
577 if (!PyUnicode_Check(item)) {
578 PyErr_SetString(PyExc_TypeError,
579 "attribute name must be a string");
580 Py_DECREF(attr);
581 return NULL;
582 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200583 if (PyUnicode_READY(item)) {
584 Py_DECREF(attr);
585 return NULL;
586 }
587 item_len = PyUnicode_GET_LENGTH(item);
588 kind = PyUnicode_KIND(item);
589 data = PyUnicode_DATA(item);
Antoine Pitroue9745712010-10-31 15:26:04 +0000590
591 /* check whethere the string is dotted */
592 dot_count = 0;
593 for (char_idx = 0; char_idx < item_len; ++char_idx) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200594 if (PyUnicode_READ(kind, data, char_idx) == '.')
Antoine Pitroue9745712010-10-31 15:26:04 +0000595 ++dot_count;
596 }
597
598 if (dot_count == 0) {
599 Py_INCREF(item);
600 PyUnicode_InternInPlace(&item);
601 PyTuple_SET_ITEM(attr, idx, item);
602 } else { /* make it a tuple of non-dotted attrnames */
603 PyObject *attr_chain = PyTuple_New(dot_count + 1);
604 PyObject *attr_chain_item;
Antoine Pitrou87298c42010-10-31 21:03:01 +0000605 Py_ssize_t unibuff_from = 0;
606 Py_ssize_t unibuff_till = 0;
607 Py_ssize_t attr_chain_idx = 0;
Antoine Pitroue9745712010-10-31 15:26:04 +0000608
609 if (attr_chain == NULL) {
610 Py_DECREF(attr);
611 return NULL;
612 }
613
Antoine Pitroue9745712010-10-31 15:26:04 +0000614 for (; dot_count > 0; --dot_count) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200615 while (PyUnicode_READ(kind, data, unibuff_till) != '.') {
Antoine Pitroue9745712010-10-31 15:26:04 +0000616 ++unibuff_till;
617 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200618 attr_chain_item = PyUnicode_Substring(item,
619 unibuff_from,
620 unibuff_till);
Antoine Pitroue9745712010-10-31 15:26:04 +0000621 if (attr_chain_item == NULL) {
622 Py_DECREF(attr_chain);
623 Py_DECREF(attr);
624 return NULL;
625 }
626 PyUnicode_InternInPlace(&attr_chain_item);
627 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
628 ++attr_chain_idx;
629 unibuff_till = unibuff_from = unibuff_till + 1;
630 }
631
632 /* now add the last dotless name */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200633 attr_chain_item = PyUnicode_Substring(item,
634 unibuff_from, item_len);
Antoine Pitroue9745712010-10-31 15:26:04 +0000635 if (attr_chain_item == NULL) {
636 Py_DECREF(attr_chain);
637 Py_DECREF(attr);
638 return NULL;
639 }
640 PyUnicode_InternInPlace(&attr_chain_item);
641 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
642
643 PyTuple_SET_ITEM(attr, idx, attr_chain);
644 }
645 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000646
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000647 /* create attrgetterobject structure */
648 ag = PyObject_GC_New(attrgetterobject, &attrgetter_type);
Antoine Pitroue9745712010-10-31 15:26:04 +0000649 if (ag == NULL) {
650 Py_DECREF(attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000651 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000652 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000653
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000654 ag->attr = attr;
655 ag->nattrs = nattrs;
656
657 PyObject_GC_Track(ag);
658 return (PyObject *)ag;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000659}
660
661static void
662attrgetter_dealloc(attrgetterobject *ag)
663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000664 PyObject_GC_UnTrack(ag);
665 Py_XDECREF(ag->attr);
666 PyObject_GC_Del(ag);
Raymond Hettinger166958b2003-12-01 13:18:39 +0000667}
668
669static int
670attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
671{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 Py_VISIT(ag->attr);
673 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000674}
675
676static PyObject *
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000677dotted_getattr(PyObject *obj, PyObject *attr)
678{
Antoine Pitroue9745712010-10-31 15:26:04 +0000679 PyObject *newobj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000680
Antoine Pitroue9745712010-10-31 15:26:04 +0000681 /* attr is either a tuple or instance of str.
682 Ensured by the setup code of attrgetter_new */
683 if (PyTuple_CheckExact(attr)) { /* chained getattr */
684 Py_ssize_t name_idx = 0, name_count;
685 PyObject *attr_name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000686
Antoine Pitroue9745712010-10-31 15:26:04 +0000687 name_count = PyTuple_GET_SIZE(attr);
688 Py_INCREF(obj);
689 for (name_idx = 0; name_idx < name_count; ++name_idx) {
690 attr_name = PyTuple_GET_ITEM(attr, name_idx);
691 newobj = PyObject_GetAttr(obj, attr_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000692 Py_DECREF(obj);
Antoine Pitroue9745712010-10-31 15:26:04 +0000693 if (newobj == NULL) {
694 return NULL;
695 }
696 /* here */
697 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 }
Antoine Pitroue9745712010-10-31 15:26:04 +0000699 } else { /* single getattr */
700 newobj = PyObject_GetAttr(obj, attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 if (newobj == NULL)
702 return NULL;
703 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 return obj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000707}
708
709static PyObject *
Raymond Hettinger166958b2003-12-01 13:18:39 +0000710attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 PyObject *obj, *result;
713 Py_ssize_t i, nattrs=ag->nattrs;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000714
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000715 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
716 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000717 if (ag->nattrs == 1) /* ag->attr is always a tuple */
718 return dotted_getattr(obj, PyTuple_GET_ITEM(ag->attr, 0));
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 assert(PyTuple_Check(ag->attr));
721 assert(PyTuple_GET_SIZE(ag->attr) == nattrs);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000722
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000723 result = PyTuple_New(nattrs);
724 if (result == NULL)
725 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 for (i=0 ; i < nattrs ; i++) {
728 PyObject *attr, *val;
729 attr = PyTuple_GET_ITEM(ag->attr, i);
730 val = dotted_getattr(obj, attr);
731 if (val == NULL) {
732 Py_DECREF(result);
733 return NULL;
734 }
735 PyTuple_SET_ITEM(result, i, val);
736 }
737 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000738}
739
740PyDoc_STRVAR(attrgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000741"attrgetter(attr, ...) --> attrgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000742\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000743Return a callable object that fetches the given attribute(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +0300744After f = attrgetter('name'), the call f(r) returns r.name.\n\
745After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
746After h = attrgetter('name.first', 'name.last'), the call h(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000747(r.name.first, r.name.last).");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000748
749static PyTypeObject attrgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750 PyVarObject_HEAD_INIT(NULL, 0)
751 "operator.attrgetter", /* tp_name */
752 sizeof(attrgetterobject), /* tp_basicsize */
753 0, /* tp_itemsize */
754 /* methods */
755 (destructor)attrgetter_dealloc, /* tp_dealloc */
756 0, /* tp_print */
757 0, /* tp_getattr */
758 0, /* tp_setattr */
759 0, /* tp_reserved */
760 0, /* tp_repr */
761 0, /* tp_as_number */
762 0, /* tp_as_sequence */
763 0, /* tp_as_mapping */
764 0, /* tp_hash */
765 (ternaryfunc)attrgetter_call, /* tp_call */
766 0, /* tp_str */
767 PyObject_GenericGetAttr, /* tp_getattro */
768 0, /* tp_setattro */
769 0, /* tp_as_buffer */
770 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
771 attrgetter_doc, /* tp_doc */
772 (traverseproc)attrgetter_traverse, /* tp_traverse */
773 0, /* tp_clear */
774 0, /* tp_richcompare */
775 0, /* tp_weaklistoffset */
776 0, /* tp_iter */
777 0, /* tp_iternext */
778 0, /* tp_methods */
779 0, /* tp_members */
780 0, /* tp_getset */
781 0, /* tp_base */
782 0, /* tp_dict */
783 0, /* tp_descr_get */
784 0, /* tp_descr_set */
785 0, /* tp_dictoffset */
786 0, /* tp_init */
787 0, /* tp_alloc */
788 attrgetter_new, /* tp_new */
789 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000790};
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000791
792
793/* methodcaller object **********************************************************/
794
795typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000796 PyObject_HEAD
797 PyObject *name;
798 PyObject *args;
799 PyObject *kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000800} methodcallerobject;
801
802static PyTypeObject methodcaller_type;
803
804static PyObject *
805methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
806{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 methodcallerobject *mc;
808 PyObject *name, *newargs;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000809
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000810 if (PyTuple_GET_SIZE(args) < 1) {
811 PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "
812 "one argument, the method name");
813 return NULL;
814 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000815
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 /* create methodcallerobject structure */
817 mc = PyObject_GC_New(methodcallerobject, &methodcaller_type);
818 if (mc == NULL)
819 return NULL;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000820
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000821 newargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
822 if (newargs == NULL) {
823 Py_DECREF(mc);
824 return NULL;
825 }
826 mc->args = newargs;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 name = PyTuple_GET_ITEM(args, 0);
829 Py_INCREF(name);
830 mc->name = name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000831
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000832 Py_XINCREF(kwds);
833 mc->kwds = kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000834
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 PyObject_GC_Track(mc);
836 return (PyObject *)mc;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000837}
838
839static void
840methodcaller_dealloc(methodcallerobject *mc)
841{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000842 PyObject_GC_UnTrack(mc);
843 Py_XDECREF(mc->name);
844 Py_XDECREF(mc->args);
845 Py_XDECREF(mc->kwds);
846 PyObject_GC_Del(mc);
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000847}
848
849static int
850methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
851{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000852 Py_VISIT(mc->args);
853 Py_VISIT(mc->kwds);
854 return 0;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000855}
856
857static PyObject *
858methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
859{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000860 PyObject *method, *obj, *result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000861
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000862 if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
863 return NULL;
864 method = PyObject_GetAttr(obj, mc->name);
865 if (method == NULL)
866 return NULL;
867 result = PyObject_Call(method, mc->args, mc->kwds);
868 Py_DECREF(method);
869 return result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000870}
871
872PyDoc_STRVAR(methodcaller_doc,
873"methodcaller(name, ...) --> methodcaller object\n\
874\n\
875Return a callable object that calls the given method on its operand.\n\
Antoine Pitroua85017f2013-04-20 19:21:44 +0200876After f = methodcaller('name'), the call f(r) returns r.name().\n\
877After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000878r.name('date', foo=1).");
879
880static PyTypeObject methodcaller_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 PyVarObject_HEAD_INIT(NULL, 0)
882 "operator.methodcaller", /* tp_name */
883 sizeof(methodcallerobject), /* tp_basicsize */
884 0, /* tp_itemsize */
885 /* methods */
886 (destructor)methodcaller_dealloc, /* tp_dealloc */
887 0, /* tp_print */
888 0, /* tp_getattr */
889 0, /* tp_setattr */
890 0, /* tp_reserved */
891 0, /* tp_repr */
892 0, /* tp_as_number */
893 0, /* tp_as_sequence */
894 0, /* tp_as_mapping */
895 0, /* tp_hash */
896 (ternaryfunc)methodcaller_call, /* tp_call */
897 0, /* tp_str */
898 PyObject_GenericGetAttr, /* tp_getattro */
899 0, /* tp_setattro */
900 0, /* tp_as_buffer */
901 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
902 methodcaller_doc, /* tp_doc */
903 (traverseproc)methodcaller_traverse, /* tp_traverse */
904 0, /* tp_clear */
905 0, /* tp_richcompare */
906 0, /* tp_weaklistoffset */
907 0, /* tp_iter */
908 0, /* tp_iternext */
909 0, /* tp_methods */
910 0, /* tp_members */
911 0, /* tp_getset */
912 0, /* tp_base */
913 0, /* tp_dict */
914 0, /* tp_descr_get */
915 0, /* tp_descr_set */
916 0, /* tp_dictoffset */
917 0, /* tp_init */
918 0, /* tp_alloc */
919 methodcaller_new, /* tp_new */
920 0, /* tp_free */
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000921};
922
923
Antoine Pitroua85017f2013-04-20 19:21:44 +0200924/* Initialization function for the module (*must* be called PyInit__operator) */
Martin v. Löwis1a214512008-06-11 05:26:20 +0000925
926
927static struct PyModuleDef operatormodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000928 PyModuleDef_HEAD_INIT,
Antoine Pitroua85017f2013-04-20 19:21:44 +0200929 "_operator",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000930 operator_doc,
931 -1,
932 operator_methods,
933 NULL,
934 NULL,
935 NULL,
936 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000937};
Guido van Rossum037b9401996-07-30 16:55:54 +0000938
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000939PyMODINIT_FUNC
Antoine Pitroua85017f2013-04-20 19:21:44 +0200940PyInit__operator(void)
Guido van Rossum037b9401996-07-30 16:55:54 +0000941{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 PyObject *m;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000943
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000944 /* Create the module and add the functions */
945 m = PyModule_Create(&operatormodule);
946 if (m == NULL)
947 return NULL;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000948
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000949 if (PyType_Ready(&itemgetter_type) < 0)
950 return NULL;
951 Py_INCREF(&itemgetter_type);
952 PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 if (PyType_Ready(&attrgetter_type) < 0)
955 return NULL;
956 Py_INCREF(&attrgetter_type);
957 PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);
958
959 if (PyType_Ready(&methodcaller_type) < 0)
960 return NULL;
961 Py_INCREF(&methodcaller_type);
962 PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);
963 return m;
Guido van Rossum037b9401996-07-30 16:55:54 +0000964}