nautilus_model/python/data/
custom.rs1use nautilus_core::python::{IntoPyObjectNautilusExt, to_pyvalue_err};
19use pyo3::{basic::CompareOp, prelude::*, types::PyAny};
20
21use crate::data::{
22 CustomData, DataType,
23 custom::{PythonCustomDataWrapper, parse_custom_data_from_json_bytes},
24 registry::try_extract_from_py,
25};
26
27#[pymethods]
28#[pyo3_stub_gen::derive::gen_stub_pymethods]
29impl CustomData {
30 #[new]
36 #[pyo3(signature = (data_type, data))]
37 #[allow(clippy::needless_pass_by_value)]
38 fn py_new(py: Python<'_>, data_type: DataType, data: &Bound<'_, PyAny>) -> PyResult<Self> {
39 let type_name = data_type.type_name();
40 if let Some(arc) = try_extract_from_py(type_name, data) {
41 return Ok(Self::new(arc, data_type));
42 }
43 let wrapper = PythonCustomDataWrapper::new(py, data)?;
44 Ok(Self::new(std::sync::Arc::new(wrapper), data_type))
45 }
46
47 #[getter]
48 fn data(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
49 self.data.to_pyobject(py)
50 }
51
52 #[getter]
53 fn data_type(&self) -> DataType {
54 self.data_type.clone()
55 }
56
57 #[getter]
58 fn ts_event(&self) -> u64 {
59 self.data.ts_event().as_u64()
60 }
61
62 #[getter]
63 fn ts_init(&self) -> u64 {
64 self.data.ts_init().as_u64()
65 }
66
67 fn to_json_bytes(&self) -> PyResult<Vec<u8>> {
69 serde_json::to_vec(self).map_err(to_pyvalue_err)
70 }
71
72 #[allow(clippy::needless_pass_by_value)]
73 fn __richcmp__(
74 &self,
75 other: pyo3::Bound<'_, PyAny>,
76 op: CompareOp,
77 py: Python<'_>,
78 ) -> Py<PyAny> {
79 if let Ok(other) = other.extract::<Self>() {
80 match op {
81 CompareOp::Eq => self.eq(&other).into_py_any_unwrap(py),
82 CompareOp::Ne => self.ne(&other).into_py_any_unwrap(py),
83 _ => py.NotImplemented(),
84 }
85 } else {
86 py.NotImplemented()
87 }
88 }
89
90 fn __repr__(&self) -> String {
91 let type_name = self.data_type.type_name();
92 let id = self
93 .data_type
94 .identifier()
95 .map(|s| format!(", identifier={s:?}"))
96 .unwrap_or_default();
97 format!(
98 "CustomData(data_type={type_name:?}{id}, ts_event={}, ts_init={})",
99 self.data.ts_event().as_u64(),
100 self.data.ts_init().as_u64()
101 )
102 }
103}
104
105#[pymethods]
106impl CustomData {
107 #[classmethod]
109 #[pyo3(name = "from_json_bytes")]
110 fn py_from_json_bytes_py(
111 _cls: pyo3::Bound<'_, pyo3::types::PyType>,
112 bytes: &[u8],
113 ) -> PyResult<Self> {
114 parse_custom_data_from_json_bytes(bytes).map_err(to_pyvalue_err)
115 }
116}
117
118#[pyfunction]
119#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.model")]
120pub fn custom_data_backend_kind(custom: &CustomData) -> &'static str {
121 if custom
122 .data
123 .as_any()
124 .downcast_ref::<PythonCustomDataWrapper>()
125 .is_some()
126 {
127 "python"
128 } else {
129 "native"
130 }
131}