From 92e99e30626ac40544b3a8818fb9552c65c0adcf Mon Sep 17 00:00:00 2001 From: Will Stott Date: Sat, 18 Mar 2023 11:04:05 +0000 Subject: [PATCH] Fix compile error when trying to use static slot methods --- pyo3-macros-backend/src/pymethod.rs | 3 +- tests/test_static_slots.rs | 57 +++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tests/test_static_slots.rs diff --git a/pyo3-macros-backend/src/pymethod.rs b/pyo3-macros-backend/src/pymethod.rs index a93fe70f859..82cd1fd28e4 100644 --- a/pyo3-macros-backend/src/pymethod.rs +++ b/pyo3-macros-backend/src/pymethod.rs @@ -1195,9 +1195,10 @@ fn generate_method_body( return_mode: Option<&ReturnMode>, ) -> Result { let self_conversion = spec.tp.self_conversion(Some(cls), extract_error_mode); + let self_arg = spec.tp.self_arg(); let rust_name = spec.name; let args = extract_proto_arguments(py, spec, arguments, extract_error_mode)?; - let call = quote! { _pyo3::callback::convert(#py, #cls::#rust_name(_slf, #(#args),*)) }; + let call = quote! { _pyo3::callback::convert(#py, #cls::#rust_name(#self_arg #(#args),*)) }; let body = if let Some(return_mode) = return_mode { return_mode.return_call_output(py, call) } else { diff --git a/tests/test_static_slots.rs b/tests/test_static_slots.rs new file mode 100644 index 00000000000..12192eabbb0 --- /dev/null +++ b/tests/test_static_slots.rs @@ -0,0 +1,57 @@ +#![cfg(feature = "macros")] + +use pyo3::exceptions::PyIndexError; +use pyo3::prelude::*; +use pyo3::types::IntoPyDict; + +use pyo3::py_run; + +mod common; + +#[pyclass] +struct Vector3 { + elements: [f64; 3], +} + +#[pymethods] +impl Vector3 { + #[new] + fn new(x: f64, y: f64, z: f64) -> Self { + Self { + elements: [x, y, z], + } + } + + #[staticmethod] + fn __len__() -> usize { + 3 + } + + fn __getitem__(&self, idx: isize) -> PyResult { + self.elements + .get(idx as usize) + .copied() + .ok_or_else(|| PyIndexError::new_err("list index out of range")) + } + + fn __setitem__(&mut self, idx: isize, value: f64) { + self.elements[idx as usize] = value; + } +} + +/// Return a dict with `s = Vector3(1, 2, 3)`. +fn seq_dict(py: Python<'_>) -> &pyo3::types::PyDict { + let d = [("Vector3", py.get_type::())].into_py_dict(py); + // Though we can construct `s` in Rust, let's test `__new__` works. + py_run!(py, *d, "s = Vector3(1, 2, 3)"); + d +} + +#[test] +fn test_len() { + Python::with_gil(|py| { + let d = seq_dict(py); + + py_assert!(py, *d, "len(s) == 3"); + }); +}