blob: 735affcdbb610e2ddb5386a6ca7916baa6c6c457 [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
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300488static PyObject *
489itemgetter_repr(itemgetterobject *ig)
490{
491 PyObject *repr;
492 const char *reprfmt;
493
494 int status = Py_ReprEnter((PyObject *)ig);
495 if (status != 0) {
496 if (status < 0)
497 return NULL;
498 return PyUnicode_FromFormat("%s(...)", Py_TYPE(ig)->tp_name);
499 }
500
501 reprfmt = ig->nitems == 1 ? "%s(%R)" : "%s%R";
502 repr = PyUnicode_FromFormat(reprfmt, Py_TYPE(ig)->tp_name, ig->item);
503 Py_ReprLeave((PyObject *)ig);
504 return repr;
505}
506
507static PyObject *
508itemgetter_reduce(itemgetterobject *ig)
509{
510 if (ig->nitems == 1)
511 return Py_BuildValue("O(O)", Py_TYPE(ig), ig->item);
512 return PyTuple_Pack(2, Py_TYPE(ig), ig->item);
513}
514
515PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
516
517static PyMethodDef itemgetter_methods[] = {
518 {"__reduce__", (PyCFunction)itemgetter_reduce, METH_NOARGS,
519 reduce_doc},
520 {NULL}
521};
522
Raymond Hettinger166958b2003-12-01 13:18:39 +0000523PyDoc_STRVAR(itemgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000524"itemgetter(item, ...) --> itemgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000525\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000526Return a callable object that fetches the given item(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +0300527After f = itemgetter(2), the call f(r) returns r[2].\n\
528After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000529
530static PyTypeObject itemgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 PyVarObject_HEAD_INIT(NULL, 0)
532 "operator.itemgetter", /* tp_name */
533 sizeof(itemgetterobject), /* tp_basicsize */
534 0, /* tp_itemsize */
535 /* methods */
536 (destructor)itemgetter_dealloc, /* tp_dealloc */
537 0, /* tp_print */
538 0, /* tp_getattr */
539 0, /* tp_setattr */
540 0, /* tp_reserved */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300541 (reprfunc)itemgetter_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000542 0, /* tp_as_number */
543 0, /* tp_as_sequence */
544 0, /* tp_as_mapping */
545 0, /* tp_hash */
546 (ternaryfunc)itemgetter_call, /* tp_call */
547 0, /* tp_str */
548 PyObject_GenericGetAttr, /* tp_getattro */
549 0, /* tp_setattro */
550 0, /* tp_as_buffer */
551 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
552 itemgetter_doc, /* tp_doc */
553 (traverseproc)itemgetter_traverse, /* tp_traverse */
554 0, /* tp_clear */
555 0, /* tp_richcompare */
556 0, /* tp_weaklistoffset */
557 0, /* tp_iter */
558 0, /* tp_iternext */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300559 itemgetter_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 0, /* tp_members */
561 0, /* tp_getset */
562 0, /* tp_base */
563 0, /* tp_dict */
564 0, /* tp_descr_get */
565 0, /* tp_descr_set */
566 0, /* tp_dictoffset */
567 0, /* tp_init */
568 0, /* tp_alloc */
569 itemgetter_new, /* tp_new */
570 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000571};
572
573
574/* attrgetter object **********************************************************/
575
576typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000577 PyObject_HEAD
578 Py_ssize_t nattrs;
579 PyObject *attr;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000580} attrgetterobject;
581
582static PyTypeObject attrgetter_type;
583
584static PyObject *
585attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
586{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000587 attrgetterobject *ag;
588 PyObject *attr;
Antoine Pitroue9745712010-10-31 15:26:04 +0000589 Py_ssize_t nattrs, idx, char_idx;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000590
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 if (!_PyArg_NoKeywords("attrgetter()", kwds))
592 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000593
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000594 nattrs = PyTuple_GET_SIZE(args);
595 if (nattrs <= 1) {
596 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))
597 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000598 }
599
600 attr = PyTuple_New(nattrs);
601 if (attr == NULL)
602 return NULL;
603
604 /* prepare attr while checking args */
605 for (idx = 0; idx < nattrs; ++idx) {
606 PyObject *item = PyTuple_GET_ITEM(args, idx);
607 Py_ssize_t item_len;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200608 void *data;
609 unsigned int kind;
Antoine Pitroue9745712010-10-31 15:26:04 +0000610 int dot_count;
611
612 if (!PyUnicode_Check(item)) {
613 PyErr_SetString(PyExc_TypeError,
614 "attribute name must be a string");
615 Py_DECREF(attr);
616 return NULL;
617 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200618 if (PyUnicode_READY(item)) {
619 Py_DECREF(attr);
620 return NULL;
621 }
622 item_len = PyUnicode_GET_LENGTH(item);
623 kind = PyUnicode_KIND(item);
624 data = PyUnicode_DATA(item);
Antoine Pitroue9745712010-10-31 15:26:04 +0000625
626 /* check whethere the string is dotted */
627 dot_count = 0;
628 for (char_idx = 0; char_idx < item_len; ++char_idx) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200629 if (PyUnicode_READ(kind, data, char_idx) == '.')
Antoine Pitroue9745712010-10-31 15:26:04 +0000630 ++dot_count;
631 }
632
633 if (dot_count == 0) {
634 Py_INCREF(item);
635 PyUnicode_InternInPlace(&item);
636 PyTuple_SET_ITEM(attr, idx, item);
637 } else { /* make it a tuple of non-dotted attrnames */
638 PyObject *attr_chain = PyTuple_New(dot_count + 1);
639 PyObject *attr_chain_item;
Antoine Pitrou87298c42010-10-31 21:03:01 +0000640 Py_ssize_t unibuff_from = 0;
641 Py_ssize_t unibuff_till = 0;
642 Py_ssize_t attr_chain_idx = 0;
Antoine Pitroue9745712010-10-31 15:26:04 +0000643
644 if (attr_chain == NULL) {
645 Py_DECREF(attr);
646 return NULL;
647 }
648
Antoine Pitroue9745712010-10-31 15:26:04 +0000649 for (; dot_count > 0; --dot_count) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200650 while (PyUnicode_READ(kind, data, unibuff_till) != '.') {
Antoine Pitroue9745712010-10-31 15:26:04 +0000651 ++unibuff_till;
652 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200653 attr_chain_item = PyUnicode_Substring(item,
654 unibuff_from,
655 unibuff_till);
Antoine Pitroue9745712010-10-31 15:26:04 +0000656 if (attr_chain_item == NULL) {
657 Py_DECREF(attr_chain);
658 Py_DECREF(attr);
659 return NULL;
660 }
661 PyUnicode_InternInPlace(&attr_chain_item);
662 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
663 ++attr_chain_idx;
664 unibuff_till = unibuff_from = unibuff_till + 1;
665 }
666
667 /* now add the last dotless name */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200668 attr_chain_item = PyUnicode_Substring(item,
669 unibuff_from, item_len);
Antoine Pitroue9745712010-10-31 15:26:04 +0000670 if (attr_chain_item == NULL) {
671 Py_DECREF(attr_chain);
672 Py_DECREF(attr);
673 return NULL;
674 }
675 PyUnicode_InternInPlace(&attr_chain_item);
676 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
677
678 PyTuple_SET_ITEM(attr, idx, attr_chain);
679 }
680 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 /* create attrgetterobject structure */
683 ag = PyObject_GC_New(attrgetterobject, &attrgetter_type);
Antoine Pitroue9745712010-10-31 15:26:04 +0000684 if (ag == NULL) {
685 Py_DECREF(attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000686 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000687 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000688
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000689 ag->attr = attr;
690 ag->nattrs = nattrs;
691
692 PyObject_GC_Track(ag);
693 return (PyObject *)ag;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000694}
695
696static void
697attrgetter_dealloc(attrgetterobject *ag)
698{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000699 PyObject_GC_UnTrack(ag);
700 Py_XDECREF(ag->attr);
701 PyObject_GC_Del(ag);
Raymond Hettinger166958b2003-12-01 13:18:39 +0000702}
703
704static int
705attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
706{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000707 Py_VISIT(ag->attr);
708 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000709}
710
711static PyObject *
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000712dotted_getattr(PyObject *obj, PyObject *attr)
713{
Antoine Pitroue9745712010-10-31 15:26:04 +0000714 PyObject *newobj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000715
Antoine Pitroue9745712010-10-31 15:26:04 +0000716 /* attr is either a tuple or instance of str.
717 Ensured by the setup code of attrgetter_new */
718 if (PyTuple_CheckExact(attr)) { /* chained getattr */
719 Py_ssize_t name_idx = 0, name_count;
720 PyObject *attr_name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000721
Antoine Pitroue9745712010-10-31 15:26:04 +0000722 name_count = PyTuple_GET_SIZE(attr);
723 Py_INCREF(obj);
724 for (name_idx = 0; name_idx < name_count; ++name_idx) {
725 attr_name = PyTuple_GET_ITEM(attr, name_idx);
726 newobj = PyObject_GetAttr(obj, attr_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 Py_DECREF(obj);
Antoine Pitroue9745712010-10-31 15:26:04 +0000728 if (newobj == NULL) {
729 return NULL;
730 }
731 /* here */
732 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000733 }
Antoine Pitroue9745712010-10-31 15:26:04 +0000734 } else { /* single getattr */
735 newobj = PyObject_GetAttr(obj, attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 if (newobj == NULL)
737 return NULL;
738 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000739 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 return obj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000742}
743
744static PyObject *
Raymond Hettinger166958b2003-12-01 13:18:39 +0000745attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
746{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000747 PyObject *obj, *result;
748 Py_ssize_t i, nattrs=ag->nattrs;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000749
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000750 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
751 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000752 if (ag->nattrs == 1) /* ag->attr is always a tuple */
753 return dotted_getattr(obj, PyTuple_GET_ITEM(ag->attr, 0));
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000754
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000755 assert(PyTuple_Check(ag->attr));
756 assert(PyTuple_GET_SIZE(ag->attr) == nattrs);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000757
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000758 result = PyTuple_New(nattrs);
759 if (result == NULL)
760 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 for (i=0 ; i < nattrs ; i++) {
763 PyObject *attr, *val;
764 attr = PyTuple_GET_ITEM(ag->attr, i);
765 val = dotted_getattr(obj, attr);
766 if (val == NULL) {
767 Py_DECREF(result);
768 return NULL;
769 }
770 PyTuple_SET_ITEM(result, i, val);
771 }
772 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000773}
774
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300775static PyObject *
776dotjoinattr(PyObject *attr, PyObject **attrsep)
777{
778 if (PyTuple_CheckExact(attr)) {
779 if (*attrsep == NULL) {
780 *attrsep = PyUnicode_FromString(".");
781 if (*attrsep == NULL)
782 return NULL;
783 }
784 return PyUnicode_Join(*attrsep, attr);
785 } else {
786 Py_INCREF(attr);
787 return attr;
788 }
789}
790
791static PyObject *
792attrgetter_args(attrgetterobject *ag)
793{
794 Py_ssize_t i;
795 PyObject *attrsep = NULL;
796 PyObject *attrstrings = PyTuple_New(ag->nattrs);
797 if (attrstrings == NULL)
798 return NULL;
799
800 for (i = 0; i < ag->nattrs; ++i) {
801 PyObject *attr = PyTuple_GET_ITEM(ag->attr, i);
802 PyObject *attrstr = dotjoinattr(attr, &attrsep);
803 if (attrstr == NULL) {
804 Py_XDECREF(attrsep);
805 Py_DECREF(attrstrings);
806 return NULL;
807 }
808 PyTuple_SET_ITEM(attrstrings, i, attrstr);
809 }
810 Py_XDECREF(attrsep);
811 return attrstrings;
812}
813
814static PyObject *
815attrgetter_repr(attrgetterobject *ag)
816{
817 PyObject *repr = NULL;
818 int status = Py_ReprEnter((PyObject *)ag);
819 if (status != 0) {
820 if (status < 0)
821 return NULL;
822 return PyUnicode_FromFormat("%s(...)", Py_TYPE(ag)->tp_name);
823 }
824
825 if (ag->nattrs == 1) {
826 PyObject *attrsep = NULL;
827 PyObject *attr = dotjoinattr(PyTuple_GET_ITEM(ag->attr, 0), &attrsep);
Serhiy Storchaka548de2b2015-05-21 14:19:20 +0300828 if (attr != NULL) {
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300829 repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(ag)->tp_name, attr);
Serhiy Storchaka548de2b2015-05-21 14:19:20 +0300830 Py_DECREF(attr);
831 }
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300832 Py_XDECREF(attrsep);
833 }
834 else {
835 PyObject *attrstrings = attrgetter_args(ag);
836 if (attrstrings != NULL) {
837 repr = PyUnicode_FromFormat("%s%R",
838 Py_TYPE(ag)->tp_name, attrstrings);
839 Py_DECREF(attrstrings);
840 }
841 }
842 Py_ReprLeave((PyObject *)ag);
843 return repr;
844}
845
846static PyObject *
847attrgetter_reduce(attrgetterobject *ag)
848{
849 PyObject *attrstrings = attrgetter_args(ag);
850 if (attrstrings == NULL)
851 return NULL;
852
853 return Py_BuildValue("ON", Py_TYPE(ag), attrstrings);
854}
855
856static PyMethodDef attrgetter_methods[] = {
857 {"__reduce__", (PyCFunction)attrgetter_reduce, METH_NOARGS,
858 reduce_doc},
859 {NULL}
860};
861
Raymond Hettinger166958b2003-12-01 13:18:39 +0000862PyDoc_STRVAR(attrgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000863"attrgetter(attr, ...) --> attrgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000864\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000865Return a callable object that fetches the given attribute(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +0300866After f = attrgetter('name'), the call f(r) returns r.name.\n\
867After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
868After h = attrgetter('name.first', 'name.last'), the call h(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000869(r.name.first, r.name.last).");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000870
871static PyTypeObject attrgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 PyVarObject_HEAD_INIT(NULL, 0)
873 "operator.attrgetter", /* tp_name */
874 sizeof(attrgetterobject), /* tp_basicsize */
875 0, /* tp_itemsize */
876 /* methods */
877 (destructor)attrgetter_dealloc, /* tp_dealloc */
878 0, /* tp_print */
879 0, /* tp_getattr */
880 0, /* tp_setattr */
881 0, /* tp_reserved */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300882 (reprfunc)attrgetter_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 0, /* tp_as_number */
884 0, /* tp_as_sequence */
885 0, /* tp_as_mapping */
886 0, /* tp_hash */
887 (ternaryfunc)attrgetter_call, /* tp_call */
888 0, /* tp_str */
889 PyObject_GenericGetAttr, /* tp_getattro */
890 0, /* tp_setattro */
891 0, /* tp_as_buffer */
892 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
893 attrgetter_doc, /* tp_doc */
894 (traverseproc)attrgetter_traverse, /* tp_traverse */
895 0, /* tp_clear */
896 0, /* tp_richcompare */
897 0, /* tp_weaklistoffset */
898 0, /* tp_iter */
899 0, /* tp_iternext */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300900 attrgetter_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 0, /* tp_members */
902 0, /* tp_getset */
903 0, /* tp_base */
904 0, /* tp_dict */
905 0, /* tp_descr_get */
906 0, /* tp_descr_set */
907 0, /* tp_dictoffset */
908 0, /* tp_init */
909 0, /* tp_alloc */
910 attrgetter_new, /* tp_new */
911 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000912};
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000913
914
915/* methodcaller object **********************************************************/
916
917typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 PyObject_HEAD
919 PyObject *name;
920 PyObject *args;
921 PyObject *kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000922} methodcallerobject;
923
924static PyTypeObject methodcaller_type;
925
926static PyObject *
927methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
928{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929 methodcallerobject *mc;
930 PyObject *name, *newargs;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000932 if (PyTuple_GET_SIZE(args) < 1) {
933 PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "
934 "one argument, the method name");
935 return NULL;
936 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000937
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300938 name = PyTuple_GET_ITEM(args, 0);
939 if (!PyUnicode_Check(name)) {
940 PyErr_SetString(PyExc_TypeError,
941 "method name must be a string");
942 return NULL;
943 }
944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000945 /* create methodcallerobject structure */
946 mc = PyObject_GC_New(methodcallerobject, &methodcaller_type);
947 if (mc == NULL)
948 return NULL;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000949
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000950 newargs = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
951 if (newargs == NULL) {
952 Py_DECREF(mc);
953 return NULL;
954 }
955 mc->args = newargs;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000956
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 Py_INCREF(name);
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300958 PyUnicode_InternInPlace(&name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000959 mc->name = name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000961 Py_XINCREF(kwds);
962 mc->kwds = kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000963
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000964 PyObject_GC_Track(mc);
965 return (PyObject *)mc;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000966}
967
968static void
969methodcaller_dealloc(methodcallerobject *mc)
970{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000971 PyObject_GC_UnTrack(mc);
972 Py_XDECREF(mc->name);
973 Py_XDECREF(mc->args);
974 Py_XDECREF(mc->kwds);
975 PyObject_GC_Del(mc);
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000976}
977
978static int
979methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
980{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 Py_VISIT(mc->args);
982 Py_VISIT(mc->kwds);
983 return 0;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000984}
985
986static PyObject *
987methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
988{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000989 PyObject *method, *obj, *result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000990
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
992 return NULL;
993 method = PyObject_GetAttr(obj, mc->name);
994 if (method == NULL)
995 return NULL;
996 result = PyObject_Call(method, mc->args, mc->kwds);
997 Py_DECREF(method);
998 return result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000999}
1000
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001001static PyObject *
1002methodcaller_repr(methodcallerobject *mc)
1003{
1004 PyObject *argreprs, *repr = NULL, *sep, *joinedargreprs;
1005 Py_ssize_t numtotalargs, numposargs, numkwdargs, i;
1006 int status = Py_ReprEnter((PyObject *)mc);
1007 if (status != 0) {
1008 if (status < 0)
1009 return NULL;
1010 return PyUnicode_FromFormat("%s(...)", Py_TYPE(mc)->tp_name);
1011 }
1012
1013 if (mc->kwds != NULL) {
1014 numkwdargs = PyDict_Size(mc->kwds);
1015 if (numkwdargs < 0) {
1016 Py_ReprLeave((PyObject *)mc);
1017 return NULL;
1018 }
1019 } else {
1020 numkwdargs = 0;
1021 }
1022
1023 numposargs = PyTuple_GET_SIZE(mc->args);
1024 numtotalargs = numposargs + numkwdargs;
1025
1026 if (numtotalargs == 0) {
1027 repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(mc)->tp_name, mc->name);
1028 Py_ReprLeave((PyObject *)mc);
1029 return repr;
1030 }
1031
1032 argreprs = PyTuple_New(numtotalargs);
1033 if (argreprs == NULL) {
1034 Py_ReprLeave((PyObject *)mc);
1035 return NULL;
1036 }
1037
1038 for (i = 0; i < numposargs; ++i) {
1039 PyObject *onerepr = PyObject_Repr(PyTuple_GET_ITEM(mc->args, i));
1040 if (onerepr == NULL)
1041 goto done;
1042 PyTuple_SET_ITEM(argreprs, i, onerepr);
1043 }
1044
1045 if (numkwdargs != 0) {
1046 PyObject *key, *value;
1047 Py_ssize_t pos = 0;
1048 while (PyDict_Next(mc->kwds, &pos, &key, &value)) {
1049 PyObject *onerepr = PyUnicode_FromFormat("%U=%R", key, value);
1050 if (onerepr == NULL)
1051 goto done;
1052 if (i >= numtotalargs) {
1053 i = -1;
1054 break;
1055 }
1056 PyTuple_SET_ITEM(argreprs, i, onerepr);
1057 ++i;
1058 }
1059 if (i != numtotalargs) {
1060 PyErr_SetString(PyExc_RuntimeError,
1061 "keywords dict changed size during iteration");
1062 goto done;
1063 }
1064 }
1065
1066 sep = PyUnicode_FromString(", ");
1067 if (sep == NULL)
1068 goto done;
1069
1070 joinedargreprs = PyUnicode_Join(sep, argreprs);
1071 Py_DECREF(sep);
1072 if (joinedargreprs == NULL)
1073 goto done;
1074
1075 repr = PyUnicode_FromFormat("%s(%R, %U)", Py_TYPE(mc)->tp_name,
1076 mc->name, joinedargreprs);
1077 Py_DECREF(joinedargreprs);
1078
1079done:
1080 Py_DECREF(argreprs);
1081 Py_ReprLeave((PyObject *)mc);
1082 return repr;
1083}
1084
1085static PyObject *
1086methodcaller_reduce(methodcallerobject *mc)
1087{
1088 PyObject *newargs;
1089 if (!mc->kwds || PyDict_Size(mc->kwds) == 0) {
1090 Py_ssize_t i;
1091 Py_ssize_t callargcount = PyTuple_GET_SIZE(mc->args);
1092 newargs = PyTuple_New(1 + callargcount);
1093 if (newargs == NULL)
1094 return NULL;
1095 Py_INCREF(mc->name);
1096 PyTuple_SET_ITEM(newargs, 0, mc->name);
1097 for (i = 0; i < callargcount; ++i) {
1098 PyObject *arg = PyTuple_GET_ITEM(mc->args, i);
1099 Py_INCREF(arg);
1100 PyTuple_SET_ITEM(newargs, i + 1, arg);
1101 }
1102 return Py_BuildValue("ON", Py_TYPE(mc), newargs);
1103 }
1104 else {
1105 PyObject *functools;
1106 PyObject *partial;
1107 PyObject *constructor;
1108 _Py_IDENTIFIER(partial);
1109 functools = PyImport_ImportModule("functools");
1110 if (!functools)
1111 return NULL;
1112 partial = _PyObject_GetAttrId(functools, &PyId_partial);
1113 Py_DECREF(functools);
1114 if (!partial)
1115 return NULL;
1116 newargs = PyTuple_New(2);
1117 if (newargs == NULL) {
1118 Py_DECREF(partial);
1119 return NULL;
1120 }
1121 Py_INCREF(Py_TYPE(mc));
1122 PyTuple_SET_ITEM(newargs, 0, (PyObject *)Py_TYPE(mc));
1123 Py_INCREF(mc->name);
1124 PyTuple_SET_ITEM(newargs, 1, mc->name);
1125 constructor = PyObject_Call(partial, newargs, mc->kwds);
1126 Py_DECREF(newargs);
1127 Py_DECREF(partial);
1128 return Py_BuildValue("NO", constructor, mc->args);
1129 }
1130}
1131
1132static PyMethodDef methodcaller_methods[] = {
1133 {"__reduce__", (PyCFunction)methodcaller_reduce, METH_NOARGS,
1134 reduce_doc},
1135 {NULL}
1136};
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001137PyDoc_STRVAR(methodcaller_doc,
1138"methodcaller(name, ...) --> methodcaller object\n\
1139\n\
1140Return a callable object that calls the given method on its operand.\n\
Antoine Pitroua85017f2013-04-20 19:21:44 +02001141After f = methodcaller('name'), the call f(r) returns r.name().\n\
1142After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001143r.name('date', foo=1).");
1144
1145static PyTypeObject methodcaller_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 PyVarObject_HEAD_INIT(NULL, 0)
1147 "operator.methodcaller", /* tp_name */
1148 sizeof(methodcallerobject), /* tp_basicsize */
1149 0, /* tp_itemsize */
1150 /* methods */
1151 (destructor)methodcaller_dealloc, /* tp_dealloc */
1152 0, /* tp_print */
1153 0, /* tp_getattr */
1154 0, /* tp_setattr */
1155 0, /* tp_reserved */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001156 (reprfunc)methodcaller_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 0, /* tp_as_number */
1158 0, /* tp_as_sequence */
1159 0, /* tp_as_mapping */
1160 0, /* tp_hash */
1161 (ternaryfunc)methodcaller_call, /* tp_call */
1162 0, /* tp_str */
1163 PyObject_GenericGetAttr, /* tp_getattro */
1164 0, /* tp_setattro */
1165 0, /* tp_as_buffer */
1166 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1167 methodcaller_doc, /* tp_doc */
1168 (traverseproc)methodcaller_traverse, /* tp_traverse */
1169 0, /* tp_clear */
1170 0, /* tp_richcompare */
1171 0, /* tp_weaklistoffset */
1172 0, /* tp_iter */
1173 0, /* tp_iternext */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001174 methodcaller_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001175 0, /* tp_members */
1176 0, /* tp_getset */
1177 0, /* tp_base */
1178 0, /* tp_dict */
1179 0, /* tp_descr_get */
1180 0, /* tp_descr_set */
1181 0, /* tp_dictoffset */
1182 0, /* tp_init */
1183 0, /* tp_alloc */
1184 methodcaller_new, /* tp_new */
1185 0, /* tp_free */
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001186};
1187
1188
Antoine Pitroua85017f2013-04-20 19:21:44 +02001189/* Initialization function for the module (*must* be called PyInit__operator) */
Martin v. Löwis1a214512008-06-11 05:26:20 +00001190
1191
1192static struct PyModuleDef operatormodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001193 PyModuleDef_HEAD_INIT,
Antoine Pitroua85017f2013-04-20 19:21:44 +02001194 "_operator",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001195 operator_doc,
1196 -1,
1197 operator_methods,
1198 NULL,
1199 NULL,
1200 NULL,
1201 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001202};
Guido van Rossum037b9401996-07-30 16:55:54 +00001203
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001204PyMODINIT_FUNC
Antoine Pitroua85017f2013-04-20 19:21:44 +02001205PyInit__operator(void)
Guido van Rossum037b9401996-07-30 16:55:54 +00001206{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001207 PyObject *m;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001208
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001209 /* Create the module and add the functions */
1210 m = PyModule_Create(&operatormodule);
1211 if (m == NULL)
1212 return NULL;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001214 if (PyType_Ready(&itemgetter_type) < 0)
1215 return NULL;
1216 Py_INCREF(&itemgetter_type);
1217 PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001218
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001219 if (PyType_Ready(&attrgetter_type) < 0)
1220 return NULL;
1221 Py_INCREF(&attrgetter_type);
1222 PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);
1223
1224 if (PyType_Ready(&methodcaller_type) < 0)
1225 return NULL;
1226 Py_INCREF(&methodcaller_type);
1227 PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);
1228 return m;
Guido van Rossum037b9401996-07-30 16:55:54 +00001229}