Skip to main content

graphrecords_python/graphrecord/
overview.rs

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