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 fn py_new(py: Python<'_>, data_type: DataType, data: &Bound<'_, PyAny>) -> PyResult<Self> {
38 let type_name = data_type.type_name();
39 if let Some(arc) = try_extract_from_py(type_name, data) {
40 return Ok(Self::new(arc, data_type));
41 }
42 let wrapper = PythonCustomDataWrapper::new(py, data)?;
43 Ok(Self::new(std::sync::Arc::new(wrapper), data_type))
44 }
45
46 #[getter]
47 fn data(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
48 self.data.to_pyobject(py)
49 }
50
51 #[getter]
52 fn data_type(&self) -> DataType {
53 self.data_type.clone()
54 }
55
56 #[getter]
57 fn ts_event(&self) -> u64 {
58 self.data.ts_event().as_u64()
59 }
60
61 #[getter]
62 fn ts_init(&self) -> u64 {
63 self.data.ts_init().as_u64()
64 }
65
66 fn to_json_bytes(&self) -> PyResult<Vec<u8>> {
68 serde_json::to_vec(self).map_err(to_pyvalue_err)
69 }
70
71 #[expect(clippy::needless_pass_by_value)]
72 fn __richcmp__(
73 &self,
74 other: pyo3::Bound<'_, PyAny>,
75 op: CompareOp,
76 py: Python<'_>,
77 ) -> Py<PyAny> {
78 if let Ok(other) = other.extract::<Self>() {
79 match op {
80 CompareOp::Eq => self.eq(&other).into_py_any_unwrap(py),
81 CompareOp::Ne => self.ne(&other).into_py_any_unwrap(py),
82 _ => py.NotImplemented(),
83 }
84 } else {
85 py.NotImplemented()
86 }
87 }
88
89 fn __repr__(&self) -> String {
90 let type_name = self.data_type.type_name();
91 let id = self
92 .data_type
93 .identifier()
94 .map(|s| format!(", identifier={s:?}"))
95 .unwrap_or_default();
96 format!(
97 "CustomData(data_type={type_name:?}{id}, ts_event={}, ts_init={})",
98 self.data.ts_event().as_u64(),
99 self.data.ts_init().as_u64()
100 )
101 }
102}
103
104#[pymethods]
105impl CustomData {
106 #[classmethod]
108 #[pyo3(name = "from_json_bytes")]
109 fn py_from_json_bytes_py(
110 _cls: pyo3::Bound<'_, pyo3::types::PyType>,
111 bytes: &[u8],
112 ) -> PyResult<Self> {
113 parse_custom_data_from_json_bytes(bytes).map_err(to_pyvalue_err)
114 }
115}
116
117#[pyfunction]
118#[pyo3_stub_gen::derive::gen_stub_pyfunction(module = "nautilus_trader.model")]
119#[must_use]
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}