| @@ -2139,16 +2139,6 @@ dependencies = [ | |||||
| "syn 1.0.109", | "syn 1.0.109", | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "derive" | |||||
| version = "0.1.0" | |||||
| dependencies = [ | |||||
| "proc-macro2", | |||||
| "quote", | |||||
| "quote_into", | |||||
| "syn 1.0.109", | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "digest" | name = "digest" | ||||
| version = "0.10.7" | version = "0.10.7" | ||||
| @@ -2456,7 +2446,6 @@ name = "dora-node-api-python" | |||||
| version = "0.3.4" | version = "0.3.4" | ||||
| dependencies = [ | dependencies = [ | ||||
| "arrow", | "arrow", | ||||
| "derive", | |||||
| "dora-node-api", | "dora-node-api", | ||||
| "dora-operator-api-python", | "dora-operator-api-python", | ||||
| "dora-ros2-bridge-python", | "dora-ros2-bridge-python", | ||||
| @@ -2465,6 +2454,7 @@ dependencies = [ | |||||
| "flume 0.10.14", | "flume 0.10.14", | ||||
| "futures", | "futures", | ||||
| "pyo3", | "pyo3", | ||||
| "python_special_method_derive", | |||||
| "pythonize", | "pythonize", | ||||
| "serde_yaml 0.8.26", | "serde_yaml 0.8.26", | ||||
| ] | ] | ||||
| @@ -6507,6 +6497,7 @@ dependencies = [ | |||||
| "cfg-if 1.0.0", | "cfg-if 1.0.0", | ||||
| "eyre", | "eyre", | ||||
| "indoc", | "indoc", | ||||
| "inventory", | |||||
| "libc", | "libc", | ||||
| "memoffset 0.9.1", | "memoffset 0.9.1", | ||||
| "parking_lot", | "parking_lot", | ||||
| @@ -6563,6 +6554,17 @@ dependencies = [ | |||||
| "syn 2.0.65", | "syn 2.0.65", | ||||
| ] | ] | ||||
| [[package]] | |||||
| name = "python_special_method_derive" | |||||
| version = "0.1.0" | |||||
| dependencies = [ | |||||
| "proc-macro2", | |||||
| "pyo3", | |||||
| "quote", | |||||
| "quote_into", | |||||
| "syn 1.0.109", | |||||
| ] | |||||
| [[package]] | [[package]] | ||||
| name = "pythonize" | name = "pythonize" | ||||
| version = "0.21.1" | version = "0.21.1" | ||||
| @@ -34,7 +34,7 @@ members = [ | |||||
| "libraries/extensions/ros2-bridge", | "libraries/extensions/ros2-bridge", | ||||
| "libraries/extensions/ros2-bridge/msg-gen", | "libraries/extensions/ros2-bridge/msg-gen", | ||||
| "libraries/extensions/ros2-bridge/python", | "libraries/extensions/ros2-bridge/python", | ||||
| "derive", | |||||
| "python_special_method_derive", | |||||
| ] | ] | ||||
| [workspace.package] | [workspace.package] | ||||
| @@ -67,12 +67,12 @@ dora-coordinator = { version = "0.3.4", path = "binaries/coordinator" } | |||||
| dora-ros2-bridge = { path = "libraries/extensions/ros2-bridge" } | dora-ros2-bridge = { path = "libraries/extensions/ros2-bridge" } | ||||
| dora-ros2-bridge-msg-gen = { path = "libraries/extensions/ros2-bridge/msg-gen" } | dora-ros2-bridge-msg-gen = { path = "libraries/extensions/ros2-bridge/msg-gen" } | ||||
| dora-ros2-bridge-python = { path = "libraries/extensions/ros2-bridge/python" } | dora-ros2-bridge-python = { path = "libraries/extensions/ros2-bridge/python" } | ||||
| derive = { path = "derive" } | |||||
| python_special_method_derive = { path = "python_special_method_derive" } | |||||
| arrow = { version = "52" } | arrow = { version = "52" } | ||||
| arrow-schema = { version = "52" } | arrow-schema = { version = "52" } | ||||
| arrow-data = { version = "52" } | arrow-data = { version = "52" } | ||||
| arrow-array = { version = "52" } | arrow-array = { version = "52" } | ||||
| pyo3 = "0.21" | |||||
| pyo3 = { version = "0.21", workspace = true, features = ["eyre", "abi3-py37", "multiple-pymethods"] } | |||||
| pythonize = "0.21" | pythonize = "0.21" | ||||
| [package] | [package] | ||||
| @@ -16,7 +16,7 @@ telemetry = ["dora-runtime/telemetry"] | |||||
| [dependencies] | [dependencies] | ||||
| dora-node-api = { workspace = true } | dora-node-api = { workspace = true } | ||||
| dora-operator-api-python = { workspace = true } | dora-operator-api-python = { workspace = true } | ||||
| pyo3 = { workspace = true, features = ["eyre", "abi3-py37"] } | |||||
| pyo3.workspace = true | |||||
| eyre = "0.6" | eyre = "0.6" | ||||
| serde_yaml = "0.8.23" | serde_yaml = "0.8.23" | ||||
| flume = "0.10.14" | flume = "0.10.14" | ||||
| @@ -25,7 +25,7 @@ arrow = { workspace = true, features = ["pyarrow"] } | |||||
| pythonize = { workspace = true } | pythonize = { workspace = true } | ||||
| futures = "0.3.28" | futures = "0.3.28" | ||||
| dora-ros2-bridge-python = { workspace = true } | dora-ros2-bridge-python = { workspace = true } | ||||
| derive = { workspace = true } | |||||
| python_special_method_derive = { workspace = true } | |||||
| [lib] | [lib] | ||||
| name = "dora" | name = "dora" | ||||
| @@ -24,7 +24,7 @@ use pyo3::types::{PyBytes, PyDict}; | |||||
| /// ``` | /// ``` | ||||
| /// | /// | ||||
| #[pyclass] | #[pyclass] | ||||
| #[derive(derive::DirHelper)] | |||||
| #[derive(python_special_method_derive::DirHelper)] | |||||
| pub struct Node { | pub struct Node { | ||||
| events: Events, | events: Events, | ||||
| node: DoraNode, | node: DoraNode, | ||||
| @@ -198,13 +198,6 @@ impl Node { | |||||
| Ok(()) | Ok(()) | ||||
| } | } | ||||
| // TODO: We should only list fields which are at least readableby Python users, right? | |||||
| /// Get a list of the fields of this Node. | |||||
| pub fn __dir__(&self) -> Vec<String> { | |||||
| self.fields() | |||||
| } | |||||
| } | } | ||||
| enum Events { | enum Events { | ||||
| @@ -1,5 +1,5 @@ | |||||
| [package] | [package] | ||||
| name = "derive" | |||||
| name = "python_special_method_derive" | |||||
| version = "0.1.0" | version = "0.1.0" | ||||
| edition = "2021" | edition = "2021" | ||||
| @@ -8,6 +8,7 @@ syn = "1.0" | |||||
| quote = "1.0" | quote = "1.0" | ||||
| proc-macro2 = "1.0" | proc-macro2 = "1.0" | ||||
| quote_into = "0.2.0" | quote_into = "0.2.0" | ||||
| pyo3.workspace = true | |||||
| [lib] | [lib] | ||||
| proc-macro = true | proc-macro = true | ||||
| @@ -5,6 +5,8 @@ use proc_macro::TokenStream; | |||||
| use quote::quote; | use quote::quote; | ||||
| use syn::{parse_macro_input, Data, DeriveInput, Fields}; | use syn::{parse_macro_input, Data, DeriveInput, Fields}; | ||||
| // TODO: We should only list fields which are at least readableby Python users, right? | |||||
| /// Add a `fields` method to the struct. | /// Add a `fields` method to the struct. | ||||
| /// | /// | ||||
| /// Because we cannot have multiple `#[pymethods]` impls, this macro | /// Because we cannot have multiple `#[pymethods]` impls, this macro | ||||
| @@ -37,8 +39,9 @@ pub fn dir_helper_derive(input: TokenStream) -> TokenStream { | |||||
| } | } | ||||
| }];); | }];); | ||||
| quote! { | quote! { | ||||
| #[pyo3::pymethods] | |||||
| impl #name { | impl #name { | ||||
| pub fn fields(&self) -> Vec<String> { | |||||
| pub fn __dir__(&self) -> Vec<String> { | |||||
| let mut names = Vec::new(); | let mut names = Vec::new(); | ||||
| #assigner | #assigner | ||||
| names | names | ||||
| @@ -49,8 +52,9 @@ pub fn dir_helper_derive(input: TokenStream) -> TokenStream { | |||||
| Fields::Unit => { | Fields::Unit => { | ||||
| // If the struct has no fields | // If the struct has no fields | ||||
| quote! { | quote! { | ||||
| #[pyo3::pymethods] | |||||
| impl #name { | impl #name { | ||||
| pub fn fields(&self) -> Vec<String> { | |||||
| pub fn __dir__(&self) -> Vec<String> { | |||||
| Vec::new() | Vec::new() | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,5 +1,7 @@ | |||||
| use derive::DirHelper; | |||||
| use pyo3::pyclass; | |||||
| use python_special_method_derive::DirHelper; | |||||
| #[pyclass] | |||||
| #[derive(DirHelper)] | #[derive(DirHelper)] | ||||
| #[allow(dead_code)] | #[allow(dead_code)] | ||||
| struct WithFields { | struct WithFields { | ||||
| @@ -17,7 +19,7 @@ fn test_with_fields() { | |||||
| my: "".to_string(), | my: "".to_string(), | ||||
| name: 0.0, | name: 0.0, | ||||
| } | } | ||||
| .fields(); | |||||
| .__dir__(); | |||||
| assert_eq!( | assert_eq!( | ||||
| vec![ | vec![ | ||||
| "hello".to_string(), | "hello".to_string(), | ||||
| @@ -29,12 +31,13 @@ fn test_with_fields() { | |||||
| ); | ); | ||||
| } | } | ||||
| #[pyclass] | |||||
| #[derive(DirHelper)] | #[derive(DirHelper)] | ||||
| #[allow(dead_code)] | #[allow(dead_code)] | ||||
| struct UnitNoFields; | struct UnitNoFields; | ||||
| #[test] | #[test] | ||||
| fn test_no_fields() { | fn test_no_fields() { | ||||
| let fields: Vec<String> = UnitNoFields.fields(); | |||||
| let fields: Vec<String> = UnitNoFields.__dir__(); | |||||
| assert_eq!(Vec::<String>::new(), fields); | assert_eq!(Vec::<String>::new(), fields); | ||||
| } | } | ||||