Tests and PyO3
I recently discovered that when using PyO3’s getters and setters for a pyclass
, cargo test
is broken. Consider the following example lib.rs:
#[pyclass]
struct MyStruct {
#[pyo3(get, set)] // Makes `i` readable/writable in Python
i: u32,
}
#[pymethods]
impl MyStruct {
#[new]
fn new(i: u32) -> Self {
MyStruct { i: i + 1 }
}
}
#[pymodule]
fn tests_and_getters(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<MyStruct>()?;
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn i_plus_1() {
let my_struct = MyStruct::new(123);
assert_eq!(my_struct.i, 124);
}
}
Creating an instance of MyStruct
should set its value of i
to the passed value plus one. So how do we test it? We should be able to i_plus_1
with cargo test
. What we find instead is the following error:
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "...
...
...
= note: /home/user/rust/gettertest/target/debug/deps/tests_and_getters-94c0ceb1fd2ab0ef.hra3dhvd2c210xh.rcgu.o: In function `pyo3::err::PyErr::restore':
/home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/pyo3-0.9.1/src/err.rs:345: undefined reference to `PyErr_Restore'
/home/user/rust/gettertest/target/debug/deps/libpyo3-a88cb910efc8a664.rlib(pyo3-a88cb910efc8
...
Note that this error doesn’t occur if we comment out the getter and setter attributes. In other words, this will let us run cargo test
without a problem:
#[pyclass]
struct MyStruct {
// #[pyo3(get, set)] // Makes `i` readable/writable in Python
i: u32,
}
Since I’m starting to use PyO3 in a work project, I’d really like to include tests in my code without giving up using getters/setters. Fortunately, there’s a workaround. By default, we might set features = ["extension-module"]
in our Cargo.toml. Instead, change this to:
[dependencies.pyo3]
version = "0.9.1"
# No longer need this:
#features = ["extension-module"]
# But we want these two:
extension-module = ["extension-module"]
default = ["extension-module"]
Then - just for testing - disable default features:
cargo test --no-default-features