blob: fb8eafc6793d703b7f9004e30ccc70f93e95fbfa [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
Serhiy Storchaka6dfcde52016-04-29 09:10:55 +0300463 if (kw != NULL && !_PyArg_NoKeywords("itemgetter", kw))
Serhiy Storchakac2a2a752016-04-23 10:51:39 +0300464 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000465 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
466 return NULL;
467 if (nitems == 1)
468 return PyObject_GetItem(obj, ig->item);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 assert(PyTuple_Check(ig->item));
471 assert(PyTuple_GET_SIZE(ig->item) == nitems);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 result = PyTuple_New(nitems);
474 if (result == NULL)
475 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000477 for (i=0 ; i < nitems ; i++) {
478 PyObject *item, *val;
479 item = PyTuple_GET_ITEM(ig->item, i);
480 val = PyObject_GetItem(obj, item);
481 if (val == NULL) {
482 Py_DECREF(result);
483 return NULL;
484 }
485 PyTuple_SET_ITEM(result, i, val);
486 }
487 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000488}
489
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300490static PyObject *
491itemgetter_repr(itemgetterobject *ig)
492{
493 PyObject *repr;
494 const char *reprfmt;
495
496 int status = Py_ReprEnter((PyObject *)ig);
497 if (status != 0) {
498 if (status < 0)
499 return NULL;
500 return PyUnicode_FromFormat("%s(...)", Py_TYPE(ig)->tp_name);
501 }
502
503 reprfmt = ig->nitems == 1 ? "%s(%R)" : "%s%R";
504 repr = PyUnicode_FromFormat(reprfmt, Py_TYPE(ig)->tp_name, ig->item);
505 Py_ReprLeave((PyObject *)ig);
506 return repr;
507}
508
509static PyObject *
510itemgetter_reduce(itemgetterobject *ig)
511{
512 if (ig->nitems == 1)
513 return Py_BuildValue("O(O)", Py_TYPE(ig), ig->item);
514 return PyTuple_Pack(2, Py_TYPE(ig), ig->item);
515}
516
517PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
518
519static PyMethodDef itemgetter_methods[] = {
520 {"__reduce__", (PyCFunction)itemgetter_reduce, METH_NOARGS,
521 reduce_doc},
522 {NULL}
523};
524
Raymond Hettinger166958b2003-12-01 13:18:39 +0000525PyDoc_STRVAR(itemgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000526"itemgetter(item, ...) --> itemgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000527\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000528Return a callable object that fetches the given item(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +0300529After f = itemgetter(2), the call f(r) returns r[2].\n\
530After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000531
532static PyTypeObject itemgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000533 PyVarObject_HEAD_INIT(NULL, 0)
534 "operator.itemgetter", /* tp_name */
535 sizeof(itemgetterobject), /* tp_basicsize */
536 0, /* tp_itemsize */
537 /* methods */
538 (destructor)itemgetter_dealloc, /* tp_dealloc */
539 0, /* tp_print */
540 0, /* tp_getattr */
541 0, /* tp_setattr */
542 0, /* tp_reserved */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300543 (reprfunc)itemgetter_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000544 0, /* tp_as_number */
545 0, /* tp_as_sequence */
546 0, /* tp_as_mapping */
547 0, /* tp_hash */
548 (ternaryfunc)itemgetter_call, /* tp_call */
549 0, /* tp_str */
550 PyObject_GenericGetAttr, /* tp_getattro */
551 0, /* tp_setattro */
552 0, /* tp_as_buffer */
553 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
554 itemgetter_doc, /* tp_doc */
555 (traverseproc)itemgetter_traverse, /* tp_traverse */
556 0, /* tp_clear */
557 0, /* tp_richcompare */
558 0, /* tp_weaklistoffset */
559 0, /* tp_iter */
560 0, /* tp_iternext */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300561 itemgetter_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000562 0, /* tp_members */
563 0, /* tp_getset */
564 0, /* tp_base */
565 0, /* tp_dict */
566 0, /* tp_descr_get */
567 0, /* tp_descr_set */
568 0, /* tp_dictoffset */
569 0, /* tp_init */
570 0, /* tp_alloc */
571 itemgetter_new, /* tp_new */
572 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000573};
574
575
576/* attrgetter object **********************************************************/
577
578typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 PyObject_HEAD
580 Py_ssize_t nattrs;
581 PyObject *attr;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000582} attrgetterobject;
583
584static PyTypeObject attrgetter_type;
585
586static PyObject *
587attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
588{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000589 attrgetterobject *ag;
590 PyObject *attr;
Antoine Pitroue9745712010-10-31 15:26:04 +0000591 Py_ssize_t nattrs, idx, char_idx;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (!_PyArg_NoKeywords("attrgetter()", kwds))
594 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 nattrs = PyTuple_GET_SIZE(args);
597 if (nattrs <= 1) {
598 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))
599 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000600 }
601
602 attr = PyTuple_New(nattrs);
603 if (attr == NULL)
604 return NULL;
605
606 /* prepare attr while checking args */
607 for (idx = 0; idx < nattrs; ++idx) {
608 PyObject *item = PyTuple_GET_ITEM(args, idx);
609 Py_ssize_t item_len;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200610 void *data;
611 unsigned int kind;
Antoine Pitroue9745712010-10-31 15:26:04 +0000612 int dot_count;
613
614 if (!PyUnicode_Check(item)) {
615 PyErr_SetString(PyExc_TypeError,
616 "attribute name must be a string");
617 Py_DECREF(attr);
618 return NULL;
619 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200620 if (PyUnicode_READY(item)) {
621 Py_DECREF(attr);
622 return NULL;
623 }
624 item_len = PyUnicode_GET_LENGTH(item);
625 kind = PyUnicode_KIND(item);
626 data = PyUnicode_DATA(item);
Antoine Pitroue9745712010-10-31 15:26:04 +0000627
628 /* check whethere the string is dotted */
629 dot_count = 0;
630 for (char_idx = 0; char_idx < item_len; ++char_idx) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200631 if (PyUnicode_READ(kind, data, char_idx) == '.')
Antoine Pitroue9745712010-10-31 15:26:04 +0000632 ++dot_count;
633 }
634
635 if (dot_count == 0) {
636 Py_INCREF(item);
637 PyUnicode_InternInPlace(&item);
638 PyTuple_SET_ITEM(attr, idx, item);
639 } else { /* make it a tuple of non-dotted attrnames */
640 PyObject *attr_chain = PyTuple_New(dot_count + 1);
641 PyObject *attr_chain_item;
Antoine Pitrou87298c42010-10-31 21:03:01 +0000642 Py_ssize_t unibuff_from = 0;
643 Py_ssize_t unibuff_till = 0;
644 Py_ssize_t attr_chain_idx = 0;
Antoine Pitroue9745712010-10-31 15:26:04 +0000645
646 if (attr_chain == NULL) {
647 Py_DECREF(attr);
648 return NULL;
649 }
650
Antoine Pitroue9745712010-10-31 15:26:04 +0000651 for (; dot_count > 0; --dot_count) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200652 while (PyUnicode_READ(kind, data, unibuff_till) != '.') {
Antoine Pitroue9745712010-10-31 15:26:04 +0000653 ++unibuff_till;
654 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200655 attr_chain_item = PyUnicode_Substring(item,
656 unibuff_from,
657 unibuff_till);
Antoine Pitroue9745712010-10-31 15:26:04 +0000658 if (attr_chain_item == NULL) {
659 Py_DECREF(attr_chain);
660 Py_DECREF(attr);
661 return NULL;
662 }
663 PyUnicode_InternInPlace(&attr_chain_item);
664 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
665 ++attr_chain_idx;
666 unibuff_till = unibuff_from = unibuff_till + 1;
667 }
668
669 /* now add the last dotless name */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200670 attr_chain_item = PyUnicode_Substring(item,
671 unibuff_from, item_len);
Antoine Pitroue9745712010-10-31 15:26:04 +0000672 if (attr_chain_item == NULL) {
673 Py_DECREF(attr_chain);
674 Py_DECREF(attr);
675 return NULL;
676 }
677 PyUnicode_InternInPlace(&attr_chain_item);
678 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
679
680 PyTuple_SET_ITEM(attr, idx, attr_chain);
681 }
682 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 /* create attrgetterobject structure */
685 ag = PyObject_GC_New(attrgetterobject, &attrgetter_type);
Antoine Pitroue9745712010-10-31 15:26:04 +0000686 if (ag == NULL) {
687 Py_DECREF(attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000688 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000689 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000690
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 ag->attr = attr;
692 ag->nattrs = nattrs;
693
694 PyObject_GC_Track(ag);
695 return (PyObject *)ag;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000696}
697
698static void
699attrgetter_dealloc(attrgetterobject *ag)
700{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 PyObject_GC_UnTrack(ag);
702 Py_XDECREF(ag->attr);
703 PyObject_GC_Del(ag);
Raymond Hettinger166958b2003-12-01 13:18:39 +0000704}
705
706static int
707attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
708{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000709 Py_VISIT(ag->attr);
710 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000711}
712
713static PyObject *
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000714dotted_getattr(PyObject *obj, PyObject *attr)
715{
Antoine Pitroue9745712010-10-31 15:26:04 +0000716 PyObject *newobj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000717
Antoine Pitroue9745712010-10-31 15:26:04 +0000718 /* attr is either a tuple or instance of str.
719 Ensured by the setup code of attrgetter_new */
720 if (PyTuple_CheckExact(attr)) { /* chained getattr */
721 Py_ssize_t name_idx = 0, name_count;
722 PyObject *attr_name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000723
Antoine Pitroue9745712010-10-31 15:26:04 +0000724 name_count = PyTuple_GET_SIZE(attr);
725 Py_INCREF(obj);
726 for (name_idx = 0; name_idx < name_count; ++name_idx) {
727 attr_name = PyTuple_GET_ITEM(attr, name_idx);
728 newobj = PyObject_GetAttr(obj, attr_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 Py_DECREF(obj);
Antoine Pitroue9745712010-10-31 15:26:04 +0000730 if (newobj == NULL) {
731 return NULL;
732 }
733 /* here */
734 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000735 }
Antoine Pitroue9745712010-10-31 15:26:04 +0000736 } else { /* single getattr */
737 newobj = PyObject_GetAttr(obj, attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000738 if (newobj == NULL)
739 return NULL;
740 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 return obj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000744}
745
746static PyObject *
Raymond Hettinger166958b2003-12-01 13:18:39 +0000747attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
748{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 PyObject *obj, *result;
750 Py_ssize_t i, nattrs=ag->nattrs;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000751
Serhiy Storchaka6dfcde52016-04-29 09:10:55 +0300752 if (kw != NULL && !_PyArg_NoKeywords("attrgetter", kw))
Serhiy Storchakac2a2a752016-04-23 10:51:39 +0300753 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
755 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +0000756 if (ag->nattrs == 1) /* ag->attr is always a tuple */
757 return dotted_getattr(obj, PyTuple_GET_ITEM(ag->attr, 0));
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000758
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000759 assert(PyTuple_Check(ag->attr));
760 assert(PyTuple_GET_SIZE(ag->attr) == nattrs);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000762 result = PyTuple_New(nattrs);
763 if (result == NULL)
764 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000765
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000766 for (i=0 ; i < nattrs ; i++) {
767 PyObject *attr, *val;
768 attr = PyTuple_GET_ITEM(ag->attr, i);
769 val = dotted_getattr(obj, attr);
770 if (val == NULL) {
771 Py_DECREF(result);
772 return NULL;
773 }
774 PyTuple_SET_ITEM(result, i, val);
775 }
776 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000777}
778
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300779static PyObject *
780dotjoinattr(PyObject *attr, PyObject **attrsep)
781{
782 if (PyTuple_CheckExact(attr)) {
783 if (*attrsep == NULL) {
784 *attrsep = PyUnicode_FromString(".");
785 if (*attrsep == NULL)
786 return NULL;
787 }
788 return PyUnicode_Join(*attrsep, attr);
789 } else {
790 Py_INCREF(attr);
791 return attr;
792 }
793}
794
795static PyObject *
796attrgetter_args(attrgetterobject *ag)
797{
798 Py_ssize_t i;
799 PyObject *attrsep = NULL;
800 PyObject *attrstrings = PyTuple_New(ag->nattrs);
801 if (attrstrings == NULL)
802 return NULL;
803
804 for (i = 0; i < ag->nattrs; ++i) {
805 PyObject *attr = PyTuple_GET_ITEM(ag->attr, i);
806 PyObject *attrstr = dotjoinattr(attr, &attrsep);
807 if (attrstr == NULL) {
808 Py_XDECREF(attrsep);
809 Py_DECREF(attrstrings);
810 return NULL;
811 }
812 PyTuple_SET_ITEM(attrstrings, i, attrstr);
813 }
814 Py_XDECREF(attrsep);
815 return attrstrings;
816}
817
818static PyObject *
819attrgetter_repr(attrgetterobject *ag)
820{
821 PyObject *repr = NULL;
822 int status = Py_ReprEnter((PyObject *)ag);
823 if (status != 0) {
824 if (status < 0)
825 return NULL;
826 return PyUnicode_FromFormat("%s(...)", Py_TYPE(ag)->tp_name);
827 }
828
829 if (ag->nattrs == 1) {
830 PyObject *attrsep = NULL;
831 PyObject *attr = dotjoinattr(PyTuple_GET_ITEM(ag->attr, 0), &attrsep);
Serhiy Storchaka548de2b2015-05-21 14:19:20 +0300832 if (attr != NULL) {
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300833 repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(ag)->tp_name, attr);
Serhiy Storchaka548de2b2015-05-21 14:19:20 +0300834 Py_DECREF(attr);
835 }
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300836 Py_XDECREF(attrsep);
837 }
838 else {
839 PyObject *attrstrings = attrgetter_args(ag);
840 if (attrstrings != NULL) {
841 repr = PyUnicode_FromFormat("%s%R",
842 Py_TYPE(ag)->tp_name, attrstrings);
843 Py_DECREF(attrstrings);
844 }
845 }
846 Py_ReprLeave((PyObject *)ag);
847 return repr;
848}
849
850static PyObject *
851attrgetter_reduce(attrgetterobject *ag)
852{
853 PyObject *attrstrings = attrgetter_args(ag);
854 if (attrstrings == NULL)
855 return NULL;
856
857 return Py_BuildValue("ON", Py_TYPE(ag), attrstrings);
858}
859
860static PyMethodDef attrgetter_methods[] = {
861 {"__reduce__", (PyCFunction)attrgetter_reduce, METH_NOARGS,
862 reduce_doc},
863 {NULL}
864};
865
Raymond Hettinger166958b2003-12-01 13:18:39 +0000866PyDoc_STRVAR(attrgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000867"attrgetter(attr, ...) --> attrgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +0000868\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +0000869Return a callable object that fetches the given attribute(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +0300870After f = attrgetter('name'), the call f(r) returns r.name.\n\
871After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
872After h = attrgetter('name.first', 'name.last'), the call h(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000873(r.name.first, r.name.last).");
Raymond Hettinger166958b2003-12-01 13:18:39 +0000874
875static PyTypeObject attrgetter_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000876 PyVarObject_HEAD_INIT(NULL, 0)
877 "operator.attrgetter", /* tp_name */
878 sizeof(attrgetterobject), /* tp_basicsize */
879 0, /* tp_itemsize */
880 /* methods */
881 (destructor)attrgetter_dealloc, /* tp_dealloc */
882 0, /* tp_print */
883 0, /* tp_getattr */
884 0, /* tp_setattr */
885 0, /* tp_reserved */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300886 (reprfunc)attrgetter_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000887 0, /* tp_as_number */
888 0, /* tp_as_sequence */
889 0, /* tp_as_mapping */
890 0, /* tp_hash */
891 (ternaryfunc)attrgetter_call, /* tp_call */
892 0, /* tp_str */
893 PyObject_GenericGetAttr, /* tp_getattro */
894 0, /* tp_setattro */
895 0, /* tp_as_buffer */
896 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
897 attrgetter_doc, /* tp_doc */
898 (traverseproc)attrgetter_traverse, /* tp_traverse */
899 0, /* tp_clear */
900 0, /* tp_richcompare */
901 0, /* tp_weaklistoffset */
902 0, /* tp_iter */
903 0, /* tp_iternext */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300904 attrgetter_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 0, /* tp_members */
906 0, /* tp_getset */
907 0, /* tp_base */
908 0, /* tp_dict */
909 0, /* tp_descr_get */
910 0, /* tp_descr_set */
911 0, /* tp_dictoffset */
912 0, /* tp_init */
913 0, /* tp_alloc */
914 attrgetter_new, /* tp_new */
915 0, /* tp_free */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000916};
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000917
918
919/* methodcaller object **********************************************************/
920
921typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000922 PyObject_HEAD
923 PyObject *name;
924 PyObject *args;
925 PyObject *kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000926} methodcallerobject;
927
928static PyTypeObject methodcaller_type;
929
930static PyObject *
931methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
932{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000933 methodcallerobject *mc;
Benjamin Peterson1f0e7c92016-08-16 23:35:35 -0700934 PyObject *name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000935
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000936 if (PyTuple_GET_SIZE(args) < 1) {
937 PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "
938 "one argument, the method name");
939 return NULL;
940 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000941
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300942 name = PyTuple_GET_ITEM(args, 0);
943 if (!PyUnicode_Check(name)) {
944 PyErr_SetString(PyExc_TypeError,
945 "method name must be a string");
946 return NULL;
947 }
948
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000949 /* create methodcallerobject structure */
950 mc = PyObject_GC_New(methodcallerobject, &methodcaller_type);
951 if (mc == NULL)
952 return NULL;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000953
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000954 name = PyTuple_GET_ITEM(args, 0);
955 Py_INCREF(name);
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300956 PyUnicode_InternInPlace(&name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000957 mc->name = name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000958
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000959 Py_XINCREF(kwds);
960 mc->kwds = kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000961
Benjamin Peterson1f0e7c92016-08-16 23:35:35 -0700962 mc->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
963 if (mc->args == NULL) {
964 Py_DECREF(mc);
965 return NULL;
966 }
967
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000968 PyObject_GC_Track(mc);
969 return (PyObject *)mc;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000970}
971
972static void
973methodcaller_dealloc(methodcallerobject *mc)
974{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975 PyObject_GC_UnTrack(mc);
976 Py_XDECREF(mc->name);
977 Py_XDECREF(mc->args);
978 Py_XDECREF(mc->kwds);
979 PyObject_GC_Del(mc);
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000980}
981
982static int
983methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
984{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000985 Py_VISIT(mc->args);
986 Py_VISIT(mc->kwds);
987 return 0;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000988}
989
990static PyObject *
991methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000993 PyObject *method, *obj, *result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +0000994
Serhiy Storchaka6dfcde52016-04-29 09:10:55 +0300995 if (kw != NULL && !_PyArg_NoKeywords("methodcaller", kw))
Serhiy Storchakac2a2a752016-04-23 10:51:39 +0300996 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
998 return NULL;
999 method = PyObject_GetAttr(obj, mc->name);
1000 if (method == NULL)
1001 return NULL;
1002 result = PyObject_Call(method, mc->args, mc->kwds);
1003 Py_DECREF(method);
1004 return result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001005}
1006
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001007static PyObject *
1008methodcaller_repr(methodcallerobject *mc)
1009{
1010 PyObject *argreprs, *repr = NULL, *sep, *joinedargreprs;
1011 Py_ssize_t numtotalargs, numposargs, numkwdargs, i;
1012 int status = Py_ReprEnter((PyObject *)mc);
1013 if (status != 0) {
1014 if (status < 0)
1015 return NULL;
1016 return PyUnicode_FromFormat("%s(...)", Py_TYPE(mc)->tp_name);
1017 }
1018
1019 if (mc->kwds != NULL) {
1020 numkwdargs = PyDict_Size(mc->kwds);
1021 if (numkwdargs < 0) {
1022 Py_ReprLeave((PyObject *)mc);
1023 return NULL;
1024 }
1025 } else {
1026 numkwdargs = 0;
1027 }
1028
1029 numposargs = PyTuple_GET_SIZE(mc->args);
1030 numtotalargs = numposargs + numkwdargs;
1031
1032 if (numtotalargs == 0) {
1033 repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(mc)->tp_name, mc->name);
1034 Py_ReprLeave((PyObject *)mc);
1035 return repr;
1036 }
1037
1038 argreprs = PyTuple_New(numtotalargs);
1039 if (argreprs == NULL) {
1040 Py_ReprLeave((PyObject *)mc);
1041 return NULL;
1042 }
1043
1044 for (i = 0; i < numposargs; ++i) {
1045 PyObject *onerepr = PyObject_Repr(PyTuple_GET_ITEM(mc->args, i));
1046 if (onerepr == NULL)
1047 goto done;
1048 PyTuple_SET_ITEM(argreprs, i, onerepr);
1049 }
1050
1051 if (numkwdargs != 0) {
1052 PyObject *key, *value;
1053 Py_ssize_t pos = 0;
1054 while (PyDict_Next(mc->kwds, &pos, &key, &value)) {
1055 PyObject *onerepr = PyUnicode_FromFormat("%U=%R", key, value);
1056 if (onerepr == NULL)
1057 goto done;
1058 if (i >= numtotalargs) {
1059 i = -1;
1060 break;
1061 }
1062 PyTuple_SET_ITEM(argreprs, i, onerepr);
1063 ++i;
1064 }
1065 if (i != numtotalargs) {
1066 PyErr_SetString(PyExc_RuntimeError,
1067 "keywords dict changed size during iteration");
1068 goto done;
1069 }
1070 }
1071
1072 sep = PyUnicode_FromString(", ");
1073 if (sep == NULL)
1074 goto done;
1075
1076 joinedargreprs = PyUnicode_Join(sep, argreprs);
1077 Py_DECREF(sep);
1078 if (joinedargreprs == NULL)
1079 goto done;
1080
1081 repr = PyUnicode_FromFormat("%s(%R, %U)", Py_TYPE(mc)->tp_name,
1082 mc->name, joinedargreprs);
1083 Py_DECREF(joinedargreprs);
1084
1085done:
1086 Py_DECREF(argreprs);
1087 Py_ReprLeave((PyObject *)mc);
1088 return repr;
1089}
1090
1091static PyObject *
1092methodcaller_reduce(methodcallerobject *mc)
1093{
1094 PyObject *newargs;
1095 if (!mc->kwds || PyDict_Size(mc->kwds) == 0) {
1096 Py_ssize_t i;
1097 Py_ssize_t callargcount = PyTuple_GET_SIZE(mc->args);
1098 newargs = PyTuple_New(1 + callargcount);
1099 if (newargs == NULL)
1100 return NULL;
1101 Py_INCREF(mc->name);
1102 PyTuple_SET_ITEM(newargs, 0, mc->name);
1103 for (i = 0; i < callargcount; ++i) {
1104 PyObject *arg = PyTuple_GET_ITEM(mc->args, i);
1105 Py_INCREF(arg);
1106 PyTuple_SET_ITEM(newargs, i + 1, arg);
1107 }
1108 return Py_BuildValue("ON", Py_TYPE(mc), newargs);
1109 }
1110 else {
1111 PyObject *functools;
1112 PyObject *partial;
1113 PyObject *constructor;
Victor Stinner7e7823a2016-08-23 00:23:23 +02001114 PyObject *newargs[2];
1115
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001116 _Py_IDENTIFIER(partial);
1117 functools = PyImport_ImportModule("functools");
1118 if (!functools)
1119 return NULL;
1120 partial = _PyObject_GetAttrId(functools, &PyId_partial);
1121 Py_DECREF(functools);
1122 if (!partial)
1123 return NULL;
Victor Stinner7e7823a2016-08-23 00:23:23 +02001124
1125 newargs[0] = (PyObject *)Py_TYPE(mc);
1126 newargs[1] = mc->name;
1127 constructor = _PyObject_FastCallDict(partial, newargs, 2, mc->kwds);
1128
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001129 Py_DECREF(partial);
1130 return Py_BuildValue("NO", constructor, mc->args);
1131 }
1132}
1133
1134static PyMethodDef methodcaller_methods[] = {
1135 {"__reduce__", (PyCFunction)methodcaller_reduce, METH_NOARGS,
1136 reduce_doc},
1137 {NULL}
1138};
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001139PyDoc_STRVAR(methodcaller_doc,
1140"methodcaller(name, ...) --> methodcaller object\n\
1141\n\
1142Return a callable object that calls the given method on its operand.\n\
Antoine Pitroua85017f2013-04-20 19:21:44 +02001143After f = methodcaller('name'), the call f(r) returns r.name().\n\
1144After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001145r.name('date', foo=1).");
1146
1147static PyTypeObject methodcaller_type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 PyVarObject_HEAD_INIT(NULL, 0)
1149 "operator.methodcaller", /* tp_name */
1150 sizeof(methodcallerobject), /* tp_basicsize */
1151 0, /* tp_itemsize */
1152 /* methods */
1153 (destructor)methodcaller_dealloc, /* tp_dealloc */
1154 0, /* tp_print */
1155 0, /* tp_getattr */
1156 0, /* tp_setattr */
1157 0, /* tp_reserved */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001158 (reprfunc)methodcaller_repr, /* tp_repr */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 0, /* tp_as_number */
1160 0, /* tp_as_sequence */
1161 0, /* tp_as_mapping */
1162 0, /* tp_hash */
1163 (ternaryfunc)methodcaller_call, /* tp_call */
1164 0, /* tp_str */
1165 PyObject_GenericGetAttr, /* tp_getattro */
1166 0, /* tp_setattro */
1167 0, /* tp_as_buffer */
1168 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1169 methodcaller_doc, /* tp_doc */
1170 (traverseproc)methodcaller_traverse, /* tp_traverse */
1171 0, /* tp_clear */
1172 0, /* tp_richcompare */
1173 0, /* tp_weaklistoffset */
1174 0, /* tp_iter */
1175 0, /* tp_iternext */
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001176 methodcaller_methods, /* tp_methods */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001177 0, /* tp_members */
1178 0, /* tp_getset */
1179 0, /* tp_base */
1180 0, /* tp_dict */
1181 0, /* tp_descr_get */
1182 0, /* tp_descr_set */
1183 0, /* tp_dictoffset */
1184 0, /* tp_init */
1185 0, /* tp_alloc */
1186 methodcaller_new, /* tp_new */
1187 0, /* tp_free */
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001188};
1189
1190
Antoine Pitroua85017f2013-04-20 19:21:44 +02001191/* Initialization function for the module (*must* be called PyInit__operator) */
Martin v. Löwis1a214512008-06-11 05:26:20 +00001192
1193
1194static struct PyModuleDef operatormodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001195 PyModuleDef_HEAD_INIT,
Antoine Pitroua85017f2013-04-20 19:21:44 +02001196 "_operator",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001197 operator_doc,
1198 -1,
1199 operator_methods,
1200 NULL,
1201 NULL,
1202 NULL,
1203 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001204};
Guido van Rossum037b9401996-07-30 16:55:54 +00001205
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001206PyMODINIT_FUNC
Antoine Pitroua85017f2013-04-20 19:21:44 +02001207PyInit__operator(void)
Guido van Rossum037b9401996-07-30 16:55:54 +00001208{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001209 PyObject *m;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001211 /* Create the module and add the functions */
1212 m = PyModule_Create(&operatormodule);
1213 if (m == NULL)
1214 return NULL;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001215
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001216 if (PyType_Ready(&itemgetter_type) < 0)
1217 return NULL;
1218 Py_INCREF(&itemgetter_type);
1219 PyModule_AddObject(m, "itemgetter", (PyObject *)&itemgetter_type);
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 if (PyType_Ready(&attrgetter_type) < 0)
1222 return NULL;
1223 Py_INCREF(&attrgetter_type);
1224 PyModule_AddObject(m, "attrgetter", (PyObject *)&attrgetter_type);
1225
1226 if (PyType_Ready(&methodcaller_type) < 0)
1227 return NULL;
1228 Py_INCREF(&methodcaller_type);
1229 PyModule_AddObject(m, "methodcaller", (PyObject *)&methodcaller_type);
1230 return m;
Guido van Rossum037b9401996-07-30 16:55:54 +00001231}