Skip to content

Commit 9b88a45

Browse files
committed
Refactor tests to use shorter macros
1 parent 7ec1fed commit 9b88a45

9 files changed

+217
-179
lines changed

src/lib.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,11 @@ macro_rules! wrap_pymodule {
331331
/// });
332332
/// ```
333333
///
334-
/// If you need to prepare the `locals` dict by yourself, you can pass it by `*locals`.
334+
/// If you need to prepare the `locals` dict by yourself, you can pass it as `*locals`.
335335
///
336336
/// ```
337-
/// # use pyo3::prelude::*;
337+
/// use pyo3::prelude::*;
338+
/// use pyo3::types::IntoPyDict;
338339
/// #[pyclass]
339340
/// struct MyClass {}
340341
/// #[pymethods]
@@ -343,7 +344,7 @@ macro_rules! wrap_pymodule {
343344
/// fn new() -> Self { MyClass {} }
344345
/// }
345346
/// Python::with_gil(|py| {
346-
/// let locals = [("C", py.get_type::<MyClass>())];
347+
/// let locals = [("C", py.get_type::<MyClass>())].into_py_dict(py);
347348
/// pyo3::py_run!(py, *locals, "c = C()");
348349
/// });
349350
/// ```

tests/test_buffer_protocol.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use std::ptr;
1313
use std::sync::atomic::{AtomicBool, Ordering};
1414
use std::sync::Arc;
1515

16+
mod common;
17+
1618
#[pyclass]
1719
struct TestBufferClass {
1820
vec: Vec<u8>,
@@ -93,8 +95,7 @@ fn test_buffer() {
9395
)
9496
.unwrap();
9597
let env = [("ob", instance)].into_py_dict(py);
96-
py.run("assert bytes(ob) == b' 23'", None, Some(env))
97-
.unwrap();
98+
py_assert!(py, *env, "bytes(ob) == b' 23'");
9899
}
99100

100101
assert!(drop_called.load(Ordering::Relaxed));

tests/test_dunder.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use pyo3::class::{
44
};
55
use pyo3::exceptions::{PyIndexError, PyValueError};
66
use pyo3::prelude::*;
7-
use pyo3::types::{IntoPyDict, PySlice, PyType};
7+
use pyo3::types::{PySlice, PyType};
88
use pyo3::{ffi, py_run, AsPyPointer, PyCell};
99
use std::convert::TryFrom;
1010
use std::{isize, iter};
@@ -446,11 +446,9 @@ fn test_cls_impl() {
446446
let py = gil.python();
447447

448448
let ob = Py::new(py, Test {}).unwrap();
449-
let d = [("ob", ob)].into_py_dict(py);
450449

451-
py.run("assert ob[1] == 'int'", None, Some(d)).unwrap();
452-
py.run("assert ob[100:200:1] == 'slice'", None, Some(d))
453-
.unwrap();
450+
py_assert!(py, ob, "ob[1] == 'int'");
451+
py_assert!(py, ob, "ob[100:200:1] == 'slice'");
454452
}
455453

456454
#[pyclass(dict, subclass)]

tests/test_getter_setter.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,7 @@ fn class_with_properties() {
6060
py_run!(py, inst, "assert inst.data_list == [42]");
6161

6262
let d = [("C", py.get_type::<ClassWithProperties>())].into_py_dict(py);
63-
py.run(
64-
"assert C.DATA.__doc__ == 'a getter for data'",
65-
None,
66-
Some(d),
67-
)
68-
.unwrap();
63+
py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'");
6964
}
7065

7166
#[pyclass]

tests/test_mapping.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ use std::collections::HashMap;
22

33
use pyo3::exceptions::PyKeyError;
44
use pyo3::prelude::*;
5+
use pyo3::py_run;
56
use pyo3::types::IntoPyDict;
67
use pyo3::types::PyList;
78
use pyo3::PyMappingProtocol;
89

10+
mod common;
11+
912
#[pyclass]
1013
struct Mapping {
1114
index: HashMap<String, usize>,
@@ -66,61 +69,58 @@ impl PyMappingProtocol for Mapping {
6669
}
6770
}
6871

72+
/// Return a dict with `m = Mapping(['1', '2', '3'])`.
73+
fn map_dict(py: Python) -> &pyo3::types::PyDict {
74+
let d = [("Mapping", py.get_type::<Mapping>())].into_py_dict(py);
75+
py_run!(py, *d, "m = Mapping(['1', '2', '3'])");
76+
d
77+
}
78+
6979
#[test]
7080
fn test_getitem() {
7181
let gil = Python::acquire_gil();
7282
let py = gil.python();
73-
let d = [("Mapping", py.get_type::<Mapping>())].into_py_dict(py);
74-
75-
let run = |code| py.run(code, None, Some(d)).unwrap();
76-
let err = |code| py.run(code, None, Some(d)).unwrap_err();
83+
let d = map_dict(py);
7784

78-
run("m = Mapping(['1', '2', '3']); assert m['1'] == 0");
79-
run("m = Mapping(['1', '2', '3']); assert m['2'] == 1");
80-
run("m = Mapping(['1', '2', '3']); assert m['3'] == 2");
81-
err("m = Mapping(['1', '2', '3']); print(m['4'])");
85+
py_assert!(py, *d, "m['1'] == 0");
86+
py_assert!(py, *d, "m['2'] == 1");
87+
py_assert!(py, *d, "m['3'] == 2");
88+
py_expect_exception!(py, *d, "print(m['4'])", PyKeyError);
8289
}
8390

8491
#[test]
8592
fn test_setitem() {
8693
let gil = Python::acquire_gil();
8794
let py = gil.python();
88-
let d = [("Mapping", py.get_type::<Mapping>())].into_py_dict(py);
89-
90-
let run = |code| py.run(code, None, Some(d)).unwrap();
91-
let err = |code| py.run(code, None, Some(d)).unwrap_err();
95+
let d = map_dict(py);
9296

93-
run("m = Mapping(['1', '2', '3']); m['1'] = 4; assert m['1'] == 4");
94-
run("m = Mapping(['1', '2', '3']); m['0'] = 0; assert m['0'] == 0");
95-
run("m = Mapping(['1', '2', '3']); len(m) == 4");
96-
err("m = Mapping(['1', '2', '3']); m[0] = 'hello'");
97-
err("m = Mapping(['1', '2', '3']); m[0] = -1");
97+
py_run!(py, *d, "m['1'] = 4; assert m['1'] == 4");
98+
py_run!(py, *d, "m['0'] = 0; assert m['0'] == 0");
99+
py_assert!(py, *d, "len(m) == 4");
100+
py_expect_exception!(py, *d, "m[0] = 'hello'", PyTypeError);
101+
py_expect_exception!(py, *d, "m[0] = -1", PyTypeError);
98102
}
99103

100104
#[test]
101105
fn test_delitem() {
102106
let gil = Python::acquire_gil();
103107
let py = gil.python();
104108

105-
let d = [("Mapping", py.get_type::<Mapping>())].into_py_dict(py);
106-
let run = |code| py.run(code, None, Some(d)).unwrap();
107-
let err = |code| py.run(code, None, Some(d)).unwrap_err();
108-
109-
run(
110-
"m = Mapping(['1', '2', '3']); del m['1']; assert len(m) == 2; \
111-
assert m['2'] == 1; assert m['3'] == 2",
109+
let d = map_dict(py);
110+
py_run!(
111+
py,
112+
*d,
113+
"del m['1']; assert len(m) == 2 and m['2'] == 1 and m['3'] == 2"
112114
);
113-
err("m = Mapping(['1', '2', '3']); del m[-1]");
114-
err("m = Mapping(['1', '2', '3']); del m['4']");
115+
py_expect_exception!(py, *d, "del m[-1]", PyTypeError);
116+
py_expect_exception!(py, *d, "del m['4']", PyKeyError);
115117
}
116118

117119
#[test]
118120
fn test_reversed() {
119121
let gil = Python::acquire_gil();
120122
let py = gil.python();
121123

122-
let d = [("Mapping", py.get_type::<Mapping>())].into_py_dict(py);
123-
let run = |code| py.run(code, None, Some(d)).unwrap();
124-
125-
run("m = Mapping(['1', '2']); assert set(reversed(m)) == {'1', '2'}");
124+
let d = map_dict(py);
125+
py_assert!(py, *d, "set(reversed(m)) == {'1', '2', '3'}");
126126
}

tests/test_methods.rs

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,8 @@ fn instance_method_with_args() {
5656
let obj = PyCell::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();
5757
let obj_ref = obj.borrow();
5858
assert_eq!(obj_ref.method(6), 42);
59-
let d = [("obj", obj)].into_py_dict(py);
60-
py.run("assert obj.method(3) == 21", None, Some(d)).unwrap();
61-
py.run("assert obj.method(multiplier=6) == 42", None, Some(d))
62-
.unwrap();
59+
py_assert!(py, obj, "obj.method(3) == 21");
60+
py_assert!(py, obj, "obj.method(multiplier=6) == 42");
6361
}
6462

6563
#[pyclass]
@@ -85,15 +83,10 @@ fn class_method() {
8583
let py = gil.python();
8684

8785
let d = [("C", py.get_type::<ClassMethod>())].into_py_dict(py);
88-
let run = |code| {
89-
py.run(code, None, Some(d))
90-
.map_err(|e| e.print(py))
91-
.unwrap()
92-
};
93-
run("assert C.method() == 'ClassMethod.method()!'");
94-
run("assert C().method() == 'ClassMethod.method()!'");
95-
run("assert C.method.__doc__ == 'Test class method.'");
96-
run("assert C().method.__doc__ == 'Test class method.'");
86+
py_assert!(py, *d, "C.method() == 'ClassMethod.method()!'");
87+
py_assert!(py, *d, "C().method() == 'ClassMethod.method()!'");
88+
py_assert!(py, *d, "C.method.__doc__ == 'Test class method.'");
89+
py_assert!(py, *d, "C().method.__doc__ == 'Test class method.'");
9790
}
9891

9992
#[pyclass]
@@ -113,12 +106,11 @@ fn class_method_with_args() {
113106
let py = gil.python();
114107

115108
let d = [("C", py.get_type::<ClassMethodWithArgs>())].into_py_dict(py);
116-
py.run(
117-
"assert C.method('abc') == 'ClassMethodWithArgs.method(abc)'",
118-
None,
119-
Some(d),
120-
)
121-
.unwrap();
109+
py_assert!(
110+
py,
111+
*d,
112+
"C.method('abc') == 'ClassMethodWithArgs.method(abc)'"
113+
);
122114
}
123115

124116
#[pyclass]
@@ -146,15 +138,10 @@ fn static_method() {
146138
assert_eq!(StaticMethod::method(py), "StaticMethod.method()!");
147139

148140
let d = [("C", py.get_type::<StaticMethod>())].into_py_dict(py);
149-
let run = |code| {
150-
py.run(code, None, Some(d))
151-
.map_err(|e| e.print(py))
152-
.unwrap()
153-
};
154-
run("assert C.method() == 'StaticMethod.method()!'");
155-
run("assert C().method() == 'StaticMethod.method()!'");
156-
run("assert C.method.__doc__ == 'Test static method.'");
157-
run("assert C().method.__doc__ == 'Test static method.'");
141+
py_assert!(py, *d, "C.method() == 'StaticMethod.method()!'");
142+
py_assert!(py, *d, "C().method() == 'StaticMethod.method()!'");
143+
py_assert!(py, *d, "C.method.__doc__ == 'Test static method.'");
144+
py_assert!(py, *d, "C().method.__doc__ == 'Test static method.'");
158145
}
159146

160147
#[pyclass]
@@ -176,8 +163,7 @@ fn static_method_with_args() {
176163
assert_eq!(StaticMethodWithArgs::method(py, 1234), "0x4d2");
177164

178165
let d = [("C", py.get_type::<StaticMethodWithArgs>())].into_py_dict(py);
179-
py.run("assert C.method(1337) == '0x539'", None, Some(d))
180-
.unwrap();
166+
py_assert!(py, *d, "C.method(1337) == '0x539'");
181167
}
182168

183169
#[pyclass]
@@ -449,15 +435,17 @@ fn meth_doc() {
449435
let gil = Python::acquire_gil();
450436
let py = gil.python();
451437
let d = [("C", py.get_type::<MethDocs>())].into_py_dict(py);
452-
let run = |code| {
453-
py.run(code, None, Some(d))
454-
.map_err(|e| e.print(py))
455-
.unwrap()
456-
};
457-
458-
run("assert C.__doc__ == 'A class with \"documentation\".'");
459-
run("assert C.method.__doc__ == 'A method with \"documentation\" as well.'");
460-
run("assert C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'");
438+
py_assert!(py, *d, "C.__doc__ == 'A class with \"documentation\".'");
439+
py_assert!(
440+
py,
441+
*d,
442+
"C.method.__doc__ == 'A method with \"documentation\" as well.'"
443+
);
444+
py_assert!(
445+
py,
446+
*d,
447+
"C.x.__doc__ == '`int`: a very \"important\" member of \\'this\\' instance.'"
448+
);
461449
}
462450

463451
#[pyclass]
@@ -530,20 +518,31 @@ fn method_with_pyclassarg() {
530518
let py = gil.python();
531519
let obj1 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
532520
let obj2 = PyCell::new(py, MethodWithPyClassArg { value: 10 }).unwrap();
533-
let objs = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py);
534-
let run = |code| {
535-
py.run(code, None, Some(objs))
536-
.map_err(|e| e.print(py))
537-
.unwrap()
538-
};
539-
run("obj = obj1.add(obj2); assert obj.value == 20");
540-
run("obj = obj1.add_pyref(obj2); assert obj.value == 20");
541-
run("obj = obj1.optional_add(); assert obj.value == 20");
542-
run("obj = obj1.optional_add(obj2); assert obj.value == 20");
543-
run("obj1.inplace_add(obj2); assert obj.value == 20");
544-
run("obj1.inplace_add_pyref(obj2); assert obj2.value == 30");
545-
run("obj1.optional_inplace_add(); assert obj2.value == 30");
546-
run("obj1.optional_inplace_add(obj2); assert obj2.value == 40");
521+
let d = [("obj1", obj1), ("obj2", obj2)].into_py_dict(py);
522+
py_run!(py, *d, "obj = obj1.add(obj2); assert obj.value == 20");
523+
py_run!(py, *d, "obj = obj1.add_pyref(obj2); assert obj.value == 20");
524+
py_run!(py, *d, "obj = obj1.optional_add(); assert obj.value == 20");
525+
py_run!(
526+
py,
527+
*d,
528+
"obj = obj1.optional_add(obj2); assert obj.value == 20"
529+
);
530+
py_run!(py, *d, "obj1.inplace_add(obj2); assert obj.value == 20");
531+
py_run!(
532+
py,
533+
*d,
534+
"obj1.inplace_add_pyref(obj2); assert obj2.value == 30"
535+
);
536+
py_run!(
537+
py,
538+
*d,
539+
"obj1.optional_inplace_add(); assert obj2.value == 30"
540+
);
541+
py_run!(
542+
py,
543+
*d,
544+
"obj1.optional_inplace_add(obj2); assert obj2.value == 40"
545+
);
547546
}
548547

549548
#[pyclass]

0 commit comments

Comments
 (0)