File: test_macros.rs

package info (click to toggle)
rust-pyo3 0.22.6-3
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 3,420 kB
  • sloc: makefile: 58; python: 39; sh: 1
file content (94 lines) | stat: -rw-r--r-- 2,483 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#![cfg(feature = "macros")]

//! Ensure that pyo3 macros can be used inside macro_rules!

use pyo3::prelude::*;

#[macro_use]
#[path = "../src/tests/common.rs"]
mod common;

macro_rules! make_struct_using_macro {
    // Ensure that one doesn't need to fall back on the escape type: tt
    // in order to macro create pyclass.
    ($class_name:ident, $py_name:literal) => {
        #[pyclass(name=$py_name)]
        struct $class_name {}
    };
}

make_struct_using_macro!(MyBaseClass, "MyClass");

macro_rules! set_extends_via_macro {
    ($class_name:ident, $base_class:path) => {
        // Try and pass a variable into the extends parameter
        #[allow(dead_code)]
        #[pyclass(extends=$base_class)]
        struct $class_name {}
    };
}

set_extends_via_macro!(MyClass2, MyBaseClass);

//
// Check that pyfunctiona nd text_signature can be called with macro arguments.
//

macro_rules! fn_macro {
    ($sig:literal, $a_exp:expr, $b_exp:expr, $c_exp: expr) => {
        // Try and pass a variable into the signature parameter
        #[pyfunction(signature = ($a_exp, $b_exp, *, $c_exp))]
        #[pyo3(text_signature = $sig)]
        fn my_function_in_macro(a: i32, b: Option<i32>, c: i32) {
            let _ = (a, b, c);
        }
    };
}

fn_macro!("(a, b=None, *, c=42)", a, b = None, c = 42);

macro_rules! property_rename_via_macro {
    ($prop_name:ident) => {
        #[pyclass]
        struct ClassWithProperty {
            member: u64,
        }

        #[pymethods]
        impl ClassWithProperty {
            #[getter($prop_name)]
            fn get_member(&self) -> u64 {
                self.member
            }

            #[setter($prop_name)]
            fn set_member(&mut self, member: u64) {
                self.member = member;
            }
        }
    };
}

property_rename_via_macro!(my_new_property_name);

#[test]
fn test_macro_rules_interactions() {
    Python::with_gil(|py| {
        let my_base = py.get_type_bound::<MyBaseClass>();
        py_assert!(py, my_base, "my_base.__name__ == 'MyClass'");

        let my_func = wrap_pyfunction_bound!(my_function_in_macro, py).unwrap();
        py_assert!(
            py,
            my_func,
            "my_func.__text_signature__ == '(a, b=None, *, c=42)'"
        );

        let renamed_prop = py.get_type_bound::<ClassWithProperty>();
        py_assert!(
            py,
            renamed_prop,
            "hasattr(renamed_prop, 'my_new_property_name')"
        );
    });
}