1
+ #![ feature( proc_macro, specialization) ]
2
+
3
+ extern crate pyo3;
4
+
5
+ use pyo3:: prelude:: * ;
6
+
7
+ use pyo3:: py:: class as pyclass;
8
+ use pyo3:: py:: proto as pyproto;
9
+
10
+
11
+ #[ macro_use]
12
+ mod common;
13
+
14
+ #[ pyclass]
15
+ struct UnaryArithmetic { token : PyToken }
16
+
17
+ #[ pyproto]
18
+ impl PyNumberProtocol for UnaryArithmetic {
19
+
20
+ fn __neg__ ( & self ) -> PyResult < & ' static str > {
21
+ Ok ( "neg" )
22
+ }
23
+
24
+ fn __pos__ ( & self ) -> PyResult < & ' static str > {
25
+ Ok ( "pos" )
26
+ }
27
+
28
+ fn __abs__ ( & self ) -> PyResult < & ' static str > {
29
+ Ok ( "abs" )
30
+ }
31
+
32
+ fn __invert__ ( & self ) -> PyResult < & ' static str > {
33
+ Ok ( "invert" )
34
+ }
35
+ }
36
+
37
+ #[ test]
38
+ fn unary_arithmetic ( ) {
39
+ let gil = Python :: acquire_gil ( ) ;
40
+ let py = gil. python ( ) ;
41
+
42
+ let c = py. init ( |t| UnaryArithmetic { token : t} ) . unwrap ( ) ;
43
+ py_run ! ( py, c, "assert -c == 'neg'" ) ;
44
+ py_run ! ( py, c, "assert +c == 'pos'" ) ;
45
+ py_run ! ( py, c, "assert abs(c) == 'abs'" ) ;
46
+ py_run ! ( py, c, "assert ~c == 'invert'" ) ;
47
+ }
48
+
49
+
50
+ #[ pyclass]
51
+ struct BinaryArithmetic {
52
+ token : PyToken
53
+ }
54
+
55
+ #[ pyproto]
56
+ impl PyObjectProtocol for BinaryArithmetic {
57
+ fn __repr__ ( & self ) -> PyResult < & ' static str > {
58
+ Ok ( "BA" )
59
+ }
60
+ }
61
+
62
+
63
+ #[ pyclass]
64
+ struct InPlaceOperations {
65
+ value : u32 ,
66
+ token : PyToken ,
67
+ }
68
+
69
+ #[ pyproto]
70
+ impl PyObjectProtocol for InPlaceOperations {
71
+ fn __repr__ ( & self ) -> PyResult < String > {
72
+ Ok ( format ! ( "IPO({:?})" , self . value) )
73
+ }
74
+ }
75
+
76
+ #[ pyproto]
77
+ impl PyNumberProtocol for InPlaceOperations {
78
+ fn __iadd__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
79
+ self . value += other;
80
+ Ok ( ( ) )
81
+ }
82
+
83
+ fn __isub__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
84
+ self . value -= other;
85
+ Ok ( ( ) )
86
+ }
87
+
88
+ fn __imul__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
89
+ self . value *= other;
90
+ Ok ( ( ) )
91
+ }
92
+
93
+ fn __ilshift__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
94
+ self . value <<= other;
95
+ Ok ( ( ) )
96
+ }
97
+
98
+ fn __irshift__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
99
+ self . value >>= other;
100
+ Ok ( ( ) )
101
+ }
102
+
103
+ fn __iand__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
104
+ self . value &= other;
105
+ Ok ( ( ) )
106
+ }
107
+
108
+ fn __ixor__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
109
+ self . value ^= other;
110
+ Ok ( ( ) )
111
+ }
112
+
113
+ fn __ior__ ( & mut self , other : u32 ) -> PyResult < ( ) > {
114
+ self . value |= other;
115
+ Ok ( ( ) )
116
+ }
117
+ }
118
+
119
+ #[ test]
120
+ fn inplace_operations ( ) {
121
+ let gil = Python :: acquire_gil ( ) ;
122
+ let py = gil. python ( ) ;
123
+
124
+ let c = py. init ( |t| InPlaceOperations { value : 0 , token : t} ) . unwrap ( ) ;
125
+ py_run ! ( py, c, "d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'" ) ;
126
+
127
+ let c = py. init ( |t| InPlaceOperations { value : 10 , token : t} ) . unwrap ( ) ;
128
+ py_run ! ( py, c, "d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'" ) ;
129
+
130
+ let c = py. init ( |t| InPlaceOperations { value : 3 , token : t} ) . unwrap ( ) ;
131
+ py_run ! ( py, c, "d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'" ) ;
132
+
133
+ let c = py. init ( |t| InPlaceOperations { value : 3 , token : t} ) . unwrap ( ) ;
134
+ py_run ! ( py, c, "d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'" ) ;
135
+
136
+ let c = py. init ( |t| InPlaceOperations { value : 12 , token : t} ) . unwrap ( ) ;
137
+ py_run ! ( py, c, "d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'" ) ;
138
+
139
+ let c = py. init ( |t| InPlaceOperations { value : 12 , token : t} ) . unwrap ( ) ;
140
+ py_run ! ( py, c, "d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'" ) ;
141
+
142
+ let c = py. init ( |t| InPlaceOperations { value : 12 , token : t} ) . unwrap ( ) ;
143
+ py_run ! ( py, c, "d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'" ) ;
144
+
145
+ let c = py. init ( |t| InPlaceOperations { value : 12 , token : t} ) . unwrap ( ) ;
146
+ py_run ! ( py, c, "d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'" ) ;
147
+ }
148
+
149
+ #[ pyproto]
150
+ impl PyNumberProtocol for BinaryArithmetic {
151
+ fn __add__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
152
+ Ok ( format ! ( "{:?} + {:?}" , lhs, rhs) )
153
+ }
154
+
155
+ fn __sub__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
156
+ Ok ( format ! ( "{:?} - {:?}" , lhs, rhs) )
157
+ }
158
+
159
+ fn __mul__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
160
+ Ok ( format ! ( "{:?} * {:?}" , lhs, rhs) )
161
+ }
162
+
163
+ fn __lshift__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
164
+ Ok ( format ! ( "{:?} << {:?}" , lhs, rhs) )
165
+ }
166
+
167
+ fn __rshift__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
168
+ Ok ( format ! ( "{:?} >> {:?}" , lhs, rhs) )
169
+ }
170
+
171
+ fn __and__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
172
+ Ok ( format ! ( "{:?} & {:?}" , lhs, rhs) )
173
+ }
174
+
175
+ fn __xor__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
176
+ Ok ( format ! ( "{:?} ^ {:?}" , lhs, rhs) )
177
+ }
178
+
179
+ fn __or__ ( lhs : & PyObjectRef , rhs : & PyObjectRef ) -> PyResult < String > {
180
+ Ok ( format ! ( "{:?} | {:?}" , lhs, rhs) )
181
+ }
182
+ }
183
+
184
+ #[ test]
185
+ fn binary_arithmetic ( ) {
186
+ let gil = Python :: acquire_gil ( ) ;
187
+ let py = gil. python ( ) ;
188
+
189
+ let c = py. init ( |t| BinaryArithmetic { token : t} ) . unwrap ( ) ;
190
+ py_run ! ( py, c, "assert c + c == 'BA + BA'" ) ;
191
+ py_run ! ( py, c, "assert c + 1 == 'BA + 1'" ) ;
192
+ py_run ! ( py, c, "assert 1 + c == '1 + BA'" ) ;
193
+ py_run ! ( py, c, "assert c - 1 == 'BA - 1'" ) ;
194
+ py_run ! ( py, c, "assert 1 - c == '1 - BA'" ) ;
195
+ py_run ! ( py, c, "assert c * 1 == 'BA * 1'" ) ;
196
+ py_run ! ( py, c, "assert 1 * c == '1 * BA'" ) ;
197
+
198
+ py_run ! ( py, c, "assert c << 1 == 'BA << 1'" ) ;
199
+ py_run ! ( py, c, "assert 1 << c == '1 << BA'" ) ;
200
+ py_run ! ( py, c, "assert c >> 1 == 'BA >> 1'" ) ;
201
+ py_run ! ( py, c, "assert 1 >> c == '1 >> BA'" ) ;
202
+ py_run ! ( py, c, "assert c & 1 == 'BA & 1'" ) ;
203
+ py_run ! ( py, c, "assert 1 & c == '1 & BA'" ) ;
204
+ py_run ! ( py, c, "assert c ^ 1 == 'BA ^ 1'" ) ;
205
+ py_run ! ( py, c, "assert 1 ^ c == '1 ^ BA'" ) ;
206
+ py_run ! ( py, c, "assert c | 1 == 'BA | 1'" ) ;
207
+ py_run ! ( py, c, "assert 1 | c == '1 | BA'" ) ;
208
+ }
209
+
210
+
211
+ #[ pyclass]
212
+ struct RichComparisons {
213
+ token : PyToken
214
+ }
215
+
216
+ #[ pyproto]
217
+ impl PyObjectProtocol for RichComparisons {
218
+ fn __repr__ ( & self ) -> PyResult < & ' static str > {
219
+ Ok ( "RC" )
220
+ }
221
+
222
+ fn __richcmp__ ( & self , other : & PyObjectRef , op : CompareOp ) -> PyResult < String > {
223
+ match op {
224
+ CompareOp :: Lt => Ok ( format ! ( "{} < {:?}" , self . __repr__( ) . unwrap( ) , other) ) ,
225
+ CompareOp :: Le => Ok ( format ! ( "{} <= {:?}" , self . __repr__( ) . unwrap( ) , other) ) ,
226
+ CompareOp :: Eq => Ok ( format ! ( "{} == {:?}" , self . __repr__( ) . unwrap( ) , other) ) ,
227
+ CompareOp :: Ne => Ok ( format ! ( "{} != {:?}" , self . __repr__( ) . unwrap( ) , other) ) ,
228
+ CompareOp :: Gt => Ok ( format ! ( "{} > {:?}" , self . __repr__( ) . unwrap( ) , other) ) ,
229
+ CompareOp :: Ge => Ok ( format ! ( "{} >= {:?}" , self . __repr__( ) . unwrap( ) , other) )
230
+ }
231
+ }
232
+ }
233
+
234
+ #[ pyclass]
235
+ struct RichComparisons2 {
236
+ py : PyToken
237
+ }
238
+
239
+ #[ pyproto]
240
+ impl PyObjectProtocol for RichComparisons2 {
241
+ fn __repr__ ( & self ) -> PyResult < & ' static str > {
242
+ Ok ( "RC2" )
243
+ }
244
+
245
+ fn __richcmp__ ( & self , _other : & ' p PyObjectRef , op : CompareOp ) -> PyResult < PyObject > {
246
+ match op {
247
+ CompareOp :: Eq => Ok ( true . to_object ( self . py ( ) ) ) ,
248
+ CompareOp :: Ne => Ok ( false . to_object ( self . py ( ) ) ) ,
249
+ _ => Ok ( self . py ( ) . NotImplemented ( ) )
250
+ }
251
+ }
252
+ }
253
+
254
+ #[ test]
255
+ fn rich_comparisons ( ) {
256
+ let gil = Python :: acquire_gil ( ) ;
257
+ let py = gil. python ( ) ;
258
+
259
+ let c = py. init ( |t| RichComparisons { token : t} ) . unwrap ( ) ;
260
+ py_run ! ( py, c, "assert (c < c) == 'RC < RC'" ) ;
261
+ py_run ! ( py, c, "assert (c < 1) == 'RC < 1'" ) ;
262
+ py_run ! ( py, c, "assert (1 < c) == 'RC > 1'" ) ;
263
+ py_run ! ( py, c, "assert (c <= c) == 'RC <= RC'" ) ;
264
+ py_run ! ( py, c, "assert (c <= 1) == 'RC <= 1'" ) ;
265
+ py_run ! ( py, c, "assert (1 <= c) == 'RC >= 1'" ) ;
266
+ py_run ! ( py, c, "assert (c == c) == 'RC == RC'" ) ;
267
+ py_run ! ( py, c, "assert (c == 1) == 'RC == 1'" ) ;
268
+ py_run ! ( py, c, "assert (1 == c) == 'RC == 1'" ) ;
269
+ py_run ! ( py, c, "assert (c != c) == 'RC != RC'" ) ;
270
+ py_run ! ( py, c, "assert (c != 1) == 'RC != 1'" ) ;
271
+ py_run ! ( py, c, "assert (1 != c) == 'RC != 1'" ) ;
272
+ py_run ! ( py, c, "assert (c > c) == 'RC > RC'" ) ;
273
+ py_run ! ( py, c, "assert (c > 1) == 'RC > 1'" ) ;
274
+ py_run ! ( py, c, "assert (1 > c) == 'RC < 1'" ) ;
275
+ py_run ! ( py, c, "assert (c >= c) == 'RC >= RC'" ) ;
276
+ py_run ! ( py, c, "assert (c >= 1) == 'RC >= 1'" ) ;
277
+ py_run ! ( py, c, "assert (1 >= c) == 'RC <= 1'" ) ;
278
+ }
279
+
280
+ #[ test]
281
+ #[ cfg( Py_3 ) ]
282
+ fn rich_comparisons_python_3_type_error ( ) {
283
+ let gil = Python :: acquire_gil ( ) ;
284
+ let py = gil. python ( ) ;
285
+
286
+ let c2 = py. init ( |t| RichComparisons2 { py : t} ) . unwrap ( ) ;
287
+ py_expect_exception ! ( py, c2, "c2 < c2" , TypeError ) ;
288
+ py_expect_exception ! ( py, c2, "c2 < 1" , TypeError ) ;
289
+ py_expect_exception ! ( py, c2, "1 < c2" , TypeError ) ;
290
+ py_expect_exception ! ( py, c2, "c2 <= c2" , TypeError ) ;
291
+ py_expect_exception ! ( py, c2, "c2 <= 1" , TypeError ) ;
292
+ py_expect_exception ! ( py, c2, "1 <= c2" , TypeError ) ;
293
+ py_run ! ( py, c2, "assert (c2 == c2) == True" ) ;
294
+ py_run ! ( py, c2, "assert (c2 == 1) == True" ) ;
295
+ py_run ! ( py, c2, "assert (1 == c2) == True" ) ;
296
+ py_run ! ( py, c2, "assert (c2 != c2) == False" ) ;
297
+ py_run ! ( py, c2, "assert (c2 != 1) == False" ) ;
298
+ py_run ! ( py, c2, "assert (1 != c2) == False" ) ;
299
+ py_expect_exception ! ( py, c2, "c2 > c2" , TypeError ) ;
300
+ py_expect_exception ! ( py, c2, "c2 > 1" , TypeError ) ;
301
+ py_expect_exception ! ( py, c2, "1 > c2" , TypeError ) ;
302
+ py_expect_exception ! ( py, c2, "c2 >= c2" , TypeError ) ;
303
+ py_expect_exception ! ( py, c2, "c2 >= 1" , TypeError ) ;
304
+ py_expect_exception ! ( py, c2, "1 >= c2" , TypeError ) ;
305
+ }
0 commit comments