2021-12-03 00:03:32 +00:00
|
|
|
#![cfg(feature = "macros")]
|
|
|
|
|
2020-05-05 19:54:09 +00:00
|
|
|
use pyo3::prelude::*;
|
|
|
|
|
|
|
|
mod common;
|
|
|
|
|
|
|
|
#[pyclass]
|
2020-05-07 18:13:10 +00:00
|
|
|
struct Foo {
|
|
|
|
#[pyo3(get)]
|
|
|
|
x: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pyclass]
|
|
|
|
struct Bar {
|
|
|
|
#[pyo3(get)]
|
|
|
|
x: i32,
|
|
|
|
}
|
2020-05-05 19:54:09 +00:00
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl Foo {
|
2020-05-07 19:20:34 +00:00
|
|
|
#[classattr]
|
|
|
|
const MY_CONST: &'static str = "foobar";
|
|
|
|
|
2021-04-17 21:22:06 +00:00
|
|
|
#[classattr]
|
|
|
|
#[pyo3(name = "RENAMED_CONST")]
|
|
|
|
const MY_CONST_2: &'static str = "foobar_2";
|
|
|
|
|
2020-05-05 19:54:09 +00:00
|
|
|
#[classattr]
|
|
|
|
fn a() -> i32 {
|
|
|
|
5
|
|
|
|
}
|
|
|
|
|
|
|
|
#[classattr]
|
2021-04-17 21:22:06 +00:00
|
|
|
#[pyo3(name = "B")]
|
2020-05-05 19:54:09 +00:00
|
|
|
fn b() -> String {
|
|
|
|
"bar".to_string()
|
|
|
|
}
|
2020-05-07 18:13:10 +00:00
|
|
|
|
|
|
|
#[classattr]
|
|
|
|
fn bar() -> Bar {
|
|
|
|
Bar { x: 2 }
|
|
|
|
}
|
2020-06-22 21:13:23 +00:00
|
|
|
|
|
|
|
#[classattr]
|
2021-08-17 06:51:08 +00:00
|
|
|
fn a_foo() -> Foo {
|
2020-06-22 21:13:23 +00:00
|
|
|
Foo { x: 1 }
|
|
|
|
}
|
2020-05-07 18:13:10 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 19:54:09 +00:00
|
|
|
#[test]
|
|
|
|
fn class_attributes() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
let foo_obj = py.get_type::<Foo>();
|
2021-04-17 21:22:06 +00:00
|
|
|
py_assert!(py, foo_obj, "foo_obj.MY_CONST == 'foobar'");
|
|
|
|
py_assert!(py, foo_obj, "foo_obj.RENAMED_CONST == 'foobar_2'");
|
2020-05-05 19:54:09 +00:00
|
|
|
py_assert!(py, foo_obj, "foo_obj.a == 5");
|
|
|
|
py_assert!(py, foo_obj, "foo_obj.B == 'bar'");
|
2021-08-17 06:51:08 +00:00
|
|
|
py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1");
|
2020-05-05 19:54:09 +00:00
|
|
|
}
|
2020-05-06 18:11:29 +00:00
|
|
|
|
2020-09-01 00:36:26 +00:00
|
|
|
// Ignored because heap types are not immutable:
|
|
|
|
// https://github.com/python/cpython/blob/master/Objects/typeobject.c#L3399-L3409
|
2020-05-06 18:11:29 +00:00
|
|
|
#[test]
|
2020-09-01 00:36:26 +00:00
|
|
|
#[ignore]
|
2020-05-06 18:11:29 +00:00
|
|
|
fn class_attributes_are_immutable() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
|
|
|
let foo_obj = py.get_type::<Foo>();
|
2020-07-04 15:55:26 +00:00
|
|
|
py_expect_exception!(py, foo_obj, "foo_obj.a = 6", PyTypeError);
|
2020-05-06 18:11:29 +00:00
|
|
|
}
|
2020-05-07 18:13:10 +00:00
|
|
|
|
2020-06-14 15:29:40 +00:00
|
|
|
#[pymethods]
|
2020-06-22 21:13:23 +00:00
|
|
|
impl Bar {
|
2020-06-14 15:29:40 +00:00
|
|
|
#[classattr]
|
2021-08-17 06:51:08 +00:00
|
|
|
fn a_foo() -> Foo {
|
2020-06-22 21:13:23 +00:00
|
|
|
Foo { x: 3 }
|
|
|
|
}
|
2020-06-14 15:29:40 +00:00
|
|
|
}
|
|
|
|
|
2020-05-07 18:13:10 +00:00
|
|
|
#[test]
|
|
|
|
fn recursive_class_attributes() {
|
|
|
|
let gil = Python::acquire_gil();
|
|
|
|
let py = gil.python();
|
2020-06-14 15:29:40 +00:00
|
|
|
|
2020-06-22 21:13:23 +00:00
|
|
|
let foo_obj = py.get_type::<Foo>();
|
|
|
|
let bar_obj = py.get_type::<Bar>();
|
2021-08-17 06:51:08 +00:00
|
|
|
py_assert!(py, foo_obj, "foo_obj.a_foo.x == 1");
|
2020-06-22 21:13:23 +00:00
|
|
|
py_assert!(py, foo_obj, "foo_obj.bar.x == 2");
|
2021-08-17 06:51:08 +00:00
|
|
|
py_assert!(py, bar_obj, "bar_obj.a_foo.x == 3");
|
2020-05-07 18:13:10 +00:00
|
|
|
}
|