5
# The patch in #561 changes code generation for most special methods
6
# to remove the Cython-generated wrapper and let PyType_Ready()
7
# generate its own wrapper. (This wrapper would be used, for instance,
8
# when using the special method as a bound method.)
10
# To test this, we go through and verify that each affected special
11
# method works as a bound method.
13
# Special methods that are treated the same under Python 2 and 3 are
14
# tested here; see also special_methods_T561_py2.pyx and
15
# special_methods_T561_py3.pyx for tests of the differences between
18
# Regarding ticket 3, we should additionally test that unbound method
19
# calls to these special methods (e.g. ExtType.__init__()) do not use
20
# a runtime lookup indirection.
22
# Additional tests added for 2 and 3 argument pow and ipow
26
from cpython.number cimport PyNumber_InPlacePower
29
>>> # If you define either setitem or delitem, you get wrapper objects
30
>>> # for both methods. (This behavior is unchanged by #561.)
31
>>> si_setitem = SetItem().__setitem__
32
>>> si_setitem('foo', 'bar')
33
SetItem setitem 'foo' 'bar'
34
>>> si_delitem = SetItem().__delitem__
36
Traceback (most recent call last):
38
NotImplementedError: Subscript deletion not supported by special_methods_T561.SetItem
39
>>> di_setitem = DelItem().__setitem__
40
>>> di_setitem('foo', 'bar')
41
Traceback (most recent call last):
43
NotImplementedError: Subscript assignment not supported by special_methods_T561.DelItem
44
>>> di_delitem = DelItem().__delitem__
47
>>> sdi_setitem = SetDelItem().__setitem__
48
>>> sdi_setitem('foo', 'bar')
49
SetDelItem setitem 'foo' 'bar'
50
>>> sdi_delitem = SetDelItem().__delitem__
51
>>> sdi_delitem('foo')
52
SetDelItem delitem 'foo'
53
>>> g01 = object.__getattribute__(GetAttr(), '__getattribute__')
55
GetAttr getattr 'attr'
56
>>> try: object.__getattribute__(GetAttribute(), '__getattr__')
57
... except AttributeError as err:
58
... assert '__getattr__' in str(err), err
59
... else: print("NOT RAISED!")
60
>>> g11 = object.__getattribute__(GetAttribute(), '__getattribute__')
62
GetAttribute getattribute 'attr'
63
>>> # If you define either set or delete, you get wrapper objects
64
>>> # for both methods. (This behavior is unchanged by #561.)
65
>>> s_set = Set().__set__
66
>>> s_set('instance', 'val')
67
Set set 'instance' 'val'
68
>>> s_delete = Set().__delete__
69
>>> s_delete('instance')
70
Traceback (most recent call last):
72
NotImplementedError: __delete__
73
>>> d_set = Delete().__set__
74
>>> d_set('instance', 'val')
75
Traceback (most recent call last):
77
NotImplementedError: __set__
78
>>> d_delete = Delete().__delete__
79
>>> d_delete('instance')
80
Delete delete 'instance'
81
>>> sd_set = SetDelete().__set__
82
>>> sd_set('instance', 'val')
83
SetDelete set 'instance' 'val'
84
>>> sd_delete = SetDelete().__delete__
85
>>> sd_delete('instance')
86
SetDelete delete 'instance'
87
>>> # If you define __long__, you get a wrapper object for __int__.
88
>>> # (This behavior is unchanged by #561.)
89
>>> Li = Long().__int__
92
>>> vs0 = VerySpecial(0)
94
>>> vs0_index = vs0.__index__
97
>>> set_name = SetName()
98
>>> assert "SetName 'SetName' 'attr'" == set_name.attr, set_name.attr
102
# type specs require a bug fix in Py3.8+ for some of these tests.
103
const int CYTHON_USE_TYPE_SPECS
105
if not CYTHON_USE_TYPE_SPECS or sys.version_info >= (3,8):
107
>>> # If you define either setattr or delattr, you get wrapper objects
108
>>> # for both methods. (This behavior is unchanged by #561.)
109
>>> sa_setattr = SetAttr().__setattr__
110
>>> sa_setattr('foo', 'bar')
111
SetAttr setattr 'foo' 'bar'
112
>>> sa_delattr = SetAttr().__delattr__
113
>>> sa_delattr('foo') # doctest: +ELLIPSIS
114
Traceback (most recent call last):
116
AttributeError: 'special_methods_T561.SetAttr' object has no attribute 'foo'...
117
>>> da_setattr = DelAttr().__setattr__
118
>>> da_setattr('foo', 'bar') # doctest: +ELLIPSIS
119
Traceback (most recent call last):
121
AttributeError: 'special_methods_T561.DelAttr' object has no attribute 'foo'...
122
>>> da_delattr = DelAttr().__delattr__
123
>>> da_delattr('foo')
124
DelAttr delattr 'foo'
125
>>> sda_setattr = SetDelAttr().__setattr__
126
>>> sda_setattr('foo', 'bar')
127
SetDelAttr setattr 'foo' 'bar'
128
>>> sda_delattr = SetDelAttr().__delattr__
129
>>> sda_delattr('foo')
130
SetDelAttr delattr 'foo'
134
cdef class VerySpecial:
136
>>> vs0 = VerySpecial(0)
138
>>> vs1 = VerySpecial(1)
141
>>> vs0_add = vs0.__add__
144
>>> vs0_sub = vs0.__sub__
147
>>> vs0_mul = vs0.__mul__
150
>>> vs0_mod = vs0.__mod__
153
>>> vs0_divmod = vs0.__divmod__
156
>>> vs0_pow = vs0.__pow__
158
VS __pow__ pow(0, 1, None)
160
VS __pow__ pow(0, 1, 13)
161
>>> vs0_neg = vs0.__neg__
164
>>> vs0_pos = vs0.__pos__
167
>>> vs0_abs = vs0.__abs__
170
>>> vs0_invert = vs0.__invert__
173
>>> vs0_lshift = vs0.__lshift__
176
>>> vs0_rshift = vs0.__rshift__
179
>>> vs0_and = vs0.__and__
182
>>> vs0_xor = vs0.__xor__
185
>>> vs0_or = vs0.__or__
188
>>> vs0_int = vs0.__int__
191
>>> vs0_float = vs0.__float__
194
>>> vs0_iadd = vs0.__iadd__
197
>>> vs0_isub = vs0.__isub__
200
>>> vs0_imul = vs0.__imul__
203
>>> vs0_imod = vs0.__imod__
206
>>> vs0_ipow = vs0.__ipow__
209
>>> vs0_ilshift = vs0.__ilshift__
211
VS __ilshift__ 0 <<= 1
212
>>> vs0_irshift = vs0.__irshift__
214
VS __irshift__ 0 >>= 1
215
>>> vs0_iand = vs0.__iand__
218
>>> vs0_ixor = vs0.__ixor__
221
>>> vs0_ior = vs0.__ior__
224
>>> vs0_floordiv = vs0.__floordiv__
225
>>> vs0_floordiv(vs1)
226
VS __floordiv__ 0 / 1
227
>>> vs0_truediv = vs0.__truediv__
230
>>> vs0_ifloordiv = vs0.__ifloordiv__
231
>>> vs0_ifloordiv(vs1)
232
VS __ifloordiv__ 0 /= 1
233
>>> vs0_itruediv = vs0.__itruediv__
234
>>> vs0_itruediv(vs1)
235
VS __itruediv__ 0 /= 1
237
# If you define an arithmetic method, you get wrapper objects for
238
# the reversed version as well. (This behavior is unchanged by #561.)
239
>>> vs0_radd = vs0.__radd__
242
>>> vs0_rsub = vs0.__rsub__
245
>>> vs0_rmul = vs0.__rmul__
248
>>> vs0_rmod = vs0.__rmod__
251
>>> vs0_rdivmod = vs0.__rdivmod__
254
>>> vs0_rpow = vs0.__rpow__
256
VS __pow__ pow(1, 0, None)
257
>>> vs0_rlshift = vs0.__rlshift__
260
>>> vs0_rrshift = vs0.__rrshift__
263
>>> vs0_rand = vs0.__rand__
266
>>> vs0_rxor = vs0.__rxor__
269
>>> vs0_ror = vs0.__ror__
272
>>> vs0_rfloordiv = vs0.__rfloordiv__
273
>>> vs0_rfloordiv(vs1)
274
VS __floordiv__ 1 / 0
275
>>> vs0_rtruediv = vs0.__rtruediv__
276
>>> vs0_rtruediv(vs1)
278
>>> vs0_getitem = vs0.__getitem__
279
>>> vs0_getitem('foo')
280
VS __getitem__ 0['foo']
281
>>> vs0_contains = vs0.__contains__
282
>>> vs0_contains(vs1)
285
>>> vs0_len = vs0.__len__
289
>>> vs0_repr = vs0.__repr__
292
>>> vs0_hash = vs0.__hash__
296
>>> vs0_call = vs0.__call__
299
>>> vs0_str = vs0.__str__
303
# If you define __richcmp__, you get all of __lt__, __le__,
304
# __eq__, __ne__, __gt__, __ge__ (this behavior is unchanged by #561).
305
# (you don't get a __richcmp__ method, because it doesn't have a
307
>>> vs0_lt = vs0.__lt__
309
VS richcmp 0 1 (kind=0)
310
>>> vs0_le = vs0.__le__
312
VS richcmp 0 1 (kind=1)
313
>>> vs0_eq = vs0.__eq__
315
VS richcmp 0 1 (kind=2)
316
>>> vs0_ne = vs0.__ne__
318
VS richcmp 0 1 (kind=3)
319
>>> vs0_gt = vs0.__gt__
321
VS richcmp 0 1 (kind=4)
322
>>> vs0_ge = vs0.__ge__
324
VS richcmp 0 1 (kind=5)
325
>>> vs0_iter = vs0.__iter__
328
>>> vs0_next = vs0.__next__
332
>>> vs0_get = vs0.__get__
333
>>> vs0_get('instance', 'owner')
334
VS __get__ 0 'instance' 'owner'
335
>>> vs0_init = vs0.__init__
339
cdef readonly int value
341
def __init__(self, v):
343
print "VS __init__ %d" % self.value
345
def __add__(self, other):
346
print "VS __add__ %d %d" % (self.value, other.value)
348
def __sub__(self, other):
349
print "VS __sub__ %d %d" % (self.value, other.value)
351
def __mul__(self, other):
352
print "VS __mul__ %d %d" % (self.value, other.value)
354
def __div__(self, other):
355
print "VS __div__ %d %d" % (self.value, other.value)
357
def __mod__(self, other):
358
print "VS __mod__ %d %d" % (self.value, other.value)
360
def __divmod__(self, other):
361
print "VS __divmod__ %d %d" % (self.value, other.value)
363
def __pow__(self, other, mod):
364
print "VS __pow__ pow(%d, %d, %r)" % (self.value, other.value, mod)
366
def __lshift__(self, other):
367
print "VS __lshift__ %d << %d" % (self.value, other.value)
369
def __rshift__(self, other):
370
print "VS __rshift__ %d >> %d" % (self.value, other.value)
372
def __and__(self, other):
373
print "VS __and__ %d & %d" % (self.value, other.value)
375
def __xor__(self, other):
376
print "VS __xor__ %d ^ %d" % (self.value, other.value)
378
def __or__(self, other):
379
print "VS __or__ %d | %d" % (self.value, other.value)
381
def __floordiv__(self, other):
382
print "VS __floordiv__ %d / %d" % (self.value, other.value)
384
def __truediv__(self, other):
385
print "VS __truediv__ %d / %d" % (self.value, other.value)
388
print "VS __neg__ %d" % self.value
391
print "VS __pos__ %d" % self.value
394
print "VS __abs__ %d" % self.value
396
def __nonzero__(self):
397
print "VS __nonzero__ %d" % self.value
399
def __invert__(self):
400
print "VS __invert__ %d" % self.value
403
print "VS __int__ %d" % self.value
406
print "VS __long__ %d" % self.value
409
print "VS __float__ %d" % self.value
412
print "VS __oct__ %d" % self.value
415
print "VS __hex__ %d" % self.value
417
def __iadd__(self, other):
418
print "VS __iadd__ %d += %d" % (self.value, other.value)
420
def __isub__(self, other):
421
print "VS __isub__ %d -= %d" % (self.value, other.value)
423
def __imul__(self, other):
424
print "VS __imul__ %d *= %d" % (self.value, other.value)
426
def __idiv__(self, other):
427
print "VS __idiv__ %d /= %d" % (self.value, other.value)
429
def __imod__(self, other):
430
print "VS __imod__ %d %%= %d" % (self.value, other.value)
432
def __ipow__(self, other):
433
# We must declare mod as an argument, but we must not touch it
434
# or we'll get a segfault. See #562
435
print "VS __ipow__ %d %d" % (self.value, other.value)
437
def __ilshift__(self, other):
438
print "VS __ilshift__ %d <<= %d" % (self.value, other.value)
440
def __irshift__(self, other):
441
print "VS __irshift__ %d >>= %d" % (self.value, other.value)
443
def __iand__(self, other):
444
print "VS __iand__ %d &= %d" % (self.value, other.value)
446
def __ixor__(self, other):
447
print "VS __ixor__ %d ^= %d" % (self.value, other.value)
449
def __ior__(self, other):
450
print "VS __ior__ %d |= %d" % (self.value, other.value)
452
def __ifloordiv__(self, other):
453
print "VS __ifloordiv__ %d /= %d" % (self.value, other.value)
455
def __itruediv__(self, other):
456
print "VS __itruediv__ %d /= %d" % (self.value, other.value)
459
print "VS __index__ %d" % self.value
461
def __getitem__(self, index):
462
print "VS __getitem__ %d[%r]" % (self.value, index)
464
def __contains__(self, other):
465
print "VS __contains__ %d %d" % (self.value, other.value)
468
print "VS __len__ %d" % (self.value)
470
def __cmp__(self, other):
471
print "VS __cmp__ %d %d" % (self.value, other.value)
474
print "VS __repr__ %d" % self.value
477
print "VS __hash__ %d" % self.value
478
return self.value + 1000
480
def __call__(self, other):
481
print "VS __call__ %d(%d)" % (self.value, other.value)
484
print "VS __str__ %d" % self.value
486
def __richcmp__(self, other, kind):
487
print "VS richcmp %d %d (kind=%r)" % (self.value, other.value, kind)
490
print "VS __iter__ %d" % self.value
493
print "VS next/__next__ %d" % self.value
495
def __get__(self, inst, own):
496
print "VS __get__ %d %r %r" % (self.value, inst, own)
499
def __setitem__(self, index, value):
500
print "SetItem setitem %r %r" % (index, value)
503
def __delitem__(self, index):
504
print "DelItem delitem %r" % index
506
cdef class SetDelItem:
507
def __setitem__(self, index, value):
508
print "SetDelItem setitem %r %r" % (index, value)
510
def __delitem__(self, index):
511
print "SetDelItem delitem %r" % index
514
def __getattr__(self, attr):
515
print "GetAttr getattr %r" % attr
517
cdef class GetAttribute:
518
def __getattribute__(self, attr):
519
print "GetAttribute getattribute %r" % attr
522
def __setattr__(self, attr, val):
523
print "SetAttr setattr %r %r" % (attr, val)
526
def __delattr__(self, attr):
527
print "DelAttr delattr %r" % attr
529
cdef class SetDelAttr:
530
def __setattr__(self, attr, val):
531
print "SetDelAttr setattr %r %r" % (attr, val)
533
def __delattr__(self, attr):
534
print "SetDelAttr delattr %r" % attr
537
def __set__(self, inst, val):
538
print "Set set %r %r" % (inst, val)
541
def __delete__(self, inst):
542
print "Delete delete %r" % inst
545
def __set__(self, inst, val):
546
print "SetDelete set %r %r" % (inst, val)
548
def __delete__(self, inst):
549
print "SetDelete delete %r" % inst
553
print "Long __long__"
560
def __set_name__(self, owner, name):
561
self.set_name = "SetName %r %r" % (owner.__name__, name)
563
def __get__(self, inst, own):
569
cdef class GetAttrGetItemRedirect:
571
>>> o = GetAttrGetItemRedirect()
573
>>> assert o.item == o['item']
574
>>> source, item_value = o.item
575
>>> assert source == 'item', source
577
>>> assert o['attr'] == o.attr
578
>>> source, attr_value = o['attr']
579
>>> assert source == 'attr', source
581
>>> assert item_value is attr_value, repr((item_value, attr_value))
587
def __getattr__(self, name):
590
return ('attr', self.obj)
592
def __getitem__(self, key):
594
return getattr(self, key)
595
return ('item', self.obj)
598
# test unbound method usage in subtypes
600
cdef class VerySpecialSubType(VerySpecial):
602
>>> vs0 = VerySpecialSubType(0)
604
>>> vs1 = VerySpecialSubType(1)
607
>>> vs0_add = vs0.__add__
610
>>> vs0_sub = vs0.__sub__
613
>>> vs0_mul = vs0.__mul__
616
>>> vs0_mod = vs0.__mod__
619
>>> vs0_divmod = vs0.__divmod__
622
>>> vs0_pow = vs0.__pow__
624
VS __pow__ pow(0, 1, None)
626
VS __pow__ pow(0, 1, 13)
627
>>> vs0_neg = vs0.__neg__
630
>>> vs0_pos = vs0.__pos__
633
>>> vs0_abs = vs0.__abs__
636
>>> vs0_invert = vs0.__invert__
639
>>> vs0_lshift = vs0.__lshift__
642
>>> vs0_rshift = vs0.__rshift__
645
>>> vs0_and = vs0.__and__
648
>>> vs0_xor = vs0.__xor__
651
>>> vs0_or = vs0.__or__
654
>>> vs0_int = vs0.__int__
657
>>> vs0_float = vs0.__float__
660
>>> vs0_iadd = vs0.__iadd__
663
>>> vs0_isub = vs0.__isub__
666
>>> vs0_imul = vs0.__imul__
669
>>> vs0_imod = vs0.__imod__
672
>>> vs0_ipow = vs0.__ipow__
675
>>> vs0_ilshift = vs0.__ilshift__
677
VS __ilshift__ 0 <<= 1
678
>>> vs0_irshift = vs0.__irshift__
680
VS __irshift__ 0 >>= 1
681
>>> vs0_iand = vs0.__iand__
684
>>> vs0_ixor = vs0.__ixor__
687
>>> vs0_ior = vs0.__ior__
690
>>> vs0_floordiv = vs0.__floordiv__
691
>>> vs0_floordiv(vs1)
692
VS __floordiv__ 0 / 1
693
>>> vs0_truediv = vs0.__truediv__
696
>>> vs0_ifloordiv = vs0.__ifloordiv__
697
>>> vs0_ifloordiv(vs1)
698
VS __ifloordiv__ 0 /= 1
699
>>> vs0_itruediv = vs0.__itruediv__
700
>>> vs0_itruediv(vs1)
701
VS __itruediv__ 0 /= 1
703
# If you define an arithmetic method, you get wrapper objects for
704
# the reversed version as well. (This behavior is unchanged by #561.)
705
>>> vs0_radd = vs0.__radd__
708
>>> vs0_rsub = vs0.__rsub__
711
>>> vs0_rmul = vs0.__rmul__
714
>>> vs0_rmod = vs0.__rmod__
717
>>> vs0_rdivmod = vs0.__rdivmod__
720
>>> vs0_rpow = vs0.__rpow__
722
VS __pow__ pow(1, 0, None)
723
>>> vs0_rlshift = vs0.__rlshift__
726
>>> vs0_rrshift = vs0.__rrshift__
729
>>> vs0_rand = vs0.__rand__
732
>>> vs0_rxor = vs0.__rxor__
735
>>> vs0_ror = vs0.__ror__
738
>>> vs0_rfloordiv = vs0.__rfloordiv__
739
>>> vs0_rfloordiv(vs1)
740
VS __floordiv__ 1 / 0
741
>>> vs0_rtruediv = vs0.__rtruediv__
742
>>> vs0_rtruediv(vs1)
744
>>> vs0_getitem = vs0.__getitem__
745
>>> vs0_getitem('foo')
746
VS __getitem__ 0['foo']
747
>>> vs0_contains = vs0.__contains__
748
>>> vs0_contains(vs1)
751
>>> vs0_len = vs0.__len__
755
>>> vs0_repr = vs0.__repr__
758
>>> vs0_hash = vs0.__hash__
762
>>> vs0_call = vs0.__call__
765
>>> vs0_str = vs0.__str__
768
>>> vs0_lt = vs0.__lt__
770
VS richcmp 0 1 (kind=0)
771
>>> vs0_le = vs0.__le__
773
VS richcmp 0 1 (kind=1)
774
>>> vs0_eq = vs0.__eq__
776
VS richcmp 0 1 (kind=2)
777
>>> vs0_ne = vs0.__ne__
779
VS richcmp 0 1 (kind=3)
780
>>> vs0_gt = vs0.__gt__
782
VS richcmp 0 1 (kind=4)
783
>>> vs0_ge = vs0.__ge__
785
VS richcmp 0 1 (kind=5)
786
>>> vs0_iter = vs0.__iter__
789
>>> vs0_next = vs0.__next__
792
>>> vs0_get = vs0.__get__
793
>>> vs0_get('instance', 'owner')
794
VS __get__ 0 'instance' 'owner'
795
>>> vs0_init = vs0.__init__
799
def __init__(self, v):
800
VerySpecial.__init__(self, v)
802
def __add__(self, other):
803
return VerySpecial.__add__(self, other)
805
def __sub__(self, other):
806
return VerySpecial.__sub__(self, other)
808
def __mul__(self, other):
809
return VerySpecial.__mul__(self, other)
811
def __div__(self, other):
812
return VerySpecial.__div__(self, other)
814
def __mod__(self, other):
815
return VerySpecial.__mod__(self, other)
817
def __divmod__(self, other):
818
return VerySpecial.__divmod__(self, other)
820
def __pow__(self, other, mod):
821
return VerySpecial.__pow__(self, other, mod)
823
def __lshift__(self, other):
824
return VerySpecial.__lshift__(self, other)
826
def __rshift__(self, other):
827
return VerySpecial.__rshift__(self, other)
829
def __and__(self, other):
830
return VerySpecial.__and__(self, other)
832
def __xor__(self, other):
833
return VerySpecial.__xor__(self, other)
835
def __or__(self, other):
836
return VerySpecial.__or__(self, other)
838
def __floordiv__(self, other):
839
return VerySpecial.__floordiv__(self, other)
841
def __truediv__(self, other):
842
return VerySpecial.__truediv__(self, other)
845
return VerySpecial.__neg__(self)
848
return VerySpecial.__pos__(self)
851
return VerySpecial.__abs__(self)
853
def __nonzero__(self):
854
return VerySpecial.__nonzero__(self)
856
def __invert__(self):
857
return VerySpecial.__invert__(self)
860
return VerySpecial.__int__(self)
863
return VerySpecial.__long__(self)
866
return VerySpecial.__float__(self)
869
return VerySpecial.__oct__(self)
872
return VerySpecial.__hex__(self)
874
def __iadd__(self, other):
875
return VerySpecial.__iadd__(self, other)
877
def __isub__(self, other):
878
return VerySpecial.__isub__(self, other)
880
def __imul__(self, other):
881
return VerySpecial.__imul__(self, other)
883
def __idiv__(self, other):
884
return VerySpecial.__idiv__(self, other)
886
def __imod__(self, other):
887
return VerySpecial.__imod__(self, other)
889
def __ipow__(self, other):
890
return VerySpecial.__ipow__(self, other)
892
def __ilshift__(self, other):
893
return VerySpecial.__ilshift__(self, other)
895
def __irshift__(self, other):
896
return VerySpecial.__irshift__(self, other)
898
def __iand__(self, other):
899
return VerySpecial.__iand__(self, other)
901
def __ixor__(self, other):
902
return VerySpecial.__ixor__(self, other)
904
def __ior__(self, other):
905
return VerySpecial.__ior__(self, other)
907
def __ifloordiv__(self, other):
908
return VerySpecial.__ifloordiv__(self, other)
910
def __itruediv__(self, other):
911
return VerySpecial.__itruediv__(self, other)
914
return VerySpecial.__index__(self)
916
def __getitem__(self, index):
917
return VerySpecial.__getitem__(self, index)
919
def __contains__(self, other):
920
return VerySpecial.__contains__(self, other)
923
return VerySpecial.__len__(self)
925
def __cmp__(self, other):
926
return VerySpecial.__cmp__(self, other)
929
return VerySpecial.__repr__(self)
932
return VerySpecial.__hash__(self)
934
def __call__(self, arg):
935
return VerySpecial.__call__(self, arg)
938
return VerySpecial.__str__(self)
940
# there is no __richcmp__ at the Python level
941
# def __richcmp__(self, other, kind):
942
# return VerySpecial.__richcmp__(self, other, kind)
945
return VerySpecial.__iter__(self)
948
return VerySpecial.__next__(self)
950
def __get__(self, inst, own):
951
return VerySpecial.__get__(self, inst, own)
954
cdef class ReverseMethodsExist:
956
reverse methods (such as __radd__) don't work in Cython <3. However, if they
957
are defined then it should be possible to look them up explicitly instead of
958
looking up autogenerated wrapper (which points to the forward method)
960
>>> o = ReverseMethodsExist()
970
def __add__(self, other):
972
def __radd__(self, other):
974
def __rsub__(self, other):
978
cdef class ArgumentTypeConversions:
980
The user can set the signature of special method arguments so that
981
it doesn't match the C signature. This just tests that a few
984
>>> obj = ArgumentTypeConversions()
987
>>> obj["not a number!"]
988
Traceback (most recent call last):
990
TypeError: an integer is required
998
Here I'm not sure how reproducible the flags are between Python versions.
999
Therefore I'm just checking that they end with ".0"
1000
>>> memoryview(obj) # doctest:+ELLIPSIS
1001
Traceback (most recent call last):
1003
RuntimeError: From __getbuffer__ with flags ....0
1005
# force conversion of object to int
1006
def __getitem__(self, int x):
1009
# force conversion of comparison (int) to object
1010
def __richcmp__(self, other, object comparison):
1011
print "In comparison", comparison
1012
return not bool(comparison)
1014
# force conversion of flags (int) to double
1015
def __getbuffer__(self, Py_buffer *buffer, double flags):
1016
raise RuntimeError("From __getbuffer__ with flags {}".format(flags))
1019
cdef class TwoArgPow:
1021
>>> print(TwoArgPow('a')**2)
1023
>>> print(pow(TwoArgPow('a'), 3))
1025
>>> pow(TwoArgPow('a'), 'x', 'y')
1026
Traceback (most recent call last):
1028
TypeError: special_methods_T561.TwoArgPow.__pow__() takes 3 arguments but 2 were given
1032
def __init__(self, name):
1035
def __pow__(self, other):
1036
return f"{self.name}**{other}"
1039
cdef class TwoArgRPow:
1041
>>> print(2**TwoArgRPow('a'))
1043
>>> print(pow(3, TwoArgRPow('a')))
1045
>>> pow('x', TwoArgRPow('a'), 'y')
1046
Traceback (most recent call last):
1048
TypeError: special_methods_T561.TwoArgRPow.__rpow__() takes 3 arguments but 2 were given
1052
def __init__(self, name):
1055
def __rpow__(self, other):
1056
return f"{self.name}**{other}"
1060
# As far as DW can tell, calling through this C API call is the
1061
# only way to actually use ternary __ipow__
1062
return PyNumber_InPlacePower(a, b, c)
1065
cdef class TwoArgIPow:
1067
>>> a = TwoArgIPow('a')
1074
def __init__(self, name):
1077
def __ipow__(self, other):
1078
return f"{self.name}**{other}"
1080
if sys.version_info >= (3, 8):
1081
# Due to a bug this check can't usefully work in Python <3.8
1083
>>> ipow(TwoArgIPow('a'), 'x', 'y')
1084
Traceback (most recent call last):
1086
TypeError: special_methods_T561.TwoArgIPow.__ipow__() takes 3 arguments but 2 were given
1090
cdef class TwoOrThreeArgPow:
1092
>>> print(TwoOrThreeArgPow('a')**2)
1094
>>> print(pow(TwoOrThreeArgPow('a'), 3))
1096
>>> print(pow(TwoOrThreeArgPow('a'), 'x', 'y'))
1101
def __init__(self, name):
1104
def __pow__(self, other, base=None):
1105
return f"{self.name}**{other}[{base}]"
1108
cdef class TwoOrThreeArgRPow:
1110
>>> print(2**TwoOrThreeArgRPow('a'))
1112
>>> print(pow(3, TwoOrThreeArgRPow('a')))
1114
>>> print(pow('x', TwoOrThreeArgRPow('a'), 'y'))
1119
def __init__(self, name):
1122
def __rpow__(self, other, base=None):
1123
return f"{self.name}**{other}[{base}]"
1125
# See special_methods_T561_py38 for some extra tests for ipow