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