blob: 5bd5a3bcb9bfe8c12e6bfafd16ebefe7db90bb23 [file] [log] [blame]
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001#include "Python.h"
Victor Stinnercdad2722021-04-22 00:52:52 +02002#include "pycore_moduleobject.h" // _PyModule_GetState()
Serhiy Storchakab813a0e2017-01-19 17:44:13 +02003#include "clinic/_operator.c.h"
4
Dong-hee Na31967fd2020-08-26 17:22:27 +00005typedef struct {
6 PyObject *itemgetter_type;
7 PyObject *attrgetter_type;
8 PyObject *methodcaller_type;
9} _operator_state;
10
11static inline _operator_state*
12get_operator_state(PyObject *module)
13{
Victor Stinnercdad2722021-04-22 00:52:52 +020014 void *state = _PyModule_GetState(module);
Dong-hee Na31967fd2020-08-26 17:22:27 +000015 assert(state != NULL);
16 return (_operator_state *)state;
17}
18
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020019/*[clinic input]
20module _operator
21[clinic start generated code]*/
22/*[clinic end generated code: output=da39a3ee5e6b4b0d input=672ecf48487521e7]*/
23
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000024PyDoc_STRVAR(operator_doc,
25"Operator interface.\n\
Guido van Rossum037b9401996-07-30 16:55:54 +000026\n\
27This module exports a set of functions implemented in C corresponding\n\
28to the intrinsic operators of Python. For example, operator.add(x, y)\n\
29is equivalent to the expression x+y. The function names are those\n\
Benjamin Petersona0dfa822009-11-13 02:25:08 +000030used for special methods; variants without leading and trailing\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000031'__' are also provided for convenience.");
Guido van Rossum037b9401996-07-30 16:55:54 +000032
Guido van Rossum037b9401996-07-30 16:55:54 +000033
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020034/*[clinic input]
35_operator.truth -> bool
Guido van Rossum037b9401996-07-30 16:55:54 +000036
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020037 a: object
38 /
Guido van Rossum037b9401996-07-30 16:55:54 +000039
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020040Return True if a is true, False otherwise.
41[clinic start generated code]*/
Guido van Rossum037b9401996-07-30 16:55:54 +000042
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020043static int
44_operator_truth_impl(PyObject *module, PyObject *a)
45/*[clinic end generated code: output=eaf87767234fa5d7 input=bc74a4cd90235875]*/
Raymond Hettinger5959c552002-08-19 03:19:09 +000046{
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020047 return PyObject_IsTrue(a);
Raymond Hettinger5959c552002-08-19 03:19:09 +000048}
49
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020050/*[clinic input]
51_operator.add
52
53 a: object
54 b: object
55 /
56
57Same as a + b.
58[clinic start generated code]*/
Armin Rigof5bd3b42005-12-29 16:50:42 +000059
Guido van Rossum38fff8c2006-03-07 18:50:55 +000060static PyObject *
Serhiy Storchakab813a0e2017-01-19 17:44:13 +020061_operator_add_impl(PyObject *module, PyObject *a, PyObject *b)
62/*[clinic end generated code: output=8292984204f45164 input=5efe3bff856ac215]*/
63{
64 return PyNumber_Add(a, b);
65}
66
67/*[clinic input]
68_operator.sub = _operator.add
69
70Same as a - b.
71[clinic start generated code]*/
72
73static PyObject *
74_operator_sub_impl(PyObject *module, PyObject *a, PyObject *b)
75/*[clinic end generated code: output=4adfc3b888c1ee2e input=6494c6b100b8e795]*/
76{
77 return PyNumber_Subtract(a, b);
78}
79
80/*[clinic input]
81_operator.mul = _operator.add
82
83Same as a * b.
84[clinic start generated code]*/
85
86static PyObject *
87_operator_mul_impl(PyObject *module, PyObject *a, PyObject *b)
88/*[clinic end generated code: output=d24d66f55a01944c input=2368615b4358b70d]*/
89{
90 return PyNumber_Multiply(a, b);
91}
92
93/*[clinic input]
94_operator.matmul = _operator.add
95
96Same as a @ b.
97[clinic start generated code]*/
98
99static PyObject *
100_operator_matmul_impl(PyObject *module, PyObject *a, PyObject *b)
101/*[clinic end generated code: output=a20d917eb35d0101 input=9ab304e37fb42dd4]*/
102{
103 return PyNumber_MatrixMultiply(a, b);
104}
105
106/*[clinic input]
107_operator.floordiv = _operator.add
108
109Same as a // b.
110[clinic start generated code]*/
111
112static PyObject *
113_operator_floordiv_impl(PyObject *module, PyObject *a, PyObject *b)
114/*[clinic end generated code: output=df26b71a60589f99 input=bb2e88ba446c612c]*/
115{
116 return PyNumber_FloorDivide(a, b);
117}
118
119/*[clinic input]
120_operator.truediv = _operator.add
121
122Same as a / b.
123[clinic start generated code]*/
124
125static PyObject *
126_operator_truediv_impl(PyObject *module, PyObject *a, PyObject *b)
127/*[clinic end generated code: output=0e6a959944d77719 input=ecbb947673f4eb1f]*/
128{
129 return PyNumber_TrueDivide(a, b);
130}
131
132/*[clinic input]
133_operator.mod = _operator.add
134
135Same as a % b.
136[clinic start generated code]*/
137
138static PyObject *
139_operator_mod_impl(PyObject *module, PyObject *a, PyObject *b)
140/*[clinic end generated code: output=9519822f0bbec166 input=102e19b422342ac1]*/
141{
142 return PyNumber_Remainder(a, b);
143}
144
145/*[clinic input]
146_operator.neg
147
148 a: object
149 /
150
151Same as -a.
152[clinic start generated code]*/
153
154static PyObject *
155_operator_neg(PyObject *module, PyObject *a)
156/*[clinic end generated code: output=36e08ecfc6a1c08c input=84f09bdcf27c96ec]*/
157{
158 return PyNumber_Negative(a);
159}
160
161/*[clinic input]
162_operator.pos = _operator.neg
163
164Same as +a.
165[clinic start generated code]*/
166
167static PyObject *
168_operator_pos(PyObject *module, PyObject *a)
169/*[clinic end generated code: output=dad7a126221dd091 input=b6445b63fddb8772]*/
170{
171 return PyNumber_Positive(a);
172}
173
174/*[clinic input]
175_operator.abs = _operator.neg
176
177Same as abs(a).
178[clinic start generated code]*/
179
180static PyObject *
181_operator_abs(PyObject *module, PyObject *a)
182/*[clinic end generated code: output=1389a93ba053ea3e input=341d07ba86f58039]*/
183{
184 return PyNumber_Absolute(a);
185}
186
187/*[clinic input]
188_operator.inv = _operator.neg
189
190Same as ~a.
191[clinic start generated code]*/
192
193static PyObject *
194_operator_inv(PyObject *module, PyObject *a)
195/*[clinic end generated code: output=a56875ba075ee06d input=b01a4677739f6eb2]*/
196{
197 return PyNumber_Invert(a);
198}
199
200/*[clinic input]
201_operator.invert = _operator.neg
202
203Same as ~a.
204[clinic start generated code]*/
205
206static PyObject *
207_operator_invert(PyObject *module, PyObject *a)
208/*[clinic end generated code: output=406b5aa030545fcc input=7f2d607176672e55]*/
209{
210 return PyNumber_Invert(a);
211}
212
213/*[clinic input]
214_operator.lshift = _operator.add
215
216Same as a << b.
217[clinic start generated code]*/
218
219static PyObject *
220_operator_lshift_impl(PyObject *module, PyObject *a, PyObject *b)
221/*[clinic end generated code: output=37f7e52c41435bd8 input=746e8a160cbbc9eb]*/
222{
223 return PyNumber_Lshift(a, b);
224}
225
226/*[clinic input]
227_operator.rshift = _operator.add
228
229Same as a >> b.
230[clinic start generated code]*/
231
232static PyObject *
233_operator_rshift_impl(PyObject *module, PyObject *a, PyObject *b)
234/*[clinic end generated code: output=4593c7ef30ec2ee3 input=d2c85bb5a64504c2]*/
235{
236 return PyNumber_Rshift(a, b);
237}
238
239/*[clinic input]
240_operator.not_ = _operator.truth
241
242Same as not a.
243[clinic start generated code]*/
244
245static int
246_operator_not__impl(PyObject *module, PyObject *a)
247/*[clinic end generated code: output=743f9c24a09759ef input=854156d50804d9b8]*/
248{
249 return PyObject_Not(a);
250}
251
252/*[clinic input]
253_operator.and_ = _operator.add
254
255Same as a & b.
256[clinic start generated code]*/
257
258static PyObject *
259_operator_and__impl(PyObject *module, PyObject *a, PyObject *b)
260/*[clinic end generated code: output=93c4fe88f7b76d9e input=4f3057c90ec4c99f]*/
261{
262 return PyNumber_And(a, b);
263}
264
265/*[clinic input]
266_operator.xor = _operator.add
267
268Same as a ^ b.
269[clinic start generated code]*/
270
271static PyObject *
272_operator_xor_impl(PyObject *module, PyObject *a, PyObject *b)
273/*[clinic end generated code: output=b24cd8b79fde0004 input=3c5cfa7253d808dd]*/
274{
275 return PyNumber_Xor(a, b);
276}
277
278/*[clinic input]
279_operator.or_ = _operator.add
280
281Same as a | b.
282[clinic start generated code]*/
283
284static PyObject *
285_operator_or__impl(PyObject *module, PyObject *a, PyObject *b)
286/*[clinic end generated code: output=58024867b8d90461 input=b40c6c44f7c79c09]*/
287{
288 return PyNumber_Or(a, b);
289}
290
291/*[clinic input]
292_operator.iadd = _operator.add
293
294Same as a += b.
295[clinic start generated code]*/
296
297static PyObject *
298_operator_iadd_impl(PyObject *module, PyObject *a, PyObject *b)
299/*[clinic end generated code: output=07dc627832526eb5 input=d22a91c07ac69227]*/
300{
301 return PyNumber_InPlaceAdd(a, b);
302}
303
304/*[clinic input]
305_operator.isub = _operator.add
306
307Same as a -= b.
308[clinic start generated code]*/
309
310static PyObject *
311_operator_isub_impl(PyObject *module, PyObject *a, PyObject *b)
312/*[clinic end generated code: output=4513467d23b5e0b1 input=4591b00d0a0ccafd]*/
313{
314 return PyNumber_InPlaceSubtract(a, b);
315}
316
317/*[clinic input]
318_operator.imul = _operator.add
319
320Same as a *= b.
321[clinic start generated code]*/
322
323static PyObject *
324_operator_imul_impl(PyObject *module, PyObject *a, PyObject *b)
325/*[clinic end generated code: output=5e87dacd19a71eab input=0e01fb8631e1b76f]*/
326{
327 return PyNumber_InPlaceMultiply(a, b);
328}
329
330/*[clinic input]
331_operator.imatmul = _operator.add
332
333Same as a @= b.
334[clinic start generated code]*/
335
336static PyObject *
337_operator_imatmul_impl(PyObject *module, PyObject *a, PyObject *b)
338/*[clinic end generated code: output=d603cbdf716ce519 input=bb614026372cd542]*/
339{
340 return PyNumber_InPlaceMatrixMultiply(a, b);
341}
342
343/*[clinic input]
344_operator.ifloordiv = _operator.add
345
346Same as a //= b.
347[clinic start generated code]*/
348
349static PyObject *
350_operator_ifloordiv_impl(PyObject *module, PyObject *a, PyObject *b)
351/*[clinic end generated code: output=535336048c681794 input=9df3b5021cff4ca1]*/
352{
353 return PyNumber_InPlaceFloorDivide(a, b);
354}
355
356/*[clinic input]
357_operator.itruediv = _operator.add
358
359Same as a /= b.
360[clinic start generated code]*/
361
362static PyObject *
363_operator_itruediv_impl(PyObject *module, PyObject *a, PyObject *b)
364/*[clinic end generated code: output=28017fbd3563952f input=9a1ee01608f5f590]*/
365{
366 return PyNumber_InPlaceTrueDivide(a, b);
367}
368
369/*[clinic input]
370_operator.imod = _operator.add
371
372Same as a %= b.
373[clinic start generated code]*/
374
375static PyObject *
376_operator_imod_impl(PyObject *module, PyObject *a, PyObject *b)
377/*[clinic end generated code: output=f7c540ae0fc70904 input=d0c384a3ce38e1dd]*/
378{
379 return PyNumber_InPlaceRemainder(a, b);
380}
381
382/*[clinic input]
383_operator.ilshift = _operator.add
384
385Same as a <<= b.
386[clinic start generated code]*/
387
388static PyObject *
389_operator_ilshift_impl(PyObject *module, PyObject *a, PyObject *b)
390/*[clinic end generated code: output=e73a8fee1ac18749 input=e21b6b310f54572e]*/
391{
392 return PyNumber_InPlaceLshift(a, b);
393}
394
395/*[clinic input]
396_operator.irshift = _operator.add
397
398Same as a >>= b.
399[clinic start generated code]*/
400
401static PyObject *
402_operator_irshift_impl(PyObject *module, PyObject *a, PyObject *b)
403/*[clinic end generated code: output=97f2af6b5ff2ed81 input=6778dbd0f6e1ec16]*/
404{
405 return PyNumber_InPlaceRshift(a, b);
406}
407
408/*[clinic input]
409_operator.iand = _operator.add
410
411Same as a &= b.
412[clinic start generated code]*/
413
414static PyObject *
415_operator_iand_impl(PyObject *module, PyObject *a, PyObject *b)
416/*[clinic end generated code: output=4599e9d40cbf7d00 input=71dfd8e70c156a7b]*/
417{
418 return PyNumber_InPlaceAnd(a, b);
419}
420
421/*[clinic input]
422_operator.ixor = _operator.add
423
424Same as a ^= b.
425[clinic start generated code]*/
426
427static PyObject *
428_operator_ixor_impl(PyObject *module, PyObject *a, PyObject *b)
429/*[clinic end generated code: output=5ff881766872be03 input=695c32bec0604d86]*/
430{
431 return PyNumber_InPlaceXor(a, b);
432}
433
434/*[clinic input]
435_operator.ior = _operator.add
436
437Same as a |= b.
438[clinic start generated code]*/
439
440static PyObject *
441_operator_ior_impl(PyObject *module, PyObject *a, PyObject *b)
442/*[clinic end generated code: output=48aac319445bf759 input=8f01d03eda9920cf]*/
443{
444 return PyNumber_InPlaceOr(a, b);
445}
446
447/*[clinic input]
448_operator.concat = _operator.add
449
450Same as a + b, for a and b sequences.
451[clinic start generated code]*/
452
453static PyObject *
454_operator_concat_impl(PyObject *module, PyObject *a, PyObject *b)
455/*[clinic end generated code: output=80028390942c5f11 input=8544ccd5341a3658]*/
456{
457 return PySequence_Concat(a, b);
458}
459
460/*[clinic input]
461_operator.iconcat = _operator.add
462
463Same as a += b, for a and b sequences.
464[clinic start generated code]*/
465
466static PyObject *
467_operator_iconcat_impl(PyObject *module, PyObject *a, PyObject *b)
468/*[clinic end generated code: output=3ea0a162ebb2e26d input=8f5fe5722fcd837e]*/
469{
470 return PySequence_InPlaceConcat(a, b);
471}
472
473/*[clinic input]
474_operator.contains -> bool
475
476 a: object
477 b: object
478 /
479
480Same as b in a (note reversed operands).
481[clinic start generated code]*/
482
483static int
484_operator_contains_impl(PyObject *module, PyObject *a, PyObject *b)
485/*[clinic end generated code: output=413b4dbe82b6ffc1 input=9122a69b505fde13]*/
486{
487 return PySequence_Contains(a, b);
488}
489
490/*[clinic input]
491_operator.indexOf -> Py_ssize_t
492
493 a: object
494 b: object
495 /
496
497Return the first index of b in a.
498[clinic start generated code]*/
499
500static Py_ssize_t
501_operator_indexOf_impl(PyObject *module, PyObject *a, PyObject *b)
502/*[clinic end generated code: output=c6226d8e0fb60fa6 input=8be2e43b6a6fffe3]*/
503{
504 return PySequence_Index(a, b);
505}
506
507/*[clinic input]
508_operator.countOf = _operator.indexOf
509
510Return the number of times b occurs in a.
511[clinic start generated code]*/
512
513static Py_ssize_t
514_operator_countOf_impl(PyObject *module, PyObject *a, PyObject *b)
515/*[clinic end generated code: output=9e1623197daf3382 input=0c3a2656add252db]*/
516{
517 return PySequence_Count(a, b);
518}
519
520/*[clinic input]
521_operator.getitem
522
523 a: object
524 b: object
525 /
526
527Same as a[b].
528[clinic start generated code]*/
529
530static PyObject *
531_operator_getitem_impl(PyObject *module, PyObject *a, PyObject *b)
532/*[clinic end generated code: output=6c8d8101a676e594 input=6682797320e48845]*/
533{
534 return PyObject_GetItem(a, b);
535}
536
537/*[clinic input]
538_operator.setitem
539
540 a: object
541 b: object
542 c: object
543 /
544
545Same as a[b] = c.
546[clinic start generated code]*/
547
548static PyObject *
549_operator_setitem_impl(PyObject *module, PyObject *a, PyObject *b,
550 PyObject *c)
551/*[clinic end generated code: output=1324f9061ae99e25 input=ceaf453c4d3a58df]*/
552{
553 if (-1 == PyObject_SetItem(a, b, c))
554 return NULL;
555 Py_RETURN_NONE;
556}
557
558/*[clinic input]
559_operator.delitem = _operator.getitem
560
561Same as del a[b].
562[clinic start generated code]*/
563
564static PyObject *
565_operator_delitem_impl(PyObject *module, PyObject *a, PyObject *b)
566/*[clinic end generated code: output=db18f61506295799 input=991bec56a0d3ec7f]*/
567{
568 if (-1 == PyObject_DelItem(a, b))
569 return NULL;
570 Py_RETURN_NONE;
571}
572
573/*[clinic input]
574_operator.eq
575
576 a: object
577 b: object
578 /
579
580Same as a == b.
581[clinic start generated code]*/
582
583static PyObject *
584_operator_eq_impl(PyObject *module, PyObject *a, PyObject *b)
585/*[clinic end generated code: output=8d7d46ed4135677c input=586fca687a95a83f]*/
586{
587 return PyObject_RichCompare(a, b, Py_EQ);
588}
589
590/*[clinic input]
591_operator.ne = _operator.eq
592
593Same as a != b.
594[clinic start generated code]*/
595
596static PyObject *
597_operator_ne_impl(PyObject *module, PyObject *a, PyObject *b)
598/*[clinic end generated code: output=c99bd0c3a4c01297 input=5d88f23d35e9abac]*/
599{
600 return PyObject_RichCompare(a, b, Py_NE);
601}
602
603/*[clinic input]
604_operator.lt = _operator.eq
605
606Same as a < b.
607[clinic start generated code]*/
608
609static PyObject *
610_operator_lt_impl(PyObject *module, PyObject *a, PyObject *b)
611/*[clinic end generated code: output=082d7c45c440e535 input=34a59ad6d39d3a2b]*/
612{
613 return PyObject_RichCompare(a, b, Py_LT);
614}
615
616/*[clinic input]
617_operator.le = _operator.eq
618
619Same as a <= b.
620[clinic start generated code]*/
621
622static PyObject *
623_operator_le_impl(PyObject *module, PyObject *a, PyObject *b)
624/*[clinic end generated code: output=00970a2923d0ae17 input=b812a7860a0bef44]*/
625{
626 return PyObject_RichCompare(a, b, Py_LE);
627}
628
629/*[clinic input]
630_operator.gt = _operator.eq
631
632Same as a > b.
633[clinic start generated code]*/
634
635static PyObject *
636_operator_gt_impl(PyObject *module, PyObject *a, PyObject *b)
637/*[clinic end generated code: output=8d373349ecf25641 input=9bdb45b995ada35b]*/
638{
639 return PyObject_RichCompare(a, b, Py_GT);
640}
641
642/*[clinic input]
643_operator.ge = _operator.eq
644
645Same as a >= b.
646[clinic start generated code]*/
647
648static PyObject *
649_operator_ge_impl(PyObject *module, PyObject *a, PyObject *b)
650/*[clinic end generated code: output=7ce3882256d4b137 input=cf1dc4a5ca9c35f5]*/
651{
652 return PyObject_RichCompare(a, b, Py_GE);
653}
654
655/*[clinic input]
656_operator.pow = _operator.add
657
658Same as a ** b.
659[clinic start generated code]*/
660
661static PyObject *
662_operator_pow_impl(PyObject *module, PyObject *a, PyObject *b)
663/*[clinic end generated code: output=09e668ad50036120 input=690b40f097ab1637]*/
664{
665 return PyNumber_Power(a, b, Py_None);
666}
667
668/*[clinic input]
669_operator.ipow = _operator.add
670
671Same as a **= b.
672[clinic start generated code]*/
673
674static PyObject *
675_operator_ipow_impl(PyObject *module, PyObject *a, PyObject *b)
676/*[clinic end generated code: output=7189ff4d4367c808 input=f00623899d07499a]*/
677{
678 return PyNumber_InPlacePower(a, b, Py_None);
679}
680
681/*[clinic input]
682_operator.index
683
684 a: object
685 /
686
687Same as a.__index__()
688[clinic start generated code]*/
689
690static PyObject *
691_operator_index(PyObject *module, PyObject *a)
692/*[clinic end generated code: output=d972b0764ac305fc input=6f54d50ea64a579c]*/
Guido van Rossum38fff8c2006-03-07 18:50:55 +0000693{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 return PyNumber_Index(a);
Guido van Rossum38fff8c2006-03-07 18:50:55 +0000695}
696
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200697/*[clinic input]
698_operator.is_ = _operator.add
699
700Same as a is b.
701[clinic start generated code]*/
702
703static PyObject *
704_operator_is__impl(PyObject *module, PyObject *a, PyObject *b)
705/*[clinic end generated code: output=bcd47a402e482e1d input=5fa9b97df03c427f]*/
Raymond Hettinger9543b342003-01-18 23:22:20 +0000706{
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200707 PyObject *result;
708 result = (a == b) ? Py_True : Py_False;
709 Py_INCREF(result);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000710 return result;
Raymond Hettinger9543b342003-01-18 23:22:20 +0000711}
712
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200713/*[clinic input]
714_operator.is_not = _operator.add
715
716Same as a is not b.
717[clinic start generated code]*/
718
719static PyObject *
720_operator_is_not_impl(PyObject *module, PyObject *a, PyObject *b)
721/*[clinic end generated code: output=491a1f2f81f6c7f9 input=5a93f7e1a93535f1]*/
Raymond Hettinger9543b342003-01-18 23:22:20 +0000722{
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200723 PyObject *result;
724 result = (a != b) ? Py_True : Py_False;
725 Py_INCREF(result);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 return result;
Raymond Hettinger9543b342003-01-18 23:22:20 +0000727}
728
Christian Heimes6cea6552012-06-24 13:48:32 +0200729/* compare_digest **********************************************************/
730
731/*
732 * timing safe compare
733 *
734 * Returns 1 of the strings are equal.
735 * In case of len(a) != len(b) the function tries to keep the timing
736 * dependent on the length of b. CPU cache locally may still alter timing
737 * a bit.
738 */
739static int
740_tscmp(const unsigned char *a, const unsigned char *b,
741 Py_ssize_t len_a, Py_ssize_t len_b)
742{
743 /* The volatile type declarations make sure that the compiler has no
744 * chance to optimize and fold the code in any way that may change
745 * the timing.
746 */
747 volatile Py_ssize_t length;
748 volatile const unsigned char *left;
749 volatile const unsigned char *right;
750 Py_ssize_t i;
Devin Jeanpierre31729362020-11-21 01:55:23 -0700751 volatile unsigned char result;
Christian Heimes6cea6552012-06-24 13:48:32 +0200752
753 /* loop count depends on length of b */
754 length = len_b;
755 left = NULL;
756 right = b;
757
758 /* don't use else here to keep the amount of CPU instructions constant,
759 * volatile forces re-evaluation
760 * */
761 if (len_a == length) {
762 left = *((volatile const unsigned char**)&a);
763 result = 0;
764 }
765 if (len_a != length) {
766 left = b;
767 result = 1;
768 }
769
770 for (i=0; i < length; i++) {
771 result |= *left++ ^ *right++;
772 }
773
774 return (result == 0);
775}
776
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200777/*[clinic input]
778_operator.length_hint -> Py_ssize_t
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200779
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200780 obj: object
781 default: Py_ssize_t = 0
782 /
783
784Return an estimate of the number of items in obj.
785
786This is useful for presizing containers when building from an iterable.
787
788If the object supports len(), the result will be exact.
789Otherwise, it may over- or under-estimate by an arbitrary amount.
790The result will be an integer >= 0.
791[clinic start generated code]*/
792
793static Py_ssize_t
794_operator_length_hint_impl(PyObject *module, PyObject *obj,
795 Py_ssize_t default_value)
796/*[clinic end generated code: output=01d469edc1d612ad input=65ed29f04401e96a]*/
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200797{
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200798 return PyObject_LengthHint(obj, default_value);
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200799}
800
Christian Heimesdb5aed92020-05-27 21:50:06 +0200801/* NOTE: Keep in sync with _hashopenssl.c implementation. */
802
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200803/*[clinic input]
804_operator._compare_digest = _operator.eq
Armin Ronacheraa9a79d2012-10-06 14:03:24 +0200805
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200806Return 'a == b'.
Christian Heimes6cea6552012-06-24 13:48:32 +0200807
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200808This function uses an approach designed to prevent
809timing analysis, making it appropriate for cryptography.
810
811a and b must both be of the same type: either str (ASCII only),
812or any bytes-like object.
813
814Note: If a and b are of different lengths, or if an error occurs,
815a timing attack could theoretically reveal information about the
816types and lengths of a and b--but not their values.
817[clinic start generated code]*/
818
819static PyObject *
820_operator__compare_digest_impl(PyObject *module, PyObject *a, PyObject *b)
821/*[clinic end generated code: output=11d452bdd3a23cbc input=9ac7e2c4e30bc356]*/
Christian Heimes6cea6552012-06-24 13:48:32 +0200822{
Christian Heimes6cea6552012-06-24 13:48:32 +0200823 int rc;
Christian Heimes6cea6552012-06-24 13:48:32 +0200824
Christian Heimes6cea6552012-06-24 13:48:32 +0200825 /* ASCII unicode string */
826 if(PyUnicode_Check(a) && PyUnicode_Check(b)) {
827 if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
828 return NULL;
829 }
830 if (!PyUnicode_IS_ASCII(a) || !PyUnicode_IS_ASCII(b)) {
831 PyErr_SetString(PyExc_TypeError,
832 "comparing strings with non-ASCII characters is "
833 "not supported");
834 return NULL;
835 }
836
837 rc = _tscmp(PyUnicode_DATA(a),
838 PyUnicode_DATA(b),
839 PyUnicode_GET_LENGTH(a),
840 PyUnicode_GET_LENGTH(b));
841 }
842 /* fallback to buffer interface for bytes, bytesarray and other */
843 else {
844 Py_buffer view_a;
845 Py_buffer view_b;
846
Benjamin Peterson23a192d2014-05-11 16:17:02 -0700847 if (PyObject_CheckBuffer(a) == 0 && PyObject_CheckBuffer(b) == 0) {
Christian Heimes6cea6552012-06-24 13:48:32 +0200848 PyErr_Format(PyExc_TypeError,
849 "unsupported operand types(s) or combination of types: "
850 "'%.100s' and '%.100s'",
851 Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
852 return NULL;
853 }
854
855 if (PyObject_GetBuffer(a, &view_a, PyBUF_SIMPLE) == -1) {
856 return NULL;
857 }
858 if (view_a.ndim > 1) {
859 PyErr_SetString(PyExc_BufferError,
860 "Buffer must be single dimension");
861 PyBuffer_Release(&view_a);
862 return NULL;
863 }
864
865 if (PyObject_GetBuffer(b, &view_b, PyBUF_SIMPLE) == -1) {
866 PyBuffer_Release(&view_a);
867 return NULL;
868 }
869 if (view_b.ndim > 1) {
870 PyErr_SetString(PyExc_BufferError,
871 "Buffer must be single dimension");
872 PyBuffer_Release(&view_a);
873 PyBuffer_Release(&view_b);
874 return NULL;
875 }
876
877 rc = _tscmp((const unsigned char*)view_a.buf,
878 (const unsigned char*)view_b.buf,
879 view_a.len,
880 view_b.len);
881
882 PyBuffer_Release(&view_a);
883 PyBuffer_Release(&view_b);
884 }
885
Georg Brandl93b7d7e2012-06-24 13:54:51 +0200886 return PyBool_FromLong(rc);
Christian Heimes6cea6552012-06-24 13:48:32 +0200887}
888
889/* operator methods **********************************************************/
890
Guido van Rossum037b9401996-07-30 16:55:54 +0000891static struct PyMethodDef operator_methods[] = {
Guido van Rossum037b9401996-07-30 16:55:54 +0000892
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200893 _OPERATOR_TRUTH_METHODDEF
894 _OPERATOR_CONTAINS_METHODDEF
895 _OPERATOR_INDEXOF_METHODDEF
896 _OPERATOR_COUNTOF_METHODDEF
897 _OPERATOR_IS__METHODDEF
898 _OPERATOR_IS_NOT_METHODDEF
899 _OPERATOR_INDEX_METHODDEF
900 _OPERATOR_ADD_METHODDEF
901 _OPERATOR_SUB_METHODDEF
902 _OPERATOR_MUL_METHODDEF
903 _OPERATOR_MATMUL_METHODDEF
904 _OPERATOR_FLOORDIV_METHODDEF
905 _OPERATOR_TRUEDIV_METHODDEF
906 _OPERATOR_MOD_METHODDEF
907 _OPERATOR_NEG_METHODDEF
908 _OPERATOR_POS_METHODDEF
909 _OPERATOR_ABS_METHODDEF
910 _OPERATOR_INV_METHODDEF
911 _OPERATOR_INVERT_METHODDEF
912 _OPERATOR_LSHIFT_METHODDEF
913 _OPERATOR_RSHIFT_METHODDEF
914 _OPERATOR_NOT__METHODDEF
915 _OPERATOR_AND__METHODDEF
916 _OPERATOR_XOR_METHODDEF
917 _OPERATOR_OR__METHODDEF
918 _OPERATOR_IADD_METHODDEF
919 _OPERATOR_ISUB_METHODDEF
920 _OPERATOR_IMUL_METHODDEF
921 _OPERATOR_IMATMUL_METHODDEF
922 _OPERATOR_IFLOORDIV_METHODDEF
923 _OPERATOR_ITRUEDIV_METHODDEF
924 _OPERATOR_IMOD_METHODDEF
925 _OPERATOR_ILSHIFT_METHODDEF
926 _OPERATOR_IRSHIFT_METHODDEF
927 _OPERATOR_IAND_METHODDEF
928 _OPERATOR_IXOR_METHODDEF
929 _OPERATOR_IOR_METHODDEF
930 _OPERATOR_CONCAT_METHODDEF
931 _OPERATOR_ICONCAT_METHODDEF
932 _OPERATOR_GETITEM_METHODDEF
933 _OPERATOR_SETITEM_METHODDEF
934 _OPERATOR_DELITEM_METHODDEF
935 _OPERATOR_POW_METHODDEF
936 _OPERATOR_IPOW_METHODDEF
937 _OPERATOR_EQ_METHODDEF
938 _OPERATOR_NE_METHODDEF
939 _OPERATOR_LT_METHODDEF
940 _OPERATOR_LE_METHODDEF
941 _OPERATOR_GT_METHODDEF
942 _OPERATOR_GE_METHODDEF
943 _OPERATOR__COMPARE_DIGEST_METHODDEF
944 _OPERATOR_LENGTH_HINT_METHODDEF
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000945 {NULL, NULL} /* sentinel */
Guido van Rossum037b9401996-07-30 16:55:54 +0000946
Guido van Rossum037b9401996-07-30 16:55:54 +0000947};
948
Raymond Hettinger166958b2003-12-01 13:18:39 +0000949/* itemgetter object **********************************************************/
Guido van Rossum037b9401996-07-30 16:55:54 +0000950
Raymond Hettinger166958b2003-12-01 13:18:39 +0000951typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000952 PyObject_HEAD
953 Py_ssize_t nitems;
954 PyObject *item;
Raymond Hettinger2d53bed2019-01-07 09:38:41 -0700955 Py_ssize_t index; // -1 unless *item* is a single non-negative integer index
Raymond Hettinger166958b2003-12-01 13:18:39 +0000956} itemgetterobject;
957
Serhiy Storchakab813a0e2017-01-19 17:44:13 +0200958/* AC 3.5: treats first argument as an iterable, otherwise uses *args */
Raymond Hettinger166958b2003-12-01 13:18:39 +0000959static PyObject *
960itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
961{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 itemgetterobject *ig;
963 PyObject *item;
964 Py_ssize_t nitems;
Raymond Hettinger2d53bed2019-01-07 09:38:41 -0700965 Py_ssize_t index;
Raymond Hettinger166958b2003-12-01 13:18:39 +0000966
Serhiy Storchaka6cca5c82017-06-08 14:41:19 +0300967 if (!_PyArg_NoKeywords("itemgetter", kwds))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000968 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +0000969
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000970 nitems = PyTuple_GET_SIZE(args);
971 if (nitems <= 1) {
972 if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item))
973 return NULL;
Dong-hee Na31967fd2020-08-26 17:22:27 +0000974 } else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000975 item = args;
Dong-hee Na31967fd2020-08-26 17:22:27 +0000976 }
977 _operator_state *state = PyType_GetModuleState(type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000978 /* create itemgetterobject structure */
Dong-hee Na31967fd2020-08-26 17:22:27 +0000979 ig = PyObject_GC_New(itemgetterobject, (PyTypeObject *) state->itemgetter_type);
980 if (ig == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000981 return NULL;
Dong-hee Na31967fd2020-08-26 17:22:27 +0000982 }
Raymond Hettinger166958b2003-12-01 13:18:39 +0000983
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000984 Py_INCREF(item);
985 ig->item = item;
986 ig->nitems = nitems;
Raymond Hettinger2d53bed2019-01-07 09:38:41 -0700987 ig->index = -1;
988 if (PyLong_CheckExact(item)) {
989 index = PyLong_AsSsize_t(item);
990 if (index < 0) {
991 /* If we get here, then either the index conversion failed
992 * due to being out of range, or the index was a negative
993 * integer. Either way, we clear any possible exception
994 * and fall back to the slow path, where ig->index is -1.
995 */
996 PyErr_Clear();
997 }
998 else {
999 ig->index = index;
1000 }
1001 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002
1003 PyObject_GC_Track(ig);
1004 return (PyObject *)ig;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001005}
1006
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001007static int
1008itemgetter_clear(itemgetterobject *ig)
1009{
1010 Py_CLEAR(ig->item);
1011 return 0;
1012}
1013
Raymond Hettinger166958b2003-12-01 13:18:39 +00001014static void
1015itemgetter_dealloc(itemgetterobject *ig)
1016{
Dong-hee Na31967fd2020-08-26 17:22:27 +00001017 PyTypeObject *tp = Py_TYPE(ig);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001018 PyObject_GC_UnTrack(ig);
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001019 (void)itemgetter_clear(ig);
Dong-hee Na31967fd2020-08-26 17:22:27 +00001020 tp->tp_free(ig);
1021 Py_DECREF(tp);
Raymond Hettinger166958b2003-12-01 13:18:39 +00001022}
1023
1024static int
1025itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
1026{
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001027 Py_VISIT(Py_TYPE(ig));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001028 Py_VISIT(ig->item);
1029 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001030}
1031
1032static PyObject *
1033itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)
1034{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001035 PyObject *obj, *result;
1036 Py_ssize_t i, nitems=ig->nitems;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001037
Raymond Hettinger2d53bed2019-01-07 09:38:41 -07001038 assert(PyTuple_CheckExact(args));
Serhiy Storchaka79342662019-01-12 08:25:41 +02001039 if (!_PyArg_NoKeywords("itemgetter", kw))
1040 return NULL;
1041 if (!_PyArg_CheckPositional("itemgetter", PyTuple_GET_SIZE(args), 1, 1))
1042 return NULL;
1043
1044 obj = PyTuple_GET_ITEM(args, 0);
Raymond Hettinger2d53bed2019-01-07 09:38:41 -07001045 if (nitems == 1) {
1046 if (ig->index >= 0
1047 && PyTuple_CheckExact(obj)
1048 && ig->index < PyTuple_GET_SIZE(obj))
1049 {
1050 result = PyTuple_GET_ITEM(obj, ig->index);
1051 Py_INCREF(result);
1052 return result;
1053 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 return PyObject_GetItem(obj, ig->item);
Raymond Hettinger2d53bed2019-01-07 09:38:41 -07001055 }
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001057 assert(PyTuple_Check(ig->item));
1058 assert(PyTuple_GET_SIZE(ig->item) == nitems);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001059
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 result = PyTuple_New(nitems);
1061 if (result == NULL)
1062 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001063
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001064 for (i=0 ; i < nitems ; i++) {
1065 PyObject *item, *val;
1066 item = PyTuple_GET_ITEM(ig->item, i);
1067 val = PyObject_GetItem(obj, item);
1068 if (val == NULL) {
1069 Py_DECREF(result);
1070 return NULL;
1071 }
1072 PyTuple_SET_ITEM(result, i, val);
1073 }
1074 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001075}
1076
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001077static PyObject *
1078itemgetter_repr(itemgetterobject *ig)
1079{
1080 PyObject *repr;
1081 const char *reprfmt;
1082
1083 int status = Py_ReprEnter((PyObject *)ig);
1084 if (status != 0) {
1085 if (status < 0)
1086 return NULL;
1087 return PyUnicode_FromFormat("%s(...)", Py_TYPE(ig)->tp_name);
1088 }
1089
1090 reprfmt = ig->nitems == 1 ? "%s(%R)" : "%s%R";
1091 repr = PyUnicode_FromFormat(reprfmt, Py_TYPE(ig)->tp_name, ig->item);
1092 Py_ReprLeave((PyObject *)ig);
1093 return repr;
1094}
1095
1096static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301097itemgetter_reduce(itemgetterobject *ig, PyObject *Py_UNUSED(ignored))
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001098{
1099 if (ig->nitems == 1)
1100 return Py_BuildValue("O(O)", Py_TYPE(ig), ig->item);
1101 return PyTuple_Pack(2, Py_TYPE(ig), ig->item);
1102}
1103
1104PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1105
1106static PyMethodDef itemgetter_methods[] = {
1107 {"__reduce__", (PyCFunction)itemgetter_reduce, METH_NOARGS,
1108 reduce_doc},
1109 {NULL}
1110};
1111
Raymond Hettinger166958b2003-12-01 13:18:39 +00001112PyDoc_STRVAR(itemgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001113"itemgetter(item, ...) --> itemgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +00001114\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001115Return a callable object that fetches the given item(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +03001116After f = itemgetter(2), the call f(r) returns r[2].\n\
1117After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])");
Raymond Hettinger166958b2003-12-01 13:18:39 +00001118
Dong-hee Na31967fd2020-08-26 17:22:27 +00001119static PyType_Slot itemgetter_type_slots[] = {
1120 {Py_tp_doc, (void *)itemgetter_doc},
1121 {Py_tp_dealloc, itemgetter_dealloc},
1122 {Py_tp_call, itemgetter_call},
1123 {Py_tp_traverse, itemgetter_traverse},
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001124 {Py_tp_clear, itemgetter_clear},
Dong-hee Na31967fd2020-08-26 17:22:27 +00001125 {Py_tp_methods, itemgetter_methods},
1126 {Py_tp_new, itemgetter_new},
1127 {Py_tp_getattro, PyObject_GenericGetAttr},
1128 {Py_tp_repr, itemgetter_repr},
1129 {0, 0}
Raymond Hettinger166958b2003-12-01 13:18:39 +00001130};
1131
Dong-hee Na31967fd2020-08-26 17:22:27 +00001132static PyType_Spec itemgetter_type_spec = {
1133 .name = "operator.itemgetter",
1134 .basicsize = sizeof(itemgetterobject),
1135 .itemsize = 0,
1136 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1137 .slots = itemgetter_type_slots,
1138};
Raymond Hettinger166958b2003-12-01 13:18:39 +00001139
1140/* attrgetter object **********************************************************/
1141
1142typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001143 PyObject_HEAD
1144 Py_ssize_t nattrs;
1145 PyObject *attr;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001146} attrgetterobject;
1147
Serhiy Storchakab813a0e2017-01-19 17:44:13 +02001148/* AC 3.5: treats first argument as an iterable, otherwise uses *args */
Raymond Hettinger166958b2003-12-01 13:18:39 +00001149static PyObject *
1150attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1151{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001152 attrgetterobject *ag;
1153 PyObject *attr;
Antoine Pitroue9745712010-10-31 15:26:04 +00001154 Py_ssize_t nattrs, idx, char_idx;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001155
Serhiy Storchaka6cca5c82017-06-08 14:41:19 +03001156 if (!_PyArg_NoKeywords("attrgetter", kwds))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 return NULL;
Georg Brandl02c42872005-08-26 06:42:30 +00001158
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001159 nattrs = PyTuple_GET_SIZE(args);
1160 if (nattrs <= 1) {
1161 if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &attr))
1162 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +00001163 }
1164
1165 attr = PyTuple_New(nattrs);
1166 if (attr == NULL)
1167 return NULL;
1168
1169 /* prepare attr while checking args */
1170 for (idx = 0; idx < nattrs; ++idx) {
1171 PyObject *item = PyTuple_GET_ITEM(args, idx);
1172 Py_ssize_t item_len;
Serhiy Storchakacd8295f2020-04-11 10:48:40 +03001173 const void *data;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001174 unsigned int kind;
Antoine Pitroue9745712010-10-31 15:26:04 +00001175 int dot_count;
1176
1177 if (!PyUnicode_Check(item)) {
1178 PyErr_SetString(PyExc_TypeError,
1179 "attribute name must be a string");
1180 Py_DECREF(attr);
1181 return NULL;
1182 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001183 if (PyUnicode_READY(item)) {
1184 Py_DECREF(attr);
1185 return NULL;
1186 }
1187 item_len = PyUnicode_GET_LENGTH(item);
1188 kind = PyUnicode_KIND(item);
1189 data = PyUnicode_DATA(item);
Antoine Pitroue9745712010-10-31 15:26:04 +00001190
1191 /* check whethere the string is dotted */
1192 dot_count = 0;
1193 for (char_idx = 0; char_idx < item_len; ++char_idx) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001194 if (PyUnicode_READ(kind, data, char_idx) == '.')
Antoine Pitroue9745712010-10-31 15:26:04 +00001195 ++dot_count;
1196 }
1197
1198 if (dot_count == 0) {
1199 Py_INCREF(item);
1200 PyUnicode_InternInPlace(&item);
1201 PyTuple_SET_ITEM(attr, idx, item);
1202 } else { /* make it a tuple of non-dotted attrnames */
1203 PyObject *attr_chain = PyTuple_New(dot_count + 1);
1204 PyObject *attr_chain_item;
Antoine Pitrou87298c42010-10-31 21:03:01 +00001205 Py_ssize_t unibuff_from = 0;
1206 Py_ssize_t unibuff_till = 0;
1207 Py_ssize_t attr_chain_idx = 0;
Antoine Pitroue9745712010-10-31 15:26:04 +00001208
1209 if (attr_chain == NULL) {
1210 Py_DECREF(attr);
1211 return NULL;
1212 }
1213
Antoine Pitroue9745712010-10-31 15:26:04 +00001214 for (; dot_count > 0; --dot_count) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001215 while (PyUnicode_READ(kind, data, unibuff_till) != '.') {
Antoine Pitroue9745712010-10-31 15:26:04 +00001216 ++unibuff_till;
1217 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001218 attr_chain_item = PyUnicode_Substring(item,
1219 unibuff_from,
1220 unibuff_till);
Antoine Pitroue9745712010-10-31 15:26:04 +00001221 if (attr_chain_item == NULL) {
1222 Py_DECREF(attr_chain);
1223 Py_DECREF(attr);
1224 return NULL;
1225 }
1226 PyUnicode_InternInPlace(&attr_chain_item);
1227 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
1228 ++attr_chain_idx;
1229 unibuff_till = unibuff_from = unibuff_till + 1;
1230 }
1231
1232 /* now add the last dotless name */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001233 attr_chain_item = PyUnicode_Substring(item,
1234 unibuff_from, item_len);
Antoine Pitroue9745712010-10-31 15:26:04 +00001235 if (attr_chain_item == NULL) {
1236 Py_DECREF(attr_chain);
1237 Py_DECREF(attr);
1238 return NULL;
1239 }
1240 PyUnicode_InternInPlace(&attr_chain_item);
1241 PyTuple_SET_ITEM(attr_chain, attr_chain_idx, attr_chain_item);
1242
1243 PyTuple_SET_ITEM(attr, idx, attr_chain);
1244 }
1245 }
Raymond Hettinger166958b2003-12-01 13:18:39 +00001246
Dong-hee Na31967fd2020-08-26 17:22:27 +00001247 _operator_state *state = PyType_GetModuleState(type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001248 /* create attrgetterobject structure */
Dong-hee Na31967fd2020-08-26 17:22:27 +00001249 ag = PyObject_GC_New(attrgetterobject, (PyTypeObject *)state->attrgetter_type);
Antoine Pitroue9745712010-10-31 15:26:04 +00001250 if (ag == NULL) {
1251 Py_DECREF(attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001252 return NULL;
Antoine Pitroue9745712010-10-31 15:26:04 +00001253 }
Raymond Hettinger166958b2003-12-01 13:18:39 +00001254
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 ag->attr = attr;
1256 ag->nattrs = nattrs;
1257
1258 PyObject_GC_Track(ag);
1259 return (PyObject *)ag;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001260}
1261
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001262static int
1263attrgetter_clear(attrgetterobject *ag)
1264{
1265 Py_CLEAR(ag->attr);
1266 return 0;
1267}
1268
Raymond Hettinger166958b2003-12-01 13:18:39 +00001269static void
1270attrgetter_dealloc(attrgetterobject *ag)
1271{
Dong-hee Na31967fd2020-08-26 17:22:27 +00001272 PyTypeObject *tp = Py_TYPE(ag);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001273 PyObject_GC_UnTrack(ag);
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001274 (void)attrgetter_clear(ag);
Dong-hee Na31967fd2020-08-26 17:22:27 +00001275 tp->tp_free(ag);
1276 Py_DECREF(tp);
Raymond Hettinger166958b2003-12-01 13:18:39 +00001277}
1278
1279static int
1280attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
1281{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 Py_VISIT(ag->attr);
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001283 Py_VISIT(Py_TYPE(ag));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001284 return 0;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001285}
1286
1287static PyObject *
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001288dotted_getattr(PyObject *obj, PyObject *attr)
1289{
Antoine Pitroue9745712010-10-31 15:26:04 +00001290 PyObject *newobj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001291
Antoine Pitroue9745712010-10-31 15:26:04 +00001292 /* attr is either a tuple or instance of str.
1293 Ensured by the setup code of attrgetter_new */
1294 if (PyTuple_CheckExact(attr)) { /* chained getattr */
1295 Py_ssize_t name_idx = 0, name_count;
1296 PyObject *attr_name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001297
Antoine Pitroue9745712010-10-31 15:26:04 +00001298 name_count = PyTuple_GET_SIZE(attr);
1299 Py_INCREF(obj);
1300 for (name_idx = 0; name_idx < name_count; ++name_idx) {
1301 attr_name = PyTuple_GET_ITEM(attr, name_idx);
1302 newobj = PyObject_GetAttr(obj, attr_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001303 Py_DECREF(obj);
Antoine Pitroue9745712010-10-31 15:26:04 +00001304 if (newobj == NULL) {
1305 return NULL;
1306 }
1307 /* here */
1308 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 }
Antoine Pitroue9745712010-10-31 15:26:04 +00001310 } else { /* single getattr */
1311 newobj = PyObject_GetAttr(obj, attr);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001312 if (newobj == NULL)
1313 return NULL;
1314 obj = newobj;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001315 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001317 return obj;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001318}
1319
1320static PyObject *
Raymond Hettinger166958b2003-12-01 13:18:39 +00001321attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
1322{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 PyObject *obj, *result;
1324 Py_ssize_t i, nattrs=ag->nattrs;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001325
Serhiy Storchaka68a001d2017-02-06 10:41:46 +02001326 if (!_PyArg_NoKeywords("attrgetter", kw))
Serhiy Storchakac2a2a752016-04-23 10:51:39 +03001327 return NULL;
Serhiy Storchaka79342662019-01-12 08:25:41 +02001328 if (!_PyArg_CheckPositional("attrgetter", PyTuple_GET_SIZE(args), 1, 1))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 return NULL;
Serhiy Storchaka79342662019-01-12 08:25:41 +02001330 obj = PyTuple_GET_ITEM(args, 0);
Antoine Pitroue9745712010-10-31 15:26:04 +00001331 if (ag->nattrs == 1) /* ag->attr is always a tuple */
1332 return dotted_getattr(obj, PyTuple_GET_ITEM(ag->attr, 0));
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001333
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001334 assert(PyTuple_Check(ag->attr));
1335 assert(PyTuple_GET_SIZE(ag->attr) == nattrs);
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001337 result = PyTuple_New(nattrs);
1338 if (result == NULL)
1339 return NULL;
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 for (i=0 ; i < nattrs ; i++) {
1342 PyObject *attr, *val;
1343 attr = PyTuple_GET_ITEM(ag->attr, i);
1344 val = dotted_getattr(obj, attr);
1345 if (val == NULL) {
1346 Py_DECREF(result);
1347 return NULL;
1348 }
1349 PyTuple_SET_ITEM(result, i, val);
1350 }
1351 return result;
Raymond Hettinger166958b2003-12-01 13:18:39 +00001352}
1353
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001354static PyObject *
1355dotjoinattr(PyObject *attr, PyObject **attrsep)
1356{
1357 if (PyTuple_CheckExact(attr)) {
1358 if (*attrsep == NULL) {
1359 *attrsep = PyUnicode_FromString(".");
1360 if (*attrsep == NULL)
1361 return NULL;
1362 }
1363 return PyUnicode_Join(*attrsep, attr);
1364 } else {
1365 Py_INCREF(attr);
1366 return attr;
1367 }
1368}
1369
1370static PyObject *
1371attrgetter_args(attrgetterobject *ag)
1372{
1373 Py_ssize_t i;
1374 PyObject *attrsep = NULL;
1375 PyObject *attrstrings = PyTuple_New(ag->nattrs);
1376 if (attrstrings == NULL)
1377 return NULL;
1378
1379 for (i = 0; i < ag->nattrs; ++i) {
1380 PyObject *attr = PyTuple_GET_ITEM(ag->attr, i);
1381 PyObject *attrstr = dotjoinattr(attr, &attrsep);
1382 if (attrstr == NULL) {
1383 Py_XDECREF(attrsep);
1384 Py_DECREF(attrstrings);
1385 return NULL;
1386 }
1387 PyTuple_SET_ITEM(attrstrings, i, attrstr);
1388 }
1389 Py_XDECREF(attrsep);
1390 return attrstrings;
1391}
1392
1393static PyObject *
1394attrgetter_repr(attrgetterobject *ag)
1395{
1396 PyObject *repr = NULL;
1397 int status = Py_ReprEnter((PyObject *)ag);
1398 if (status != 0) {
1399 if (status < 0)
1400 return NULL;
1401 return PyUnicode_FromFormat("%s(...)", Py_TYPE(ag)->tp_name);
1402 }
1403
1404 if (ag->nattrs == 1) {
1405 PyObject *attrsep = NULL;
1406 PyObject *attr = dotjoinattr(PyTuple_GET_ITEM(ag->attr, 0), &attrsep);
Serhiy Storchaka548de2b2015-05-21 14:19:20 +03001407 if (attr != NULL) {
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001408 repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(ag)->tp_name, attr);
Serhiy Storchaka548de2b2015-05-21 14:19:20 +03001409 Py_DECREF(attr);
1410 }
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001411 Py_XDECREF(attrsep);
1412 }
1413 else {
1414 PyObject *attrstrings = attrgetter_args(ag);
1415 if (attrstrings != NULL) {
1416 repr = PyUnicode_FromFormat("%s%R",
1417 Py_TYPE(ag)->tp_name, attrstrings);
1418 Py_DECREF(attrstrings);
1419 }
1420 }
1421 Py_ReprLeave((PyObject *)ag);
1422 return repr;
1423}
1424
1425static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301426attrgetter_reduce(attrgetterobject *ag, PyObject *Py_UNUSED(ignored))
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001427{
1428 PyObject *attrstrings = attrgetter_args(ag);
1429 if (attrstrings == NULL)
1430 return NULL;
1431
1432 return Py_BuildValue("ON", Py_TYPE(ag), attrstrings);
1433}
1434
1435static PyMethodDef attrgetter_methods[] = {
1436 {"__reduce__", (PyCFunction)attrgetter_reduce, METH_NOARGS,
1437 reduce_doc},
1438 {NULL}
1439};
1440
Raymond Hettinger166958b2003-12-01 13:18:39 +00001441PyDoc_STRVAR(attrgetter_doc,
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001442"attrgetter(attr, ...) --> attrgetter object\n\
Raymond Hettinger166958b2003-12-01 13:18:39 +00001443\n\
Raymond Hettinger984f9bb2005-03-09 16:38:48 +00001444Return a callable object that fetches the given attribute(s) from its operand.\n\
Ezio Melottibabc8222013-05-08 10:53:11 +03001445After f = attrgetter('name'), the call f(r) returns r.name.\n\
1446After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\
1447After h = attrgetter('name.first', 'name.last'), the call h(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001448(r.name.first, r.name.last).");
Raymond Hettinger166958b2003-12-01 13:18:39 +00001449
Dong-hee Na31967fd2020-08-26 17:22:27 +00001450static PyType_Slot attrgetter_type_slots[] = {
1451 {Py_tp_doc, (void *)attrgetter_doc},
1452 {Py_tp_dealloc, attrgetter_dealloc},
1453 {Py_tp_call, attrgetter_call},
1454 {Py_tp_traverse, attrgetter_traverse},
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001455 {Py_tp_clear, attrgetter_clear},
Dong-hee Na31967fd2020-08-26 17:22:27 +00001456 {Py_tp_methods, attrgetter_methods},
1457 {Py_tp_new, attrgetter_new},
1458 {Py_tp_getattro, PyObject_GenericGetAttr},
1459 {Py_tp_repr, attrgetter_repr},
1460 {0, 0}
1461};
1462
1463static PyType_Spec attrgetter_type_spec = {
1464 .name = "operator.attrgetter",
1465 .basicsize = sizeof(attrgetterobject),
1466 .itemsize = 0,
1467 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1468 .slots = attrgetter_type_slots,
Raymond Hettinger166958b2003-12-01 13:18:39 +00001469};
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001470
1471
1472/* methodcaller object **********************************************************/
1473
1474typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 PyObject_HEAD
1476 PyObject *name;
1477 PyObject *args;
1478 PyObject *kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001479} methodcallerobject;
1480
Serhiy Storchakab813a0e2017-01-19 17:44:13 +02001481/* AC 3.5: variable number of arguments, not currently support by AC */
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001482static PyObject *
1483methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1484{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001485 methodcallerobject *mc;
Benjamin Peterson1f0e7c92016-08-16 23:35:35 -07001486 PyObject *name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001487
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001488 if (PyTuple_GET_SIZE(args) < 1) {
1489 PyErr_SetString(PyExc_TypeError, "methodcaller needs at least "
1490 "one argument, the method name");
1491 return NULL;
1492 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001493
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001494 name = PyTuple_GET_ITEM(args, 0);
1495 if (!PyUnicode_Check(name)) {
1496 PyErr_SetString(PyExc_TypeError,
1497 "method name must be a string");
1498 return NULL;
1499 }
1500
Dong-hee Na31967fd2020-08-26 17:22:27 +00001501 _operator_state *state = PyType_GetModuleState(type);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001502 /* create methodcallerobject structure */
Dong-hee Na31967fd2020-08-26 17:22:27 +00001503 mc = PyObject_GC_New(methodcallerobject, (PyTypeObject *)state->methodcaller_type);
1504 if (mc == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505 return NULL;
Dong-hee Na31967fd2020-08-26 17:22:27 +00001506 }
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001507
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001508 name = PyTuple_GET_ITEM(args, 0);
1509 Py_INCREF(name);
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001510 PyUnicode_InternInPlace(&name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001511 mc->name = name;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001513 Py_XINCREF(kwds);
1514 mc->kwds = kwds;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001515
Benjamin Peterson1f0e7c92016-08-16 23:35:35 -07001516 mc->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
1517 if (mc->args == NULL) {
1518 Py_DECREF(mc);
1519 return NULL;
1520 }
1521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001522 PyObject_GC_Track(mc);
1523 return (PyObject *)mc;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001524}
1525
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001526static int
1527methodcaller_clear(methodcallerobject *mc)
1528{
1529 Py_CLEAR(mc->name);
1530 Py_CLEAR(mc->args);
1531 Py_CLEAR(mc->kwds);
1532 return 0;
1533}
1534
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001535static void
1536methodcaller_dealloc(methodcallerobject *mc)
1537{
Dong-hee Na31967fd2020-08-26 17:22:27 +00001538 PyTypeObject *tp = Py_TYPE(mc);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 PyObject_GC_UnTrack(mc);
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001540 (void)methodcaller_clear(mc);
Dong-hee Na31967fd2020-08-26 17:22:27 +00001541 tp->tp_free(mc);
1542 Py_DECREF(tp);
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001543}
1544
1545static int
1546methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
1547{
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001548 Py_VISIT(mc->name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 Py_VISIT(mc->args);
1550 Py_VISIT(mc->kwds);
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001551 Py_VISIT(Py_TYPE(mc));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 return 0;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001553}
1554
1555static PyObject *
1556methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
1557{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001558 PyObject *method, *obj, *result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001559
Serhiy Storchaka68a001d2017-02-06 10:41:46 +02001560 if (!_PyArg_NoKeywords("methodcaller", kw))
Serhiy Storchakac2a2a752016-04-23 10:51:39 +03001561 return NULL;
Serhiy Storchaka79342662019-01-12 08:25:41 +02001562 if (!_PyArg_CheckPositional("methodcaller", PyTuple_GET_SIZE(args), 1, 1))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 return NULL;
Serhiy Storchaka79342662019-01-12 08:25:41 +02001564 obj = PyTuple_GET_ITEM(args, 0);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 method = PyObject_GetAttr(obj, mc->name);
1566 if (method == NULL)
1567 return NULL;
1568 result = PyObject_Call(method, mc->args, mc->kwds);
1569 Py_DECREF(method);
1570 return result;
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001571}
1572
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001573static PyObject *
1574methodcaller_repr(methodcallerobject *mc)
1575{
1576 PyObject *argreprs, *repr = NULL, *sep, *joinedargreprs;
1577 Py_ssize_t numtotalargs, numposargs, numkwdargs, i;
1578 int status = Py_ReprEnter((PyObject *)mc);
1579 if (status != 0) {
1580 if (status < 0)
1581 return NULL;
1582 return PyUnicode_FromFormat("%s(...)", Py_TYPE(mc)->tp_name);
1583 }
1584
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001585 numkwdargs = mc->kwds != NULL ? PyDict_GET_SIZE(mc->kwds) : 0;
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001586 numposargs = PyTuple_GET_SIZE(mc->args);
1587 numtotalargs = numposargs + numkwdargs;
1588
1589 if (numtotalargs == 0) {
1590 repr = PyUnicode_FromFormat("%s(%R)", Py_TYPE(mc)->tp_name, mc->name);
1591 Py_ReprLeave((PyObject *)mc);
1592 return repr;
1593 }
1594
1595 argreprs = PyTuple_New(numtotalargs);
1596 if (argreprs == NULL) {
1597 Py_ReprLeave((PyObject *)mc);
1598 return NULL;
1599 }
1600
1601 for (i = 0; i < numposargs; ++i) {
1602 PyObject *onerepr = PyObject_Repr(PyTuple_GET_ITEM(mc->args, i));
1603 if (onerepr == NULL)
1604 goto done;
1605 PyTuple_SET_ITEM(argreprs, i, onerepr);
1606 }
1607
1608 if (numkwdargs != 0) {
1609 PyObject *key, *value;
1610 Py_ssize_t pos = 0;
1611 while (PyDict_Next(mc->kwds, &pos, &key, &value)) {
1612 PyObject *onerepr = PyUnicode_FromFormat("%U=%R", key, value);
1613 if (onerepr == NULL)
1614 goto done;
1615 if (i >= numtotalargs) {
1616 i = -1;
Zackery Spytz5b83ef72018-11-23 12:26:46 -07001617 Py_DECREF(onerepr);
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001618 break;
1619 }
1620 PyTuple_SET_ITEM(argreprs, i, onerepr);
1621 ++i;
1622 }
1623 if (i != numtotalargs) {
1624 PyErr_SetString(PyExc_RuntimeError,
1625 "keywords dict changed size during iteration");
1626 goto done;
1627 }
1628 }
1629
1630 sep = PyUnicode_FromString(", ");
1631 if (sep == NULL)
1632 goto done;
1633
1634 joinedargreprs = PyUnicode_Join(sep, argreprs);
1635 Py_DECREF(sep);
1636 if (joinedargreprs == NULL)
1637 goto done;
1638
1639 repr = PyUnicode_FromFormat("%s(%R, %U)", Py_TYPE(mc)->tp_name,
1640 mc->name, joinedargreprs);
1641 Py_DECREF(joinedargreprs);
1642
1643done:
1644 Py_DECREF(argreprs);
1645 Py_ReprLeave((PyObject *)mc);
1646 return repr;
1647}
1648
1649static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301650methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001651{
1652 PyObject *newargs;
Serhiy Storchaka5ab81d72016-12-16 16:18:57 +02001653 if (!mc->kwds || PyDict_GET_SIZE(mc->kwds) == 0) {
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001654 Py_ssize_t i;
1655 Py_ssize_t callargcount = PyTuple_GET_SIZE(mc->args);
1656 newargs = PyTuple_New(1 + callargcount);
1657 if (newargs == NULL)
1658 return NULL;
1659 Py_INCREF(mc->name);
1660 PyTuple_SET_ITEM(newargs, 0, mc->name);
1661 for (i = 0; i < callargcount; ++i) {
1662 PyObject *arg = PyTuple_GET_ITEM(mc->args, i);
1663 Py_INCREF(arg);
1664 PyTuple_SET_ITEM(newargs, i + 1, arg);
1665 }
1666 return Py_BuildValue("ON", Py_TYPE(mc), newargs);
1667 }
1668 else {
1669 PyObject *functools;
1670 PyObject *partial;
1671 PyObject *constructor;
Victor Stinner7e7823a2016-08-23 00:23:23 +02001672 PyObject *newargs[2];
1673
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001674 _Py_IDENTIFIER(partial);
1675 functools = PyImport_ImportModule("functools");
1676 if (!functools)
1677 return NULL;
1678 partial = _PyObject_GetAttrId(functools, &PyId_partial);
1679 Py_DECREF(functools);
1680 if (!partial)
1681 return NULL;
Victor Stinner7e7823a2016-08-23 00:23:23 +02001682
1683 newargs[0] = (PyObject *)Py_TYPE(mc);
1684 newargs[1] = mc->name;
Petr Viktorinffd97532020-02-11 17:46:57 +01001685 constructor = PyObject_VectorcallDict(partial, newargs, 2, mc->kwds);
Victor Stinner7e7823a2016-08-23 00:23:23 +02001686
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +03001687 Py_DECREF(partial);
1688 return Py_BuildValue("NO", constructor, mc->args);
1689 }
1690}
1691
1692static PyMethodDef methodcaller_methods[] = {
1693 {"__reduce__", (PyCFunction)methodcaller_reduce, METH_NOARGS,
1694 reduce_doc},
1695 {NULL}
1696};
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001697PyDoc_STRVAR(methodcaller_doc,
1698"methodcaller(name, ...) --> methodcaller object\n\
1699\n\
1700Return a callable object that calls the given method on its operand.\n\
Antoine Pitroua85017f2013-04-20 19:21:44 +02001701After f = methodcaller('name'), the call f(r) returns r.name().\n\
1702After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001703r.name('date', foo=1).");
1704
Dong-hee Na31967fd2020-08-26 17:22:27 +00001705static PyType_Slot methodcaller_type_slots[] = {
1706 {Py_tp_doc, (void *)methodcaller_doc},
1707 {Py_tp_dealloc, methodcaller_dealloc},
1708 {Py_tp_call, methodcaller_call},
1709 {Py_tp_traverse, methodcaller_traverse},
Miss Islington (bot)d1c73292021-05-27 14:49:43 -07001710 {Py_tp_clear, methodcaller_clear},
Dong-hee Na31967fd2020-08-26 17:22:27 +00001711 {Py_tp_methods, methodcaller_methods},
1712 {Py_tp_new, methodcaller_new},
1713 {Py_tp_getattro, PyObject_GenericGetAttr},
1714 {Py_tp_repr, methodcaller_repr},
1715 {0, 0}
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001716};
1717
Dong-hee Na31967fd2020-08-26 17:22:27 +00001718static PyType_Spec methodcaller_type_spec = {
1719 .name = "operator.methodcaller",
1720 .basicsize = sizeof(methodcallerobject),
1721 .itemsize = 0,
1722 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
1723 .slots = methodcaller_type_slots,
1724};
Christian Heimesd3eb5a152008-02-24 00:38:49 +00001725
Paulo Henrique Silvaf3d5ac42020-03-24 23:18:47 -03001726static int
1727operator_exec(PyObject *module)
1728{
Dong-hee Na31967fd2020-08-26 17:22:27 +00001729 _operator_state *state = get_operator_state(module);
1730 state->attrgetter_type = PyType_FromModuleAndSpec(module, &attrgetter_type_spec, NULL);
1731 if (state->attrgetter_type == NULL) {
1732 return -1;
1733 }
1734 if (PyModule_AddType(module, (PyTypeObject *)state->attrgetter_type) < 0) {
1735 return -1;
1736 }
Paulo Henrique Silvaf3d5ac42020-03-24 23:18:47 -03001737
Dong-hee Na31967fd2020-08-26 17:22:27 +00001738 state->itemgetter_type = PyType_FromModuleAndSpec(module, &itemgetter_type_spec, NULL);
1739 if (state->itemgetter_type == NULL) {
1740 return -1;
1741 }
1742 if (PyModule_AddType(module, (PyTypeObject *)state->itemgetter_type) < 0) {
1743 return -1;
1744 }
1745
1746 state->methodcaller_type = PyType_FromModuleAndSpec(module, &methodcaller_type_spec, NULL);
1747 if (state->methodcaller_type == NULL) {
1748 return -1;
1749 }
1750 if (PyModule_AddType(module, (PyTypeObject *)state->methodcaller_type) < 0) {
1751 return -1;
Paulo Henrique Silvaf3d5ac42020-03-24 23:18:47 -03001752 }
1753
1754 return 0;
1755}
1756
1757
1758static struct PyModuleDef_Slot operator_slots[] = {
1759 {Py_mod_exec, operator_exec},
1760 {0, NULL}
1761};
Martin v. Löwis1a214512008-06-11 05:26:20 +00001762
Dong-hee Na31967fd2020-08-26 17:22:27 +00001763static int
1764operator_traverse(PyObject *module, visitproc visit, void *arg)
1765{
1766 _operator_state *state = get_operator_state(module);
1767 Py_VISIT(state->attrgetter_type);
1768 Py_VISIT(state->itemgetter_type);
1769 Py_VISIT(state->methodcaller_type);
1770 return 0;
1771}
1772
1773static int
1774operator_clear(PyObject *module)
1775{
1776 _operator_state *state = get_operator_state(module);
1777 Py_CLEAR(state->attrgetter_type);
1778 Py_CLEAR(state->itemgetter_type);
1779 Py_CLEAR(state->methodcaller_type);
1780 return 0;
1781}
1782
1783static void
1784operator_free(void *module)
1785{
1786 operator_clear((PyObject *)module);
1787}
Martin v. Löwis1a214512008-06-11 05:26:20 +00001788
1789static struct PyModuleDef operatormodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001790 PyModuleDef_HEAD_INIT,
Dong-hee Na31967fd2020-08-26 17:22:27 +00001791 .m_name = "_operator",
1792 .m_doc = operator_doc,
1793 .m_size = sizeof(_operator_state),
1794 .m_methods = operator_methods,
1795 .m_slots = operator_slots,
1796 .m_traverse = operator_traverse,
1797 .m_clear = operator_clear,
1798 .m_free = operator_free,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001799};
Guido van Rossum037b9401996-07-30 16:55:54 +00001800
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001801PyMODINIT_FUNC
Antoine Pitroua85017f2013-04-20 19:21:44 +02001802PyInit__operator(void)
Guido van Rossum037b9401996-07-30 16:55:54 +00001803{
Paulo Henrique Silvaf3d5ac42020-03-24 23:18:47 -03001804 return PyModuleDef_Init(&operatormodule);
Guido van Rossum037b9401996-07-30 16:55:54 +00001805}