nautilus_trading/python/
controller.rs1use std::collections::HashMap;
17
18use nautilus_core::python::to_pyvalue_err;
19use pyo3::{
20 prelude::*,
21 types::{PyDict, PyDictMethods, PyModule},
22};
23
24use crate::ImportableControllerConfig;
25
26#[pyo3::pymethods]
27#[pyo3_stub_gen::derive::gen_stub_pymethods]
28impl ImportableControllerConfig {
29 #[new]
31 #[expect(clippy::needless_pass_by_value)]
32 fn py_new(controller_path: String, config_path: String, config: Py<PyDict>) -> PyResult<Self> {
33 let json_config = Python::attach(|py| -> PyResult<HashMap<String, serde_json::Value>> {
34 let kwargs = PyDict::new(py);
35 kwargs.set_item("default", py.eval(pyo3::ffi::c_str!("str"), None, None)?)?;
36 let json_str: String = PyModule::import(py, "json")?
37 .call_method("dumps", (config.bind(py),), Some(&kwargs))?
38 .extract()?;
39
40 let json_value: serde_json::Value =
41 serde_json::from_str(&json_str).map_err(to_pyvalue_err)?;
42
43 if let serde_json::Value::Object(map) = json_value {
44 Ok(map.into_iter().collect())
45 } else {
46 Err(to_pyvalue_err("Config must be a dictionary"))
47 }
48 })?;
49
50 Ok(Self {
51 controller_path,
52 config_path,
53 config: json_config,
54 })
55 }
56
57 #[getter]
58 fn controller_path(&self) -> &String {
59 &self.controller_path
60 }
61
62 #[getter]
63 fn config_path(&self) -> &String {
64 &self.config_path
65 }
66
67 #[getter]
68 fn config(&self, py: Python<'_>) -> PyResult<Py<PyDict>> {
69 let py_dict = PyDict::new(py);
70
71 for (key, value) in &self.config {
72 let json_str = serde_json::to_string(value).map_err(to_pyvalue_err)?;
73 let py_value = PyModule::import(py, "json")?.call_method("loads", (json_str,), None)?;
74 py_dict.set_item(key, py_value)?;
75 }
76 Ok(py_dict.unbind())
77 }
78}