Skip to main content

graphrecords_python/graphrecord/
overview.rs

1use std::collections::HashMap;
2
3use crate::graphrecord::{
4    attribute::PyGraphRecordAttribute,
5    datatype::PyDataType,
6    schema::PyAttributeType,
7    traits::{DeepFrom, DeepInto},
8    value::PyGraphRecordValue,
9};
10use graphrecords_core::graphrecord::overview::{
11    AttributeOverview, AttributeOverviewData, EdgeGroupOverview, GroupOverview, NodeGroupOverview,
12    Overview,
13};
14use pyo3::{prelude::*, types::PyDict};
15
16#[pyclass(frozen)]
17#[repr(transparent)]
18#[derive(Debug, Clone)]
19pub struct PyAttributeOverview(AttributeOverview);
20
21impl From<AttributeOverview> for PyAttributeOverview {
22    fn from(value: AttributeOverview) -> Self {
23        Self(value)
24    }
25}
26
27impl From<PyAttributeOverview> for AttributeOverview {
28    fn from(value: PyAttributeOverview) -> Self {
29        value.0
30    }
31}
32
33impl DeepFrom<AttributeOverview> for PyAttributeOverview {
34    fn deep_from(value: AttributeOverview) -> Self {
35        value.into()
36    }
37}
38
39impl DeepFrom<PyAttributeOverview> for AttributeOverview {
40    fn deep_from(value: PyAttributeOverview) -> Self {
41        value.into()
42    }
43}
44
45impl AsRef<AttributeOverview> for PyAttributeOverview {
46    fn as_ref(&self) -> &AttributeOverview {
47        &self.0
48    }
49}
50
51#[pymethods]
52impl PyAttributeOverview {
53    #[getter]
54    pub fn data_type(&self) -> PyDataType {
55        self.0.data_type.clone().into()
56    }
57
58    #[getter]
59    #[allow(clippy::missing_panics_doc)]
60    pub fn data(&self, py: Python<'_>) -> Py<PyAny> {
61        let dict = PyDict::new(py);
62
63        match &self.0.data {
64            AttributeOverviewData::Categorical { distinct_values } => {
65                let distinct_values: Vec<PyGraphRecordValue> = distinct_values.clone().deep_into();
66
67                dict.set_item("distinct_values", distinct_values)
68                    .expect("Setting item must succeed");
69                dict.set_item("attribute_type", PyAttributeType::Categorical)
70                    .expect("Setting item must succeed");
71
72                dict.into_pyobject(py)
73                    .expect("Conversion must succeed")
74                    .into()
75            }
76            AttributeOverviewData::Continuous { min, mean, max } => {
77                dict.set_item("min", PyGraphRecordValue::from(min.clone()))
78                    .expect("Setting item must succeed");
79                dict.set_item("mean", PyGraphRecordValue::from(mean.clone()))
80                    .expect("Setting item must succeed");
81                dict.set_item("max", PyGraphRecordValue::from(max.clone()))
82                    .expect("Setting item must succeed");
83                dict.set_item("attribute_type", PyAttributeType::Continuous)
84                    .expect("Setting item must succeed");
85
86                dict.into()
87            }
88            AttributeOverviewData::Temporal { min, max } => {
89                dict.set_item("min", PyGraphRecordValue::from(min.clone()))
90                    .expect("Setting item must succeed");
91                dict.set_item("max", PyGraphRecordValue::from(max.clone()))
92                    .expect("Setting item must succeed");
93                dict.set_item("attribute_type", PyAttributeType::Temporal)
94                    .expect("Setting item must succeed");
95
96                dict.into()
97            }
98            AttributeOverviewData::Unstructured { distinct_count } => {
99                dict.set_item("distinct_count", *distinct_count)
100                    .expect("Setting item must succeed");
101                dict.set_item("attribute_type", PyAttributeType::Unstructured)
102                    .expect("Setting item must succeed");
103
104                dict.into()
105            }
106        }
107    }
108}
109
110#[pyclass(frozen)]
111#[repr(transparent)]
112#[derive(Debug, Clone)]
113pub struct PyNodeGroupOverview(NodeGroupOverview);
114
115impl From<NodeGroupOverview> for PyNodeGroupOverview {
116    fn from(value: NodeGroupOverview) -> Self {
117        Self(value)
118    }
119}
120
121impl From<PyNodeGroupOverview> for NodeGroupOverview {
122    fn from(value: PyNodeGroupOverview) -> Self {
123        value.0
124    }
125}
126
127impl DeepFrom<NodeGroupOverview> for PyNodeGroupOverview {
128    fn deep_from(value: NodeGroupOverview) -> Self {
129        value.into()
130    }
131}
132
133impl DeepFrom<PyNodeGroupOverview> for NodeGroupOverview {
134    fn deep_from(value: PyNodeGroupOverview) -> Self {
135        value.into()
136    }
137}
138
139impl AsRef<NodeGroupOverview> for PyNodeGroupOverview {
140    fn as_ref(&self) -> &NodeGroupOverview {
141        &self.0
142    }
143}
144
145#[pymethods]
146impl PyNodeGroupOverview {
147    #[getter]
148    pub const fn count(&self) -> usize {
149        self.0.count
150    }
151
152    #[getter]
153    pub fn attributes(&self) -> HashMap<PyGraphRecordAttribute, PyAttributeOverview> {
154        self.0.attributes.clone().deep_into()
155    }
156
157    pub fn __repr__(&self) -> PyResult<String> {
158        Ok(format!("{}", self.0))
159    }
160}
161
162#[pyclass(frozen)]
163#[repr(transparent)]
164#[derive(Debug, Clone)]
165pub struct PyEdgeGroupOverview(EdgeGroupOverview);
166
167impl From<EdgeGroupOverview> for PyEdgeGroupOverview {
168    fn from(value: EdgeGroupOverview) -> Self {
169        Self(value)
170    }
171}
172
173impl From<PyEdgeGroupOverview> for EdgeGroupOverview {
174    fn from(value: PyEdgeGroupOverview) -> Self {
175        value.0
176    }
177}
178
179impl DeepFrom<EdgeGroupOverview> for PyEdgeGroupOverview {
180    fn deep_from(value: EdgeGroupOverview) -> Self {
181        value.into()
182    }
183}
184
185impl DeepFrom<PyEdgeGroupOverview> for EdgeGroupOverview {
186    fn deep_from(value: PyEdgeGroupOverview) -> Self {
187        value.into()
188    }
189}
190
191impl AsRef<EdgeGroupOverview> for PyEdgeGroupOverview {
192    fn as_ref(&self) -> &EdgeGroupOverview {
193        &self.0
194    }
195}
196
197#[pymethods]
198impl PyEdgeGroupOverview {
199    #[getter]
200    pub const fn count(&self) -> usize {
201        self.0.count
202    }
203
204    #[getter]
205    pub fn attributes(&self) -> HashMap<PyGraphRecordAttribute, PyAttributeOverview> {
206        self.0
207            .attributes
208            .iter()
209            .map(|(k, v)| (k.clone().into(), v.clone().into()))
210            .collect()
211    }
212
213    pub fn __repr__(&self) -> PyResult<String> {
214        Ok(format!("{}", self.0))
215    }
216}
217
218#[pyclass(frozen)]
219#[repr(transparent)]
220#[derive(Debug, Clone)]
221pub struct PyGroupOverview(GroupOverview);
222
223impl From<GroupOverview> for PyGroupOverview {
224    fn from(value: GroupOverview) -> Self {
225        Self(value)
226    }
227}
228
229impl From<PyGroupOverview> for GroupOverview {
230    fn from(value: PyGroupOverview) -> Self {
231        value.0
232    }
233}
234
235impl DeepFrom<GroupOverview> for PyGroupOverview {
236    fn deep_from(value: GroupOverview) -> Self {
237        value.into()
238    }
239}
240
241impl DeepFrom<PyGroupOverview> for GroupOverview {
242    fn deep_from(value: PyGroupOverview) -> Self {
243        value.into()
244    }
245}
246
247impl AsRef<GroupOverview> for PyGroupOverview {
248    fn as_ref(&self) -> &GroupOverview {
249        &self.0
250    }
251}
252
253#[pymethods]
254impl PyGroupOverview {
255    #[getter]
256    pub fn node_overview(&self) -> PyNodeGroupOverview {
257        self.0.node_overview.clone().into()
258    }
259
260    #[getter]
261    pub fn edge_overview(&self) -> PyEdgeGroupOverview {
262        self.0.edge_overview.clone().into()
263    }
264
265    pub fn __repr__(&self) -> PyResult<String> {
266        Ok(format!("{}", self.0))
267    }
268}
269
270#[pyclass(frozen)]
271#[repr(transparent)]
272#[derive(Debug, Clone)]
273pub struct PyOverview(Overview);
274
275impl From<Overview> for PyOverview {
276    fn from(value: Overview) -> Self {
277        Self(value)
278    }
279}
280
281impl From<PyOverview> for Overview {
282    fn from(value: PyOverview) -> Self {
283        value.0
284    }
285}
286
287impl AsRef<Overview> for PyOverview {
288    fn as_ref(&self) -> &Overview {
289        &self.0
290    }
291}
292
293#[pymethods]
294impl PyOverview {
295    #[getter]
296    pub fn ungrouped_overview(&self) -> PyGroupOverview {
297        self.0.ungrouped_overview.clone().into()
298    }
299
300    #[getter]
301    pub fn grouped_overviews(&self) -> HashMap<PyGraphRecordAttribute, PyGroupOverview> {
302        self.0.grouped_overviews.clone().deep_into()
303    }
304
305    pub fn __repr__(&self) -> PyResult<String> {
306        Ok(format!("{}", self.0))
307    }
308}