blob: c5369a50216d98b1dbabebb1058174af0f108057 [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)
Fred Drake428e75f2001-08-09 20:14:34 +000072spam2(op_floordiv , PyNumber_FloorDivide)
73spam2(op_truediv , PyNumber_TrueDivide)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000074spam2(op_mod , PyNumber_Remainder)
75spam1(op_neg , PyNumber_Negative)
76spam1(op_pos , PyNumber_Positive)
77spam1(op_abs , PyNumber_Absolute)
78spam1(op_inv , PyNumber_Invert)
Fred Drakeea4d3f02000-09-17 16:09:27 +000079spam1(op_invert , PyNumber_Invert)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000080spam2(op_lshift , PyNumber_Lshift)
81spam2(op_rshift , PyNumber_Rshift)
Guido van Rossum99c185e1998-04-09 17:54:26 +000082spami(op_not_ , PyObject_Not)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000083spam2(op_and_ , PyNumber_And)
84spam2(op_xor , PyNumber_Xor)
85spam2(op_or_ , PyNumber_Or)
Armin Rigof5bd3b42005-12-29 16:50:42 +000086spam2(op_iadd , PyNumber_InPlaceAdd)
87spam2(op_isub , PyNumber_InPlaceSubtract)
88spam2(op_imul , PyNumber_InPlaceMultiply)
Armin Rigof5bd3b42005-12-29 16:50:42 +000089spam2(op_ifloordiv , PyNumber_InPlaceFloorDivide)
90spam2(op_itruediv , PyNumber_InPlaceTrueDivide)
91spam2(op_imod , PyNumber_InPlaceRemainder)
92spam2(op_ilshift , PyNumber_InPlaceLshift)
93spam2(op_irshift , PyNumber_InPlaceRshift)
94spam2(op_iand , PyNumber_InPlaceAnd)
95spam2(op_ixor , PyNumber_InPlaceXor)
96spam2(op_ior , PyNumber_InPlaceOr)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +000097spam2(op_concat , PySequence_Concat)
Armin Rigof5bd3b42005-12-29 16:50:42 +000098spam2(op_iconcat , PySequence_InPlaceConcat)
Guido van Rossum77f6a652002-04-03 22:41:51 +000099spami2b(op_contains , PySequence_Contains)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000100spamn2(indexOf , PySequence_Index)
101spamn2(countOf , PySequence_Count)
Guido van Rossumc9fb47e1996-08-21 17:40:51 +0000102spam2(op_getitem , PyObject_GetItem)
103spam2n(op_delitem , PyObject_DelItem)
104spam3n(op_setitem , PyObject_SetItem)
Fred Drake428e75f2001-08-09 20:14:34 +0000105spamrc(op_lt , Py_LT)
106spamrc(op_le , Py_LE)
107spamrc(op_eq , Py_EQ)
108spamrc(op_ne , Py_NE)
109spamrc(op_gt , Py_GT)
110spamrc(op_ge , Py_GE)
Guido van Rossum037b9401996-07-30 16:55:54 +0000111
112static PyObject*
Raymond Hettinger5959c552002-08-19 03:19:09 +0000113op_pow(PyObject *s, PyObject *a)
114{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000115 PyObject *a1, *a2;
116 if (PyArg_UnpackTuple(a,"pow", 2, 2, &a1, &a2))
117 return PyNumber_Power(a1, a2, Py_None);
118 return NULL;
Raymond Hettinger5959c552002-08-19 03:19:09 +0000119}
120
121static PyObject*
Armin Rigof5bd3b42005-12-29 16:50:42 +0000122op_ipow(PyObject *s, PyObject *a)
123{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000124 PyObject *a1, *a2;
125 if (PyArg_UnpackTuple(a,"ipow", 2, 2, &a1, &a2))
126 return PyNumber_InPlacePower(a1, a2, Py_None);
127 return NULL;
Armin Rigof5bd3b42005-12-29 16:50:42 +0000128}
129
Guido van Rossum38fff8c2006-03-07 18:50:55 +0000130static PyObject *
131op_index(PyObject *s, PyObject *a)
132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 return PyNumber_Index(a);
Guido van Rossum38fff8c2006-03-07 18:50:55 +0000134}
135
Armin Rigof5bd3b42005-12-29 16:50:42 +0000136static PyObject*
Raymond Hettinger9543b342003-01-18 23:22:20 +0000137is_(PyObject *s, PyObject *a)
138{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 PyObject *a1, *a2, *result = NULL;
140 if (PyArg_UnpackTuple(a,"is_", 2, 2, &a1, &a2)) {
141 result = (a1 == a2) ? Py_True : Py_False;
142 Py_INCREF(result);
143 }
144 return result;
Raymond Hettinger9543b342003-01-18 23:22:20 +0000145}
146
147static PyObject*
148is_not(PyObject *s, PyObject *a)
149{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 PyObject *a1, *a2, *result = NULL;
151 if (PyArg_UnpackTuple(a,"is_not", 2, 2, &a1, &a2)) {
152 result = (a1 != a2) ? Py_True : Py_False;
153 Py_INCREF(result);
154 }
155 return result;
Raymond Hettinger9543b342003-01-18 23:22:20 +0000156}
157
Guido van Rossum037b9401996-07-30 16:55:54 +0000158#undef spam1
159#undef spam2
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +0000160#undef spam1o
161#undef spam1o
Christian Heimes6cea6552012-06-24 13:48:32 +0200162
163/* compare_digest **********************************************************/
164
165/*
166 * timing safe compare
167 *
168 * Returns 1 of the strings are equal.
169 * In case of len(a) != len(b) the function tries to keep the timing
170 * dependent on the length of b. CPU cache locally may still alter timing
171 * a bit.
172 */
173static int
174_tscmp(const unsigned char *a, const unsigned char *b,
175 Py_ssize_t len_a, Py_ssize_t len_b)
176{
177 /* The volatile type declarations make sure that the compiler has no
178 * chance to optimize and fold the code in any way that may change
179 * the timing.
180 */
181 volatile Py_ssize_t length;
182 volatile const unsigned char *left;
183 volatile const unsigned char *right;
184 Py_ssize_t i;
185 unsigned char result;
186
187 /* loop count depends on length of b */
188 length = len_b;
189 left = NULL;
190 right = b;
191
192 /* don't use else here to keep the amount of CPU instructions constant,
193 * volatile forces re-evaluation
194 * */
195 if (len_a == length) {
196 left = *((volatile const unsigned char**)&a);
197 result = 0;
198 }
199 if (len_a != length) {
200 left = b;
201 result = 1;
202 }
203
204 for (i=0; i < length; i++) {
205 result |= *left++ ^ *right++;
206 }
207
208 return (result == 0);
209}
210
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200211PyDoc_STRVAR(length_hint__doc__,
212"length_hint(obj, default=0) -> int\n"
213"Return an estimate of the number of items in obj.\n"
214"This is useful for presizing containers when building from an\n"
215"iterable.\n"
216"\n"
217"If the object supports len(), the result will be\n"
218"exact. Otherwise, it may over- or under-estimate by an\n"
219"arbitrary amount. The result will be an integer >= 0.");
220
221static PyObject *length_hint(PyObject *self, PyObject *args)
222{
223 PyObject *obj;
224 Py_ssize_t defaultvalue = 0, res;
225 if (!PyArg_ParseTuple(args, "O|n:length_hint", &obj, &defaultvalue)) {
226 return NULL;
227 }
228 res = PyObject_LengthHint(obj, defaultvalue);
229 if (res == -1 && PyErr_Occurred()) {
230 return NULL;
231 }
232 return PyLong_FromSsize_t(res);
233}
234
235
Christian Heimes6cea6552012-06-24 13:48:32 +0200236PyDoc_STRVAR(compare_digest__doc__,
237"compare_digest(a, b) -> bool\n"
238"\n"
Georg Brandla1bc35f2012-06-24 16:07:33 +0200239"Return 'a == b'. This function uses an approach designed to prevent\n"
240"timing analysis, making it appropriate for cryptography.\n"
241"a and b must both be of the same type: either str (ASCII only),\n"
242"or any type that supports the buffer protocol (e.g. bytes).\n"
Christian Heimes6cea6552012-06-24 13:48:32 +0200243"\n"
Georg Brandla1bc35f2012-06-24 16:07:33 +0200244"Note: If a and b are of different lengths, or if an error occurs,\n"
Larry Hastings48986d62012-06-25 00:59:34 -0700245"a timing attack could theoretically reveal information about the\n"
246"types and lengths of a and b--but not their values.\n");
Christian Heimes6cea6552012-06-24 13:48:32 +0200247
248static PyObject*
249compare_digest(PyObject *self, PyObject *args)
250{
251 PyObject *a, *b;
252 int rc;
Christian Heimes6cea6552012-06-24 13:48:32 +0200253
254 if (!PyArg_ParseTuple(args, "OO:compare_digest", &a, &b)) {
255 return NULL;
256 }
257
258 /* ASCII unicode string */
259 if(PyUnicode_Check(a) && PyUnicode_Check(b)) {
260 if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
261 return NULL;
262 }
263 if (!PyUnicode_IS_ASCII(a) || !PyUnicode_IS_ASCII(b)) {
264 PyErr_SetString(PyExc_TypeError,
265 "comparing strings with non-ASCII characters is "
266 "not supported");
267 return NULL;
268 }
269
270 rc = _tscmp(PyUnicode_DATA(a),
271 PyUnicode_DATA(b),
272 PyUnicode_GET_LENGTH(a),
273 PyUnicode_GET_LENGTH(b));
274 }
275 /* fallback to buffer interface for bytes, bytesarray and other */
276 else {
277 Py_buffer view_a;
278 Py_buffer view_b;
279
280 if ((PyObject_CheckBuffer(a) == 0) & (PyObject_CheckBuffer(b) == 0)) {
281 PyErr_Format(PyExc_TypeError,
282 "unsupported operand types(s) or combination of types: "
283 "'%.100s' and '%.100s'",
284 Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
285 return NULL;
286 }
287
288 if (PyObject_GetBuffer(a, &view_a, PyBUF_SIMPLE) == -1) {
289 return NULL;
290 }
291 if (view_a.ndim > 1) {
292 PyErr_SetString(PyExc_BufferError,
293 "Buffer must be single dimension");
294 PyBuffer_Release(&view_a);
295 return NULL;
296 }
297
298 if (PyObject_GetBuffer(b, &view_b, PyBUF_SIMPLE) == -1) {
299 PyBuffer_Release(&view_a);
300 return NULL;
301 }
302 if (view_b.ndim > 1) {
303 PyErr_SetString(PyExc_BufferError,
304 "Buffer must be single dimension");
305 PyBuffer_Release(&view_a);
306 PyBuffer_Release(&view_b);
307 return NULL;
308 }
309
310 rc = _tscmp((const unsigned char*)view_a.buf,
311 (const unsigned char*)view_b.buf,
312 view_a.len,
313 view_b.len);
314
315 PyBuffer_Release(&view_a);
316 PyBuffer_Release(&view_b);
317 }
318
Georg Brandl93b7d7e2012-06-24 13:54:51 +0200319 return PyBool_FromLong(rc);
Christian Heimes6cea6552012-06-24 13:48:32 +0200320}
321
322/* operator methods **********************************************************/
323
Neal Norwitz200788c2002-08-13 22:20:41 +0000324#define spam1(OP,DOC) {#OP, OP, METH_VARARGS, PyDoc_STR(DOC)},
Armin Rigoc4308d52005-12-29 14:39:28 +0000325#define spam2(OP,ALTOP,DOC) {#OP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)}, \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 {#ALTOP, op_##OP, METH_VARARGS, PyDoc_STR(DOC)},
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +0000327#define spam1o(OP,DOC) {#OP, OP, METH_O, PyDoc_STR(DOC)},
Armin Rigoc4308d52005-12-29 14:39:28 +0000328#define spam2o(OP,ALTOP,DOC) {#OP, op_##OP, METH_O, PyDoc_STR(DOC)}, \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 {#ALTOP, 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.")
Fred Drakeea4d3f02000-09-17 16:09:27 +0000335spam2(contains,__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.")
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000344spam2o(index, __index__, "index(a) -- Same as a.__index__()")
Guido van Rossum832f6d21998-05-22 18:12:59 +0000345spam2(add,__add__, "add(a, b) -- Same as a + b.")
346spam2(sub,__sub__, "sub(a, b) -- Same as a - b.")
347spam2(mul,__mul__, "mul(a, b) -- Same as a * b.")
Fred Drake428e75f2001-08-09 20:14:34 +0000348spam2(floordiv,__floordiv__, "floordiv(a, b) -- Same as a // b.")
Neal Norwitzbcc0db82006-03-24 08:14:36 +0000349spam2(truediv,__truediv__, "truediv(a, b) -- Same as a / b.")
Guido van Rossum832f6d21998-05-22 18:12:59 +0000350spam2(mod,__mod__, "mod(a, b) -- Same as a % b.")
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +0000351spam2o(neg,__neg__, "neg(a) -- Same as -a.")
352spam2o(pos,__pos__, "pos(a) -- Same as +a.")
353spam2o(abs,__abs__, "abs(a) -- Same as abs(a).")
354spam2o(inv,__inv__, "inv(a) -- Same as ~a.")
355spam2o(invert,__invert__, "invert(a) -- Same as ~a.")
Guido van Rossum832f6d21998-05-22 18:12:59 +0000356spam2(lshift,__lshift__, "lshift(a, b) -- Same as a << b.")
357spam2(rshift,__rshift__, "rshift(a, b) -- Same as a >> b.")
Raymond Hettinger36cd2bf2003-01-03 08:24:58 +0000358spam2o(not_,__not__, "not_(a) -- Same as not a.")
Guido van Rossum832f6d21998-05-22 18:12:59 +0000359spam2(and_,__and__, "and_(a, b) -- Same as a & b.")
360spam2(xor,__xor__, "xor(a, b) -- Same as a ^ b.")
361spam2(or_,__or__, "or_(a, b) -- Same as a | b.")
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000362spam2(iadd,__iadd__, "a = iadd(a, b) -- Same as a += b.")
363spam2(isub,__isub__, "a = isub(a, b) -- Same as a -= b.")
364spam2(imul,__imul__, "a = imul(a, b) -- Same as a *= b.")
365spam2(ifloordiv,__ifloordiv__, "a = ifloordiv(a, b) -- Same as a //= b.")
366spam2(itruediv,__itruediv__, "a = itruediv(a, b) -- Same as a /= b")
367spam2(imod,__imod__, "a = imod(a, b) -- Same as a %= b.")
368spam2(ilshift,__ilshift__, "a = ilshift(a, b) -- Same as a <<= b.")
369spam2(irshift,__irshift__, "a = irshift(a, b) -- Same as a >>= b.")
370spam2(iand,__iand__, "a = iand(a, b) -- Same as a &= b.")
371spam2(ixor,__ixor__, "a = ixor(a, b) -- Same as a ^= b.")
372spam2(ior,__ior__, "a = ior(a, b) -- Same as a |= b.")
Guido van Rossum17202301996-08-19 22:01:39 +0000373spam2(concat,__concat__,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000374 "concat(a, b) -- Same as a + b, for a and b sequences.")
Armin Rigof5bd3b42005-12-29 16:50:42 +0000375spam2(iconcat,__iconcat__,
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000376 "a = iconcat(a, b) -- Same as a += b, for a and b sequences.")
Guido van Rossum17202301996-08-19 22:01:39 +0000377spam2(getitem,__getitem__,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000378 "getitem(a, b) -- Same as a[b].")
Guido van Rossum17202301996-08-19 22:01:39 +0000379spam2(setitem,__setitem__,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000380 "setitem(a, b, c) -- Same as a[b] = c.")
Guido van Rossumc9fb47e1996-08-21 17:40:51 +0000381spam2(delitem,__delitem__,
Guido van Rossum832f6d21998-05-22 18:12:59 +0000382 "delitem(a, b) -- Same as del a[b].")
Armin Rigof5bd3b42005-12-29 16:50:42 +0000383spam2(pow,__pow__, "pow(a, b) -- Same as a ** b.")
Benjamin Petersona0dfa822009-11-13 02:25:08 +0000384spam2(ipow,__ipow__, "a = ipow(a, b) -- Same as a **= b.")
Fred Drake428e75f2001-08-09 20:14:34 +0000385spam2(lt,__lt__, "lt(a, b) -- Same as a<b.")
386spam2(le,__le__, "le(a, b) -- Same as a<=b.")
387spam2(eq,__eq__, "eq(a, b) -- Same as a==b.")
388spam2(ne,__ne__, "ne(a, b) -- Same as a!=b.")
389spam2(gt,__gt__, "gt(a, b) -- Same as a>b.")
390spam2(ge,__ge__, "ge(a, b) -- Same as a>=b.")
Guido van Rossum037b9401996-07-30 16:55:54 +0000391
Christian Heimes6cea6552012-06-24 13:48:32 +0200392 {"_compare_digest", (PyCFunction)compare_digest, METH_VARARGS,
393 compare_digest__doc__},
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200394 {"length_hint", (PyCFunction)length_hint, METH_VARARGS,
395 length_hint__doc__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 {NULL, NULL} /* sentinel */
Guido van Rossum037b9401996-07-30 16:55:54 +0000397
Guido van Rossum037b9401996-07-30 16:55:54 +0000398};
399
Raymond Hettinger166958b2003-12-01 13:18:39 +0000400/* itemgetter object **********************************************************/
Guido van Rossum037b9401996-07-30 16:55:54 +0000401
Raymond Hettinger166958b2003-12-01 13:18:39 +0000402typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 PyObject_HEAD
404 Py_ssize_t nitems;
405 PyObject *item;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000406} itemgetterobject;
407
408static PyTypeObject itemgetter_type;
409
410static PyObject *
411itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
412{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 itemgetterobject *ig;
414 PyObject *item;
415 Py_ssize_t nitems;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 if (!_PyArg_NoKeywords("itemgetter()", kwds))
418 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 nitems = PyTuple_GET_SIZE(args);
421 if (nitems <= 1) {
422 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item))
423 return NULL;
424 } else
425 item = args;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000427 /* create itemgetterobject structure */
428 ig = PyObject_GC_New(itemgetterobject, &itemgetter_type);
429 if (ig == NULL)
430 return NULL;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000432 Py_INCREF(item);
433 ig->item = item;
434 ig->nitems = nitems;
435
436 PyObject_GC_Track(ig);
437 return (PyObject *)ig;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000438}
439
440static void
441itemgetter_dealloc(itemgetterobject *ig)
442{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 PyObject_GC_UnTrack(ig);
444 Py_XDECREF(ig->item);
445 PyObject_GC_Del(ig);
Raymond Hettinger166958b2003-12-01 13:18:39 +0000446}
447
448static int
449itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
450{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000451 Py_VISIT(ig->item);
452 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000453}
454
455static PyObject *
456itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)
457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000458 PyObject *obj, *result;
459 Py_ssize_t i, nitems=ig->nitems;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000460
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
462 return NULL;
463 if (nitems == 1)
464 return PyObject_GetItem(obj, ig->item);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000465
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000466 assert(PyTuple_Check(ig->item));
467 assert(PyTuple_GET_SIZE(ig->item) == nitems);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000468
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 result = PyTuple_New(nitems);
470 if (result == NULL)
471 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 for (i=0 ; i < nitems ; i++) {
474 PyObject *item, *val;
475 item = PyTuple_GET_ITEM(ig->item, i);
476 val = PyObject_GetItem(obj, item);
477 if (val == NULL) {
478 Py_DECREF(result);
479 return NULL;
480 }
481 PyTuple_SET_ITEM(result, i, val);
482 }
483 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000484}
485
486PyDoc_STRVAR(itemgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000487"itemgetter(item, ...) --> itemgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000488\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000489Return a callable object that fetches the given item(s) from its operand.\n\
490After, f=itemgetter(2), the call f(r) returns r[2].\n\
491After, g=itemgetter(2,5,3), the call g(r) returns (r[2], r[5], r[3])");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000492
493static PyTypeObject itemgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000494 PyVarObject_HEAD_INIT(NULL, 0)
495 "operator.itemgetter", /* tp_name */
496 sizeof(itemgetterobject), /* tp_basicsize */
497 0, /* tp_itemsize */
498 /* methods */
499 (destructor)itemgetter_dealloc, /* tp_dealloc */
500 0, /* tp_print */
501 0, /* tp_getattr */
502 0, /* tp_setattr */
503 0, /* tp_reserved */
504 0, /* tp_repr */
505 0, /* tp_as_number */
506 0, /* tp_as_sequence */
507 0, /* tp_as_mapping */
508 0, /* tp_hash */
509 (ternaryfunc)itemgetter_call, /* tp_call */
510 0, /* tp_str */
511 PyObject_GenericGetAttr, /* tp_getattro */
512 0, /* tp_setattro */
513 0, /* tp_as_buffer */
514 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
515 itemgetter_doc, /* tp_doc */
516 (traverseproc)itemgetter_traverse, /* tp_traverse */
517 0, /* tp_clear */
518 0, /* tp_richcompare */
519 0, /* tp_weaklistoffset */
520 0, /* tp_iter */
521 0, /* tp_iternext */
522 0, /* tp_methods */
523 0, /* tp_members */
524 0, /* tp_getset */
525 0, /* tp_base */
526 0, /* tp_dict */
527 0, /* tp_descr_get */
528 0, /* tp_descr_set */
529 0, /* tp_dictoffset */
530 0, /* tp_init */
531 0, /* tp_alloc */
532 itemgetter_new, /* tp_new */
533 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000534};
535
536
537/* attrgetter object **********************************************************/
538
539typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 PyObject_HEAD
541 Py_ssize_t nattrs;
542 PyObject *attr;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000543} attrgetterobject;
544
545static PyTypeObject attrgetter_type;
546
547static PyObject *
548attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
549{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 attrgetterobject *ag;
551 PyObject *attr;
Antoine Pitroue9745712010-10-31 15:26:04 +0000552 Py_ssize_t nattrs, idx, char_idx;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000553
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 if (!_PyArg_NoKeywords("attrgetter()", kwds))
555 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000556
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 nattrs = PyTuple_GET_SIZE(args);
558 if (nattrs <= 1) {
559 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))
560 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000561 }
562
563 attr = PyTuple_New(nattrs);
564 if (attr == NULL)
565 return NULL;
566
567 /* prepare attr while checking args */
568 for (idx = 0; idx < nattrs; ++idx) {
569 PyObject *item = PyTuple_GET_ITEM(args, idx);
570 Py_ssize_t item_len;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200571 void *data;
572 unsigned int kind;
Antoine Pitroue9745712010-10-31 15:26:04 +0000573 int dot_count;
574
575 if (!PyUnicode_Check(item)) {
576 PyErr_SetString(PyExc_TypeError,
577 "attribute name must be a string");
578 Py_DECREF(attr);
579 return NULL;
580 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200581 if (PyUnicode_READY(item)) {
582 Py_DECREF(attr);
583 return NULL;
584 }
585 item_len = PyUnicode_GET_LENGTH(item);
586 kind = PyUnicode_KIND(item);
587 data = PyUnicode_DATA(item);
Antoine Pitroue9745712010-10-31 15:26:04 +0000588
589 /* check whethere the string is dotted */
590 dot_count = 0;
591 for (char_idx = 0; char_idx < item_len; ++char_idx) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200592 if (PyUnicode_READ(kind, data, char_idx) == '.')
Antoine Pitroue9745712010-10-31 15:26:04 +0000593 ++dot_count;
594 }
595
596 if (dot_count == 0) {
597 Py_INCREF(item);
598 PyUnicode_InternInPlace(&item);
599 PyTuple_SET_ITEM(attr, idx, item);
600 } else { /* make it a tuple of non-dotted attrnames */
601 PyObject *attr_chain = PyTuple_New(dot_count + 1);
602 PyObject *attr_chain_item;
Antoine Pitrou87298c42010-10-31 21:03:01 +0000603 Py_ssize_t unibuff_from = 0;
604 Py_ssize_t unibuff_till = 0;
605 Py_ssize_t attr_chain_idx = 0;
Antoine Pitroue9745712010-10-31 15:26:04 +0000606
607 if (attr_chain == NULL) {
608 Py_DECREF(attr);
609 return NULL;
610 }
611
Antoine Pitroue9745712010-10-31 15:26:04 +0000612 for (; dot_count > 0; --dot_count) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200613 while (PyUnicode_READ(kind, data, unibuff_till) != '.') {
Antoine Pitroue9745712010-10-31 15:26:04 +0000614 ++unibuff_till;
615 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200616 attr_chain_item = PyUnicode_Substring(item,
617 unibuff_from,
618 unibuff_till);
Antoine Pitroue9745712010-10-31 15:26:04 +0000619 if (attr_chain_item == NULL) {
620 Py_DECREF(attr_chain);
621 Py_DECREF(attr);
622 return NULL;
623 }
624 PyUnicode_InternInPlace(&attr_chain_item);
625 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
626 ++attr_chain_idx;
627 unibuff_till = unibuff_from = unibuff_till + 1;
628 }
629
630 /* now add the last dotless name */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200631 attr_chain_item = PyUnicode_Substring(item,
632 unibuff_from, item_len);
Antoine Pitroue9745712010-10-31 15:26:04 +0000633 if (attr_chain_item == NULL) {
634 Py_DECREF(attr_chain);
635 Py_DECREF(attr);
636 return NULL;
637 }
638 PyUnicode_InternInPlace(&attr_chain_item);
639 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
640
641 PyTuple_SET_ITEM(attr, idx, attr_chain);
642 }
643 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 /* create attrgetterobject structure */
646 ag = PyObject_GC_New(attrgetterobject, &attrgetter_type);
Antoine Pitroue9745712010-10-31 15:26:04 +0000647 if (ag == NULL) {
648 Py_DECREF(attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000649 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000650 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000651
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000652 ag->attr = attr;
653 ag->nattrs = nattrs;
654
655 PyObject_GC_Track(ag);
656 return (PyObject *)ag;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000657}
658
659static void
660attrgetter_dealloc(attrgetterobject *ag)
661{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000662 PyObject_GC_UnTrack(ag);
663 Py_XDECREF(ag->attr);
664 PyObject_GC_Del(ag);
Raymond Hettinger166958b2003-12-01 13:18:39 +0000665}
666
667static int
668attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
669{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000670 Py_VISIT(ag->attr);
671 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000672}
673
674static PyObject *
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000675dotted_getattr(PyObject *obj, PyObject *attr)
676{
Antoine Pitroue9745712010-10-31 15:26:04 +0000677 PyObject *newobj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000678
Antoine Pitroue9745712010-10-31 15:26:04 +0000679 /* attr is either a tuple or instance of str.
680 Ensured by the setup code of attrgetter_new */
681 if (PyTuple_CheckExact(attr)) { /* chained getattr */
682 Py_ssize_t name_idx = 0, name_count;
683 PyObject *attr_name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000684
Antoine Pitroue9745712010-10-31 15:26:04 +0000685 name_count = PyTuple_GET_SIZE(attr);
686 Py_INCREF(obj);
687 for (name_idx = 0; name_idx < name_count; ++name_idx) {
688 attr_name = PyTuple_GET_ITEM(attr, name_idx);
689 newobj = PyObject_GetAttr(obj, attr_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000690 Py_DECREF(obj);
Antoine Pitroue9745712010-10-31 15:26:04 +0000691 if (newobj == NULL) {
692 return NULL;
693 }
694 /* here */
695 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000696 }
Antoine Pitroue9745712010-10-31 15:26:04 +0000697 } else { /* single getattr */
698 newobj = PyObject_GetAttr(obj, attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 if (newobj == NULL)
700 return NULL;
701 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000703
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 return obj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000705}
706
707static PyObject *
Raymond Hettinger166958b2003-12-01 13:18:39 +0000708attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
709{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 PyObject *obj, *result;
711 Py_ssize_t i, nattrs=ag->nattrs;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000712
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000713 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
714 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000715 if (ag->nattrs == 1) /* ag->attr is always a tuple */
716 return dotted_getattr(obj, PyTuple_GET_ITEM(ag->attr, 0));
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 assert(PyTuple_Check(ag->attr));
719 assert(PyTuple_GET_SIZE(ag->attr) == nattrs);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000720
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000721 result = PyTuple_New(nattrs);
722 if (result == NULL)
723 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000724
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 for (i=0 ; i < nattrs ; i++) {
726 PyObject *attr, *val;
727 attr = PyTuple_GET_ITEM(ag->attr, i);
728 val = dotted_getattr(obj, attr);
729 if (val == NULL) {
730 Py_DECREF(result);
731 return NULL;
732 }
733 PyTuple_SET_ITEM(result, i, val);
734 }
735 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000736}
737
738PyDoc_STRVAR(attrgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000739"attrgetter(attr, ...) --> attrgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000740\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000741Return a callable object that fetches the given attribute(s) from its operand.\n\
742After, f=attrgetter('name'), the call f(r) returns r.name.\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000743After, g=attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
744After, h=attrgetter('name.first', 'name.last'), the call h(r) returns\n\
745(r.name.first, r.name.last).");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000746
747static PyTypeObject attrgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000748 PyVarObject_HEAD_INIT(NULL, 0)
749 "operator.attrgetter", /* tp_name */
750 sizeof(attrgetterobject), /* tp_basicsize */
751 0, /* tp_itemsize */
752 /* methods */
753 (destructor)attrgetter_dealloc, /* tp_dealloc */
754 0, /* tp_print */
755 0, /* tp_getattr */
756 0, /* tp_setattr */
757 0, /* tp_reserved */
758 0, /* tp_repr */
759 0, /* tp_as_number */
760 0, /* tp_as_sequence */
761 0, /* tp_as_mapping */
762 0, /* tp_hash */
763 (ternaryfunc)attrgetter_call, /* tp_call */
764 0, /* tp_str */
765 PyObject_GenericGetAttr, /* tp_getattro */
766 0, /* tp_setattro */
767 0, /* tp_as_buffer */
768 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
769 attrgetter_doc, /* tp_doc */
770 (traverseproc)attrgetter_traverse, /* tp_traverse */
771 0, /* tp_clear */
772 0, /* tp_richcompare */
773 0, /* tp_weaklistoffset */
774 0, /* tp_iter */
775 0, /* tp_iternext */
776 0, /* tp_methods */
777 0, /* tp_members */
778 0, /* tp_getset */
779 0, /* tp_base */
780 0, /* tp_dict */
781 0, /* tp_descr_get */
782 0, /* tp_descr_set */
783 0, /* tp_dictoffset */
784 0, /* tp_init */
785 0, /* tp_alloc */
786 attrgetter_new, /* tp_new */
787 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000788};
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000789
790
791/* methodcaller object **********************************************************/
792
793typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000794 PyObject_HEAD
795 PyObject *name;
796 PyObject *args;
797 PyObject *kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000798} methodcallerobject;
799
800static PyTypeObject methodcaller_type;
801
802static PyObject *
803methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
804{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 methodcallerobject *mc;
806 PyObject *name, *newargs;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000807
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000808 if (PyTuple_GET_SIZE(args) < 1) {
809 PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "
810 "one argument, the method name");
811 return NULL;
812 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000814 /* create methodcallerobject structure */
815 mc = PyObject_GC_New(methodcallerobject, &methodcaller_type);
816 if (mc == NULL)
817 return NULL;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000818
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000819 newargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
820 if (newargs == NULL) {
821 Py_DECREF(mc);
822 return NULL;
823 }
824 mc->args = newargs;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826 name = PyTuple_GET_ITEM(args, 0);
827 Py_INCREF(name);
828 mc->name = name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000830 Py_XINCREF(kwds);
831 mc->kwds = kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000832
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000833 PyObject_GC_Track(mc);
834 return (PyObject *)mc;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000835}
836
837static void
838methodcaller_dealloc(methodcallerobject *mc)
839{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000840 PyObject_GC_UnTrack(mc);
841 Py_XDECREF(mc->name);
842 Py_XDECREF(mc->args);
843 Py_XDECREF(mc->kwds);
844 PyObject_GC_Del(mc);
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000845}
846
847static int
848methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
849{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000850 Py_VISIT(mc->args);
851 Py_VISIT(mc->kwds);
852 return 0;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000853}
854
855static PyObject *
856methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
857{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000858 PyObject *method, *obj, *result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000859
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000860 if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
861 return NULL;
862 method = PyObject_GetAttr(obj, mc->name);
863 if (method == NULL)
864 return NULL;
865 result = PyObject_Call(method, mc->args, mc->kwds);
866 Py_DECREF(method);
867 return result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000868}
869
870PyDoc_STRVAR(methodcaller_doc,
871"methodcaller(name, ...) --> methodcaller object\n\
872\n\
873Return a callable object that calls the given method on its operand.\n\
874After, f = methodcaller('name'), the call f(r) returns r.name().\n\
875After, g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
876r.name('date', foo=1).");
877
878static PyTypeObject methodcaller_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000879 PyVarObject_HEAD_INIT(NULL, 0)
880 "operator.methodcaller", /* tp_name */
881 sizeof(methodcallerobject), /* tp_basicsize */
882 0, /* tp_itemsize */
883 /* methods */
884 (destructor)methodcaller_dealloc, /* tp_dealloc */
885 0, /* tp_print */
886 0, /* tp_getattr */
887 0, /* tp_setattr */
888 0, /* tp_reserved */
889 0, /* tp_repr */
890 0, /* tp_as_number */
891 0, /* tp_as_sequence */
892 0, /* tp_as_mapping */
893 0, /* tp_hash */
894 (ternaryfunc)methodcaller_call, /* tp_call */
895 0, /* tp_str */
896 PyObject_GenericGetAttr, /* tp_getattro */
897 0, /* tp_setattro */
898 0, /* tp_as_buffer */
899 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
900 methodcaller_doc, /* tp_doc */
901 (traverseproc)methodcaller_traverse, /* tp_traverse */
902 0, /* tp_clear */
903 0, /* tp_richcompare */
904 0, /* tp_weaklistoffset */
905 0, /* tp_iter */
906 0, /* tp_iternext */
907 0, /* tp_methods */
908 0, /* tp_members */
909 0, /* tp_getset */
910 0, /* tp_base */
911 0, /* tp_dict */
912 0, /* tp_descr_get */
913 0, /* tp_descr_set */
914 0, /* tp_dictoffset */
915 0, /* tp_init */
916 0, /* tp_alloc */
917 methodcaller_new, /* tp_new */
918 0, /* tp_free */
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000919};
920
921
Martin v. Löwis1a214512008-06-11 05:26:20 +0000922/* Initialization function for the module (*must* be called PyInit_operator) */
923
924
925static struct PyModuleDef operatormodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000926 PyModuleDef_HEAD_INIT,
927 "operator",
928 operator_doc,
929 -1,
930 operator_methods,
931 NULL,
932 NULL,
933 NULL,
934 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000935};
Guido van Rossum037b9401996-07-30 16:55:54 +0000936
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000937PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000938PyInit_operator(void)
Guido van Rossum037b9401996-07-30 16:55:54 +0000939{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940 PyObject *m;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000942 /* Create the module and add the functions */
943 m = PyModule_Create(&operatormodule);
944 if (m == NULL)
945 return NULL;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000946
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000947 if (PyType_Ready(&itemgetter_type) < 0)
948 return NULL;
949 Py_INCREF(&itemgetter_type);
950 PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000951
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 if (PyType_Ready(&attrgetter_type) < 0)
953 return NULL;
954 Py_INCREF(&attrgetter_type);
955 PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);
956
957 if (PyType_Ready(&methodcaller_type) < 0)
958 return NULL;
959 Py_INCREF(&methodcaller_type);
960 PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);
961 return m;
Guido van Rossum037b9401996-07-30 16:55:54 +0000962}