Skip to content

Commit 9dc7661

Browse files
authored
Merge pull request #150 from konstin/test_class
Split up test_class into multiple files
2 parents 7f49673 + 3e8a36b commit 9dc7661

14 files changed

+1608
-1517
lines changed

tests/common.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#[macro_export]
2+
macro_rules! py_run {
3+
($py:expr, $val:ident, $code:expr) => {{
4+
let d = PyDict::new($py);
5+
d.set_item(stringify!($val), &$val).unwrap();
6+
$py.run($code, None, Some(d)).map_err(|e| e.print($py)).expect($code);
7+
}}
8+
}
9+
10+
#[macro_export]
11+
macro_rules! py_assert {
12+
($py:expr, $val:ident, $assertion:expr) => { py_run!($py, $val, concat!("assert ", $assertion)) };
13+
}
14+
15+
#[macro_export]
16+
macro_rules! py_expect_exception {
17+
($py:expr, $val:ident, $code:expr, $err:ident) => {{
18+
let d = PyDict::new($py);
19+
d.set_item(stringify!($val), &$val).unwrap();
20+
let res = $py.run($code, None, Some(d));
21+
let err = res.unwrap_err();
22+
if !err.matches($py, $py.get_type::<exc::$err>()) {
23+
panic!(format!("Expected {} but got {:?}", stringify!($err), err))
24+
}
25+
}}
26+
}

tests/test_arithmetics.rs

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
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+
}

tests/test_buffer_protocol.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
#![allow(dead_code, unused_variables)]
2-
#![feature(proc_macro, specialization, const_fn, const_align_of, const_size_of)]
1+
#![feature(proc_macro, specialization)]
32

43
extern crate pyo3;
54

65
use std::ptr;
76
use std::os::raw::{c_int, c_void};
87

9-
use pyo3::*;
8+
use pyo3::prelude::*;
9+
use pyo3::ffi;
1010

1111
use pyo3::py::class as pyclass;
1212
use pyo3::py::proto as pyproto;
@@ -19,7 +19,7 @@ struct TestClass {
1919
}
2020

2121
#[pyproto]
22-
impl class::PyBufferProtocol for TestClass {
22+
impl PyBufferProtocol for TestClass {
2323

2424
fn bf_getbuffer(&self, view: *mut ffi::Py_buffer, flags: c_int) -> PyResult<()> {
2525
if view.is_null() {

0 commit comments

Comments
 (0)