Skip to main content

graphrecords_python/graphrecord/
plugins.rs

1use crate::{
2    graphrecord::traits::DeepInto,
3    prelude::{PyAttributes, PyGraphRecord, PyGroup, PyNodeIndex, PySchema},
4};
5use graphrecords_core::{
6    errors::{GraphRecordError, GraphRecordResult},
7    graphrecord::{
8        EdgeDataFrameInput, EdgeIndex, GraphRecord, NodeDataFrameInput,
9        plugins::{
10            Plugin, PostAddEdgeContext, PostAddEdgeToGroupContext, PostAddEdgeWithGroupContext,
11            PostAddEdgesContext, PostAddEdgesDataframesContext,
12            PostAddEdgesDataframesWithGroupContext, PostAddEdgesWithGroupContext,
13            PostAddGroupContext, PostAddNodeContext, PostAddNodeToGroupContext,
14            PostAddNodeWithGroupContext, PostAddNodesContext, PostAddNodesDataframesContext,
15            PostAddNodesDataframesWithGroupContext, PostAddNodesWithGroupContext,
16            PostRemoveEdgeContext, PostRemoveEdgeFromGroupContext, PostRemoveGroupContext,
17            PostRemoveNodeContext, PostRemoveNodeFromGroupContext, PreAddEdgeContext,
18            PreAddEdgeToGroupContext, PreAddEdgeWithGroupContext, PreAddEdgesContext,
19            PreAddEdgesDataframesContext, PreAddEdgesDataframesWithGroupContext,
20            PreAddEdgesWithGroupContext, PreAddGroupContext, PreAddNodeContext,
21            PreAddNodeToGroupContext, PreAddNodeWithGroupContext, PreAddNodesContext,
22            PreAddNodesDataframesContext, PreAddNodesDataframesWithGroupContext,
23            PreAddNodesWithGroupContext, PreRemoveEdgeContext, PreRemoveEdgeFromGroupContext,
24            PreRemoveGroupContext, PreRemoveNodeContext, PreRemoveNodeFromGroupContext,
25            PreSetSchemaContext,
26        },
27    },
28};
29use pyo3::{IntoPyObjectExt, Py, PyAny, Python, pyclass, pymethods, types::PyAnyMethods};
30use pyo3_polars::PyDataFrame;
31use serde::{Deserialize, Deserializer, Serialize, Serializer};
32
33macro_rules! impl_pre_hook {
34    ($method:ident, $py_context_type:ident, $core_context_type:ident) => {
35        fn $method(
36            &self,
37            graphrecord: &mut GraphRecord,
38            context: $core_context_type,
39        ) -> GraphRecordResult<$core_context_type> {
40            Python::attach(|py| {
41                PyGraphRecord::scope_mut(py, graphrecord, |py, graphrecord| {
42                    let py_context = $py_context_type::bind(py, context);
43
44                    let result = self
45                        .0
46                        .call_method1(py, stringify!($method), (graphrecord, py_context))
47                        .map_err(|err| GraphRecordError::ConversionError(format!("{}", err)))?;
48
49                    Ok(result
50                        .extract::<$py_context_type>(py)
51                        .map_err(|err| GraphRecordError::ConversionError(format!("{}", err)))?
52                        .extract(py))
53                })
54            })
55        }
56    };
57}
58
59macro_rules! impl_post_hook {
60    ($method:ident) => {
61        fn $method(&self, graphrecord: &mut GraphRecord) -> GraphRecordResult<()> {
62            Python::attach(|py| {
63                PyGraphRecord::scope_mut(py, graphrecord, |py, graphrecord| {
64                    self.0
65                        .call_method1(py, stringify!($method), (graphrecord,))
66                        .map_err(|err| GraphRecordError::ConversionError(format!("{}", err)))?;
67
68                    Ok(())
69                })
70            })
71        }
72    };
73    ($method:ident, $py_context_type:ident, $core_context_type:ident) => {
74        fn $method(
75            &self,
76            graphrecord: &mut GraphRecord,
77            context: $core_context_type,
78        ) -> GraphRecordResult<()> {
79            Python::attach(|py| {
80                PyGraphRecord::scope_mut(py, graphrecord, |py, graphrecord| {
81                    let py_context = $py_context_type::bind(py, context);
82
83                    self.0
84                        .call_method1(py, stringify!($method), (graphrecord, py_context))
85                        .map_err(|err| GraphRecordError::ConversionError(format!("{}", err)))?;
86
87                    Ok(())
88                })
89            })
90        }
91    };
92}
93
94#[derive(Debug)]
95pub struct PyPlugin(Py<PyAny>);
96
97impl Serialize for PyPlugin {
98    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
99        Python::attach(|py| {
100            let cloudpickle = py
101                .import("cloudpickle")
102                .map_err(serde::ser::Error::custom)?;
103
104            let bytes: Vec<u8> = cloudpickle
105                .call_method1("dumps", (&self.0,))
106                .map_err(serde::ser::Error::custom)?
107                .extract()
108                .map_err(serde::ser::Error::custom)?;
109
110            serializer.serialize_bytes(&bytes)
111        })
112    }
113}
114
115impl<'de> Deserialize<'de> for PyPlugin {
116    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
117        let bytes: Vec<u8> = Deserialize::deserialize(deserializer)?;
118
119        Python::attach(|py| {
120            let cloudpickle = py.import("cloudpickle").map_err(serde::de::Error::custom)?;
121
122            let obj: Py<PyAny> = cloudpickle
123                .call_method1("loads", (bytes.as_slice(),))
124                .map_err(serde::de::Error::custom)?
125                .into();
126
127            Ok(Self(obj))
128        })
129    }
130}
131
132impl PyPlugin {
133    pub const fn new(py_obj: Py<PyAny>) -> Self {
134        Self(py_obj)
135    }
136}
137
138fn node_dataframe_inputs_to_py(inputs: Vec<NodeDataFrameInput>) -> Vec<(PyDataFrame, String)> {
139    inputs
140        .into_iter()
141        .map(|input| (PyDataFrame(input.dataframe), input.index_column))
142        .collect()
143}
144
145fn py_to_node_dataframe_inputs(inputs: Vec<(PyDataFrame, String)>) -> Vec<NodeDataFrameInput> {
146    inputs
147        .into_iter()
148        .map(|(dataframe, index_column)| NodeDataFrameInput {
149            dataframe: dataframe.0,
150            index_column,
151        })
152        .collect()
153}
154
155fn edge_dataframe_inputs_to_py(
156    inputs: Vec<EdgeDataFrameInput>,
157) -> Vec<(PyDataFrame, String, String)> {
158    inputs
159        .into_iter()
160        .map(|input| {
161            (
162                PyDataFrame(input.dataframe),
163                input.source_index_column,
164                input.target_index_column,
165            )
166        })
167        .collect()
168}
169
170fn py_to_edge_dataframe_inputs(
171    inputs: Vec<(PyDataFrame, String, String)>,
172) -> Vec<EdgeDataFrameInput> {
173    inputs
174        .into_iter()
175        .map(
176            |(dataframe, source_index_column, target_index_column)| EdgeDataFrameInput {
177                dataframe: dataframe.0,
178                source_index_column,
179                target_index_column,
180            },
181        )
182        .collect()
183}
184
185#[pyclass(frozen)]
186#[derive(Debug)]
187pub struct PyPreSetSchemaContext {
188    schema: Py<PySchema>,
189}
190
191impl Clone for PyPreSetSchemaContext {
192    fn clone(&self) -> Self {
193        Python::attach(|py| Self {
194            schema: self.schema.clone_ref(py),
195        })
196    }
197}
198
199impl PyPreSetSchemaContext {
200    /// # Panics
201    ///
202    /// Panics if the python typing was not followed.
203    pub fn bind(py: Python<'_>, context: PreSetSchemaContext) -> Self {
204        Self {
205            schema: Py::new(py, PySchema::from(context.schema))
206                .expect("PySchema should be creatable"),
207        }
208    }
209
210    /// # Panics
211    ///
212    /// Panics if the python typing was not followed.
213    pub fn extract(self, py: Python<'_>) -> PreSetSchemaContext {
214        let py_schema: PySchema = self
215            .schema
216            .extract(py)
217            .expect("PySchema should be extractable");
218
219        PreSetSchemaContext {
220            schema: py_schema.into(),
221        }
222    }
223}
224
225#[pymethods]
226impl PyPreSetSchemaContext {
227    #[new]
228    pub const fn new(schema: Py<PySchema>) -> Self {
229        Self { schema }
230    }
231
232    #[getter]
233    pub fn schema(&self, py: Python<'_>) -> Py<PySchema> {
234        self.schema.clone_ref(py)
235    }
236}
237
238#[pyclass(frozen)]
239#[derive(Debug)]
240pub struct PyPreAddNodeContext {
241    node_index: Py<PyAny>,
242    attributes: Py<PyAny>,
243}
244
245impl Clone for PyPreAddNodeContext {
246    fn clone(&self) -> Self {
247        Python::attach(|py| Self {
248            node_index: self.node_index.clone_ref(py),
249            attributes: self.attributes.clone_ref(py),
250        })
251    }
252}
253
254impl PyPreAddNodeContext {
255    /// # Panics
256    ///
257    /// Panics if the python typing was not followed.
258    pub fn bind(py: Python<'_>, context: PreAddNodeContext) -> Self {
259        Self {
260            node_index: PyNodeIndex::from(context.node_index)
261                .into_py_any(py)
262                .expect("PyNodeIndex should be creatable"),
263            attributes: {
264                let py_attrs: PyAttributes = context.attributes.deep_into();
265                py_attrs
266                    .into_py_any(py)
267                    .expect("PyAttributes should be creatable")
268            },
269        }
270    }
271
272    /// # Panics
273    ///
274    /// Panics if the python typing was not followed.
275    pub fn extract(self, py: Python<'_>) -> PreAddNodeContext {
276        let node_index: PyNodeIndex = self
277            .node_index
278            .extract(py)
279            .expect("PyNodeIndex should be extractable");
280
281        let attributes: PyAttributes = self
282            .attributes
283            .extract(py)
284            .expect("PyAttributes should be extractable");
285
286        PreAddNodeContext {
287            node_index: node_index.into(),
288            attributes: attributes.deep_into(),
289        }
290    }
291}
292
293#[pymethods]
294impl PyPreAddNodeContext {
295    #[new]
296    pub const fn new(node_index: Py<PyAny>, attributes: Py<PyAny>) -> Self {
297        Self {
298            node_index,
299            attributes,
300        }
301    }
302
303    #[getter]
304    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
305        self.node_index.clone_ref(py)
306    }
307
308    #[getter]
309    pub fn attributes(&self, py: Python<'_>) -> Py<PyAny> {
310        self.attributes.clone_ref(py)
311    }
312}
313
314#[pyclass(frozen)]
315#[derive(Debug)]
316pub struct PyPostAddNodeContext {
317    node_index: Py<PyAny>,
318}
319
320impl Clone for PyPostAddNodeContext {
321    fn clone(&self) -> Self {
322        Python::attach(|py| Self {
323            node_index: self.node_index.clone_ref(py),
324        })
325    }
326}
327
328impl PyPostAddNodeContext {
329    /// # Panics
330    ///
331    /// Panics if the python typing was not followed.
332    pub fn bind(py: Python<'_>, context: PostAddNodeContext) -> Self {
333        Self {
334            node_index: PyNodeIndex::from(context.node_index)
335                .into_py_any(py)
336                .expect("PyNodeIndex should be creatable"),
337        }
338    }
339}
340
341#[pymethods]
342impl PyPostAddNodeContext {
343    #[new]
344    pub const fn new(node_index: Py<PyAny>) -> Self {
345        Self { node_index }
346    }
347
348    #[getter]
349    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
350        self.node_index.clone_ref(py)
351    }
352}
353
354#[pyclass(frozen)]
355#[derive(Debug)]
356pub struct PyPreAddNodeWithGroupContext {
357    node_index: Py<PyAny>,
358    attributes: Py<PyAny>,
359    group: Py<PyAny>,
360}
361
362impl Clone for PyPreAddNodeWithGroupContext {
363    fn clone(&self) -> Self {
364        Python::attach(|py| Self {
365            node_index: self.node_index.clone_ref(py),
366            attributes: self.attributes.clone_ref(py),
367            group: self.group.clone_ref(py),
368        })
369    }
370}
371
372impl PyPreAddNodeWithGroupContext {
373    /// # Panics
374    ///
375    /// Panics if the python typing was not followed.
376    pub fn bind(py: Python<'_>, context: PreAddNodeWithGroupContext) -> Self {
377        Self {
378            node_index: PyNodeIndex::from(context.node_index)
379                .into_py_any(py)
380                .expect("PyNodeIndex should be creatable"),
381            attributes: {
382                let py_attrs: PyAttributes = context.attributes.deep_into();
383                py_attrs
384                    .into_py_any(py)
385                    .expect("PyAttributes should be creatable")
386            },
387            group: PyGroup::from(context.group)
388                .into_py_any(py)
389                .expect("PyGroup should be creatable"),
390        }
391    }
392
393    /// # Panics
394    ///
395    /// Panics if the python typing was not followed.
396    pub fn extract(self, py: Python<'_>) -> PreAddNodeWithGroupContext {
397        let node_index: PyNodeIndex = self
398            .node_index
399            .extract(py)
400            .expect("PyNodeIndex should be extractable");
401
402        let attributes: PyAttributes = self
403            .attributes
404            .extract(py)
405            .expect("PyAttributes should be extractable");
406
407        let group: PyGroup = self
408            .group
409            .extract(py)
410            .expect("PyGroup should be extractable");
411
412        PreAddNodeWithGroupContext {
413            node_index: node_index.into(),
414            attributes: attributes.deep_into(),
415            group: group.into(),
416        }
417    }
418}
419
420#[pymethods]
421impl PyPreAddNodeWithGroupContext {
422    #[new]
423    pub const fn new(node_index: Py<PyAny>, attributes: Py<PyAny>, group: Py<PyAny>) -> Self {
424        Self {
425            node_index,
426            attributes,
427            group,
428        }
429    }
430
431    #[getter]
432    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
433        self.node_index.clone_ref(py)
434    }
435
436    #[getter]
437    pub fn attributes(&self, py: Python<'_>) -> Py<PyAny> {
438        self.attributes.clone_ref(py)
439    }
440
441    #[getter]
442    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
443        self.group.clone_ref(py)
444    }
445}
446
447#[pyclass(frozen)]
448#[derive(Debug)]
449pub struct PyPostAddNodeWithGroupContext {
450    node_index: Py<PyAny>,
451    group: Py<PyAny>,
452}
453
454impl Clone for PyPostAddNodeWithGroupContext {
455    fn clone(&self) -> Self {
456        Python::attach(|py| Self {
457            node_index: self.node_index.clone_ref(py),
458            group: self.group.clone_ref(py),
459        })
460    }
461}
462
463impl PyPostAddNodeWithGroupContext {
464    /// # Panics
465    ///
466    /// Panics if the python typing was not followed.
467    pub fn bind(py: Python<'_>, context: PostAddNodeWithGroupContext) -> Self {
468        Self {
469            node_index: PyNodeIndex::from(context.node_index)
470                .into_py_any(py)
471                .expect("PyNodeIndex should be creatable"),
472            group: PyGroup::from(context.group)
473                .into_py_any(py)
474                .expect("PyGroup should be creatable"),
475        }
476    }
477}
478
479#[pymethods]
480impl PyPostAddNodeWithGroupContext {
481    #[new]
482    pub const fn new(node_index: Py<PyAny>, group: Py<PyAny>) -> Self {
483        Self { node_index, group }
484    }
485
486    #[getter]
487    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
488        self.node_index.clone_ref(py)
489    }
490
491    #[getter]
492    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
493        self.group.clone_ref(py)
494    }
495}
496
497#[pyclass(frozen)]
498#[derive(Debug)]
499pub struct PyPreRemoveNodeContext {
500    node_index: Py<PyAny>,
501}
502
503impl Clone for PyPreRemoveNodeContext {
504    fn clone(&self) -> Self {
505        Python::attach(|py| Self {
506            node_index: self.node_index.clone_ref(py),
507        })
508    }
509}
510
511impl PyPreRemoveNodeContext {
512    /// # Panics
513    ///
514    /// Panics if the python typing was not followed.
515    pub fn bind(py: Python<'_>, context: PreRemoveNodeContext) -> Self {
516        Self {
517            node_index: PyNodeIndex::from(context.node_index)
518                .into_py_any(py)
519                .expect("PyNodeIndex should be creatable"),
520        }
521    }
522
523    /// # Panics
524    ///
525    /// Panics if the python typing was not followed.
526    pub fn extract(self, py: Python<'_>) -> PreRemoveNodeContext {
527        let py_node_index: PyNodeIndex = self
528            .node_index
529            .extract(py)
530            .expect("PyNodeIndex should be extractable");
531
532        PreRemoveNodeContext {
533            node_index: py_node_index.into(),
534        }
535    }
536}
537
538#[pymethods]
539impl PyPreRemoveNodeContext {
540    #[new]
541    pub const fn new(node_index: Py<PyAny>) -> Self {
542        Self { node_index }
543    }
544
545    #[getter]
546    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
547        self.node_index.clone_ref(py)
548    }
549}
550
551#[pyclass(frozen)]
552#[derive(Debug)]
553pub struct PyPostRemoveNodeContext {
554    node_index: Py<PyAny>,
555}
556
557impl Clone for PyPostRemoveNodeContext {
558    fn clone(&self) -> Self {
559        Python::attach(|py| Self {
560            node_index: self.node_index.clone_ref(py),
561        })
562    }
563}
564
565impl PyPostRemoveNodeContext {
566    /// # Panics
567    ///
568    /// Panics if the python typing was not followed.
569    pub fn bind(py: Python<'_>, context: PostRemoveNodeContext) -> Self {
570        Self {
571            node_index: PyNodeIndex::from(context.node_index)
572                .into_py_any(py)
573                .expect("PyNodeIndex should be creatable"),
574        }
575    }
576}
577
578#[pymethods]
579impl PyPostRemoveNodeContext {
580    #[new]
581    pub const fn new(node_index: Py<PyAny>) -> Self {
582        Self { node_index }
583    }
584
585    #[getter]
586    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
587        self.node_index.clone_ref(py)
588    }
589}
590
591#[pyclass(frozen)]
592#[derive(Debug)]
593pub struct PyPreAddNodesContext {
594    nodes: Py<PyAny>,
595}
596
597impl Clone for PyPreAddNodesContext {
598    fn clone(&self) -> Self {
599        Python::attach(|py| Self {
600            nodes: self.nodes.clone_ref(py),
601        })
602    }
603}
604
605impl PyPreAddNodesContext {
606    /// # Panics
607    ///
608    /// Panics if the python typing was not followed.
609    pub fn bind(py: Python<'_>, context: PreAddNodesContext) -> Self {
610        let nodes: Vec<(PyNodeIndex, PyAttributes)> = context.nodes.deep_into();
611
612        Self {
613            nodes: nodes.into_py_any(py).expect("nodes should be creatable"),
614        }
615    }
616
617    /// # Panics
618    ///
619    /// Panics if the python typing was not followed.
620    pub fn extract(self, py: Python<'_>) -> PreAddNodesContext {
621        let nodes: Vec<(PyNodeIndex, PyAttributes)> =
622            self.nodes.extract(py).expect("nodes should be extractable");
623
624        PreAddNodesContext {
625            nodes: nodes.deep_into(),
626        }
627    }
628}
629
630#[pymethods]
631impl PyPreAddNodesContext {
632    #[new]
633    pub const fn new(nodes: Py<PyAny>) -> Self {
634        Self { nodes }
635    }
636
637    #[getter]
638    pub fn nodes(&self, py: Python<'_>) -> Py<PyAny> {
639        self.nodes.clone_ref(py)
640    }
641}
642
643#[pyclass(frozen)]
644#[derive(Debug)]
645pub struct PyPostAddNodesContext {
646    nodes: Py<PyAny>,
647}
648
649impl Clone for PyPostAddNodesContext {
650    fn clone(&self) -> Self {
651        Python::attach(|py| Self {
652            nodes: self.nodes.clone_ref(py),
653        })
654    }
655}
656
657impl PyPostAddNodesContext {
658    /// # Panics
659    ///
660    /// Panics if the python typing was not followed.
661    pub fn bind(py: Python<'_>, context: PostAddNodesContext) -> Self {
662        let nodes: Vec<(PyNodeIndex, PyAttributes)> = context.nodes.deep_into();
663
664        Self {
665            nodes: nodes.into_py_any(py).expect("nodes should be creatable"),
666        }
667    }
668}
669
670#[pymethods]
671impl PyPostAddNodesContext {
672    #[new]
673    pub const fn new(nodes: Py<PyAny>) -> Self {
674        Self { nodes }
675    }
676
677    #[getter]
678    pub fn nodes(&self, py: Python<'_>) -> Py<PyAny> {
679        self.nodes.clone_ref(py)
680    }
681}
682
683#[pyclass(frozen)]
684#[derive(Debug)]
685pub struct PyPreAddNodesWithGroupContext {
686    nodes: Py<PyAny>,
687    group: Py<PyAny>,
688}
689
690impl Clone for PyPreAddNodesWithGroupContext {
691    fn clone(&self) -> Self {
692        Python::attach(|py| Self {
693            nodes: self.nodes.clone_ref(py),
694            group: self.group.clone_ref(py),
695        })
696    }
697}
698
699impl PyPreAddNodesWithGroupContext {
700    /// # Panics
701    ///
702    /// Panics if the python typing was not followed.
703    pub fn bind(py: Python<'_>, context: PreAddNodesWithGroupContext) -> Self {
704        let nodes: Vec<(PyNodeIndex, PyAttributes)> = context.nodes.deep_into();
705
706        Self {
707            nodes: nodes.into_py_any(py).expect("nodes should be creatable"),
708            group: PyGroup::from(context.group)
709                .into_py_any(py)
710                .expect("PyGroup should be creatable"),
711        }
712    }
713
714    /// # Panics
715    ///
716    /// Panics if the python typing was not followed.
717    pub fn extract(self, py: Python<'_>) -> PreAddNodesWithGroupContext {
718        let nodes: Vec<(PyNodeIndex, PyAttributes)> =
719            self.nodes.extract(py).expect("nodes should be extractable");
720
721        let group: PyGroup = self
722            .group
723            .extract(py)
724            .expect("PyGroup should be extractable");
725
726        PreAddNodesWithGroupContext {
727            nodes: nodes.deep_into(),
728            group: group.into(),
729        }
730    }
731}
732
733#[pymethods]
734impl PyPreAddNodesWithGroupContext {
735    #[new]
736    pub const fn new(nodes: Py<PyAny>, group: Py<PyAny>) -> Self {
737        Self { nodes, group }
738    }
739
740    #[getter]
741    pub fn nodes(&self, py: Python<'_>) -> Py<PyAny> {
742        self.nodes.clone_ref(py)
743    }
744
745    #[getter]
746    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
747        self.group.clone_ref(py)
748    }
749}
750
751#[pyclass(frozen)]
752#[derive(Debug)]
753pub struct PyPostAddNodesWithGroupContext {
754    nodes: Py<PyAny>,
755    group: Py<PyAny>,
756}
757
758impl Clone for PyPostAddNodesWithGroupContext {
759    fn clone(&self) -> Self {
760        Python::attach(|py| Self {
761            nodes: self.nodes.clone_ref(py),
762            group: self.group.clone_ref(py),
763        })
764    }
765}
766
767impl PyPostAddNodesWithGroupContext {
768    /// # Panics
769    ///
770    /// Panics if the python typing was not followed.
771    pub fn bind(py: Python<'_>, context: PostAddNodesWithGroupContext) -> Self {
772        let nodes: Vec<(PyNodeIndex, PyAttributes)> = context.nodes.deep_into();
773
774        Self {
775            nodes: nodes.into_py_any(py).expect("nodes should be creatable"),
776            group: PyGroup::from(context.group)
777                .into_py_any(py)
778                .expect("PyGroup should be creatable"),
779        }
780    }
781}
782
783#[pymethods]
784impl PyPostAddNodesWithGroupContext {
785    #[new]
786    pub const fn new(nodes: Py<PyAny>, group: Py<PyAny>) -> Self {
787        Self { nodes, group }
788    }
789
790    #[getter]
791    pub fn nodes(&self, py: Python<'_>) -> Py<PyAny> {
792        self.nodes.clone_ref(py)
793    }
794
795    #[getter]
796    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
797        self.group.clone_ref(py)
798    }
799}
800
801#[pyclass(frozen)]
802#[derive(Debug)]
803pub struct PyPreAddNodesDataframesContext {
804    nodes_dataframes: Py<PyAny>,
805}
806
807impl Clone for PyPreAddNodesDataframesContext {
808    fn clone(&self) -> Self {
809        Python::attach(|py| Self {
810            nodes_dataframes: self.nodes_dataframes.clone_ref(py),
811        })
812    }
813}
814
815impl PyPreAddNodesDataframesContext {
816    /// # Panics
817    ///
818    /// Panics if the python typing was not followed.
819    pub fn bind(py: Python<'_>, context: PreAddNodesDataframesContext) -> Self {
820        let nodes_dataframes = node_dataframe_inputs_to_py(context.nodes_dataframes);
821
822        Self {
823            nodes_dataframes: nodes_dataframes
824                .into_py_any(py)
825                .expect("nodes_dataframes should be creatable"),
826        }
827    }
828
829    /// # Panics
830    ///
831    /// Panics if the python typing was not followed.
832    pub fn extract(self, py: Python<'_>) -> PreAddNodesDataframesContext {
833        let nodes_dataframes: Vec<(PyDataFrame, String)> = self
834            .nodes_dataframes
835            .extract(py)
836            .expect("nodes_dataframes should be extractable");
837
838        PreAddNodesDataframesContext {
839            nodes_dataframes: py_to_node_dataframe_inputs(nodes_dataframes),
840        }
841    }
842}
843
844#[pymethods]
845impl PyPreAddNodesDataframesContext {
846    #[new]
847    pub const fn new(nodes_dataframes: Py<PyAny>) -> Self {
848        Self { nodes_dataframes }
849    }
850
851    #[getter]
852    pub fn nodes_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
853        self.nodes_dataframes.clone_ref(py)
854    }
855}
856
857#[pyclass(frozen)]
858#[derive(Debug)]
859pub struct PyPostAddNodesDataframesContext {
860    nodes_dataframes: Py<PyAny>,
861}
862
863impl Clone for PyPostAddNodesDataframesContext {
864    fn clone(&self) -> Self {
865        Python::attach(|py| Self {
866            nodes_dataframes: self.nodes_dataframes.clone_ref(py),
867        })
868    }
869}
870
871impl PyPostAddNodesDataframesContext {
872    /// # Panics
873    ///
874    /// Panics if the python typing was not followed.
875    pub fn bind(py: Python<'_>, context: PostAddNodesDataframesContext) -> Self {
876        let nodes_dataframes = node_dataframe_inputs_to_py(context.nodes_dataframes);
877
878        Self {
879            nodes_dataframes: nodes_dataframes
880                .into_py_any(py)
881                .expect("nodes_dataframes should be creatable"),
882        }
883    }
884}
885
886#[pymethods]
887impl PyPostAddNodesDataframesContext {
888    #[new]
889    pub const fn new(nodes_dataframes: Py<PyAny>) -> Self {
890        Self { nodes_dataframes }
891    }
892
893    #[getter]
894    pub fn nodes_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
895        self.nodes_dataframes.clone_ref(py)
896    }
897}
898
899#[pyclass(frozen)]
900#[derive(Debug)]
901pub struct PyPreAddNodesDataframesWithGroupContext {
902    nodes_dataframes: Py<PyAny>,
903    group: Py<PyAny>,
904}
905
906impl Clone for PyPreAddNodesDataframesWithGroupContext {
907    fn clone(&self) -> Self {
908        Python::attach(|py| Self {
909            nodes_dataframes: self.nodes_dataframes.clone_ref(py),
910            group: self.group.clone_ref(py),
911        })
912    }
913}
914
915impl PyPreAddNodesDataframesWithGroupContext {
916    /// # Panics
917    ///
918    /// Panics if the python typing was not followed.
919    pub fn bind(py: Python<'_>, context: PreAddNodesDataframesWithGroupContext) -> Self {
920        let nodes_dataframes = node_dataframe_inputs_to_py(context.nodes_dataframes);
921
922        Self {
923            nodes_dataframes: nodes_dataframes
924                .into_py_any(py)
925                .expect("nodes_dataframes should be creatable"),
926            group: PyGroup::from(context.group)
927                .into_py_any(py)
928                .expect("PyGroup should be creatable"),
929        }
930    }
931
932    /// # Panics
933    ///
934    /// Panics if the python typing was not followed.
935    pub fn extract(self, py: Python<'_>) -> PreAddNodesDataframesWithGroupContext {
936        let nodes_dataframes: Vec<(PyDataFrame, String)> = self
937            .nodes_dataframes
938            .extract(py)
939            .expect("nodes_dataframes should be extractable");
940
941        let group: PyGroup = self
942            .group
943            .extract(py)
944            .expect("PyGroup should be extractable");
945
946        PreAddNodesDataframesWithGroupContext {
947            nodes_dataframes: py_to_node_dataframe_inputs(nodes_dataframes),
948            group: group.into(),
949        }
950    }
951}
952
953#[pymethods]
954impl PyPreAddNodesDataframesWithGroupContext {
955    #[new]
956    pub const fn new(nodes_dataframes: Py<PyAny>, group: Py<PyAny>) -> Self {
957        Self {
958            nodes_dataframes,
959            group,
960        }
961    }
962
963    #[getter]
964    pub fn nodes_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
965        self.nodes_dataframes.clone_ref(py)
966    }
967
968    #[getter]
969    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
970        self.group.clone_ref(py)
971    }
972}
973
974#[pyclass(frozen)]
975#[derive(Debug)]
976pub struct PyPostAddNodesDataframesWithGroupContext {
977    nodes_dataframes: Py<PyAny>,
978    group: Py<PyAny>,
979}
980
981impl Clone for PyPostAddNodesDataframesWithGroupContext {
982    fn clone(&self) -> Self {
983        Python::attach(|py| Self {
984            nodes_dataframes: self.nodes_dataframes.clone_ref(py),
985            group: self.group.clone_ref(py),
986        })
987    }
988}
989
990impl PyPostAddNodesDataframesWithGroupContext {
991    /// # Panics
992    ///
993    /// Panics if the python typing was not followed.
994    pub fn bind(py: Python<'_>, context: PostAddNodesDataframesWithGroupContext) -> Self {
995        let nodes_dataframes = node_dataframe_inputs_to_py(context.nodes_dataframes);
996
997        Self {
998            nodes_dataframes: nodes_dataframes
999                .into_py_any(py)
1000                .expect("nodes_dataframes should be creatable"),
1001            group: PyGroup::from(context.group)
1002                .into_py_any(py)
1003                .expect("PyGroup should be creatable"),
1004        }
1005    }
1006}
1007
1008#[pymethods]
1009impl PyPostAddNodesDataframesWithGroupContext {
1010    #[new]
1011    pub const fn new(nodes_dataframes: Py<PyAny>, group: Py<PyAny>) -> Self {
1012        Self {
1013            nodes_dataframes,
1014            group,
1015        }
1016    }
1017
1018    #[getter]
1019    pub fn nodes_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
1020        self.nodes_dataframes.clone_ref(py)
1021    }
1022
1023    #[getter]
1024    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
1025        self.group.clone_ref(py)
1026    }
1027}
1028
1029#[pyclass(frozen)]
1030#[derive(Debug)]
1031pub struct PyPreAddEdgeContext {
1032    source_node_index: Py<PyAny>,
1033    target_node_index: Py<PyAny>,
1034    attributes: Py<PyAny>,
1035}
1036
1037impl Clone for PyPreAddEdgeContext {
1038    fn clone(&self) -> Self {
1039        Python::attach(|py| Self {
1040            source_node_index: self.source_node_index.clone_ref(py),
1041            target_node_index: self.target_node_index.clone_ref(py),
1042            attributes: self.attributes.clone_ref(py),
1043        })
1044    }
1045}
1046
1047impl PyPreAddEdgeContext {
1048    /// # Panics
1049    ///
1050    /// Panics if the python typing was not followed.
1051    pub fn bind(py: Python<'_>, context: PreAddEdgeContext) -> Self {
1052        Self {
1053            source_node_index: PyNodeIndex::from(context.source_node_index)
1054                .into_py_any(py)
1055                .expect("PyNodeIndex should be creatable"),
1056            target_node_index: PyNodeIndex::from(context.target_node_index)
1057                .into_py_any(py)
1058                .expect("PyNodeIndex should be creatable"),
1059            attributes: {
1060                let py_attrs: PyAttributes = context.attributes.deep_into();
1061                py_attrs
1062                    .into_py_any(py)
1063                    .expect("PyAttributes should be creatable")
1064            },
1065        }
1066    }
1067
1068    /// # Panics
1069    ///
1070    /// Panics if the python typing was not followed.
1071    pub fn extract(self, py: Python<'_>) -> PreAddEdgeContext {
1072        let source: PyNodeIndex = self
1073            .source_node_index
1074            .extract(py)
1075            .expect("PyNodeIndex should be extractable");
1076
1077        let target: PyNodeIndex = self
1078            .target_node_index
1079            .extract(py)
1080            .expect("PyNodeIndex should be extractable");
1081
1082        let attributes: PyAttributes = self
1083            .attributes
1084            .extract(py)
1085            .expect("PyAttributes should be extractable");
1086
1087        PreAddEdgeContext {
1088            source_node_index: source.into(),
1089            target_node_index: target.into(),
1090            attributes: attributes.deep_into(),
1091        }
1092    }
1093}
1094
1095#[pymethods]
1096impl PyPreAddEdgeContext {
1097    #[new]
1098    pub const fn new(
1099        source_node_index: Py<PyAny>,
1100        target_node_index: Py<PyAny>,
1101        attributes: Py<PyAny>,
1102    ) -> Self {
1103        Self {
1104            source_node_index,
1105            target_node_index,
1106            attributes,
1107        }
1108    }
1109
1110    #[getter]
1111    pub fn source_node_index(&self, py: Python<'_>) -> Py<PyAny> {
1112        self.source_node_index.clone_ref(py)
1113    }
1114
1115    #[getter]
1116    pub fn target_node_index(&self, py: Python<'_>) -> Py<PyAny> {
1117        self.target_node_index.clone_ref(py)
1118    }
1119
1120    #[getter]
1121    pub fn attributes(&self, py: Python<'_>) -> Py<PyAny> {
1122        self.attributes.clone_ref(py)
1123    }
1124}
1125
1126#[pyclass(frozen)]
1127#[derive(Debug)]
1128pub struct PyPostAddEdgeContext {
1129    edge_index: Py<PyAny>,
1130}
1131
1132impl Clone for PyPostAddEdgeContext {
1133    fn clone(&self) -> Self {
1134        Python::attach(|py| Self {
1135            edge_index: self.edge_index.clone_ref(py),
1136        })
1137    }
1138}
1139
1140impl PyPostAddEdgeContext {
1141    /// # Panics
1142    ///
1143    /// Panics if the python typing was not followed.
1144    pub fn bind(py: Python<'_>, context: PostAddEdgeContext) -> Self {
1145        Self {
1146            edge_index: context
1147                .edge_index
1148                .into_py_any(py)
1149                .expect("edge_index should be creatable"),
1150        }
1151    }
1152
1153    /// # Panics
1154    ///
1155    /// Panics if the python typing was not followed.
1156    pub fn extract(self, py: Python<'_>) -> PostAddEdgeContext {
1157        PostAddEdgeContext {
1158            edge_index: self
1159                .edge_index
1160                .extract(py)
1161                .expect("edge_index should be extractable"),
1162        }
1163    }
1164}
1165
1166#[pymethods]
1167impl PyPostAddEdgeContext {
1168    #[new]
1169    pub const fn new(edge_index: Py<PyAny>) -> Self {
1170        Self { edge_index }
1171    }
1172
1173    #[getter]
1174    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
1175        self.edge_index.clone_ref(py)
1176    }
1177}
1178
1179#[pyclass(frozen)]
1180#[derive(Debug)]
1181pub struct PyPreAddEdgeWithGroupContext {
1182    source_node_index: Py<PyAny>,
1183    target_node_index: Py<PyAny>,
1184    attributes: Py<PyAny>,
1185    group: Py<PyAny>,
1186}
1187
1188impl Clone for PyPreAddEdgeWithGroupContext {
1189    fn clone(&self) -> Self {
1190        Python::attach(|py| Self {
1191            source_node_index: self.source_node_index.clone_ref(py),
1192            target_node_index: self.target_node_index.clone_ref(py),
1193            attributes: self.attributes.clone_ref(py),
1194            group: self.group.clone_ref(py),
1195        })
1196    }
1197}
1198
1199impl PyPreAddEdgeWithGroupContext {
1200    /// # Panics
1201    ///
1202    /// Panics if the python typing was not followed.
1203    pub fn bind(py: Python<'_>, context: PreAddEdgeWithGroupContext) -> Self {
1204        Self {
1205            source_node_index: PyNodeIndex::from(context.source_node_index)
1206                .into_py_any(py)
1207                .expect("PyNodeIndex should be creatable"),
1208            target_node_index: PyNodeIndex::from(context.target_node_index)
1209                .into_py_any(py)
1210                .expect("PyNodeIndex should be creatable"),
1211            attributes: {
1212                let py_attrs: PyAttributes = context.attributes.deep_into();
1213                py_attrs
1214                    .into_py_any(py)
1215                    .expect("PyAttributes should be creatable")
1216            },
1217            group: PyGroup::from(context.group)
1218                .into_py_any(py)
1219                .expect("PyGroup should be creatable"),
1220        }
1221    }
1222
1223    /// # Panics
1224    ///
1225    /// Panics if the python typing was not followed.
1226    pub fn extract(self, py: Python<'_>) -> PreAddEdgeWithGroupContext {
1227        let source: PyNodeIndex = self
1228            .source_node_index
1229            .extract(py)
1230            .expect("PyNodeIndex should be extractable");
1231
1232        let target: PyNodeIndex = self
1233            .target_node_index
1234            .extract(py)
1235            .expect("PyNodeIndex should be extractable");
1236
1237        let attributes: PyAttributes = self
1238            .attributes
1239            .extract(py)
1240            .expect("PyAttributes should be extractable");
1241
1242        let group: PyGroup = self
1243            .group
1244            .extract(py)
1245            .expect("PyGroup should be extractable");
1246
1247        PreAddEdgeWithGroupContext {
1248            source_node_index: source.into(),
1249            target_node_index: target.into(),
1250            attributes: attributes.deep_into(),
1251            group: group.into(),
1252        }
1253    }
1254}
1255
1256#[pymethods]
1257impl PyPreAddEdgeWithGroupContext {
1258    #[new]
1259    pub const fn new(
1260        source_node_index: Py<PyAny>,
1261        target_node_index: Py<PyAny>,
1262        attributes: Py<PyAny>,
1263        group: Py<PyAny>,
1264    ) -> Self {
1265        Self {
1266            source_node_index,
1267            target_node_index,
1268            attributes,
1269            group,
1270        }
1271    }
1272
1273    #[getter]
1274    pub fn source_node_index(&self, py: Python<'_>) -> Py<PyAny> {
1275        self.source_node_index.clone_ref(py)
1276    }
1277
1278    #[getter]
1279    pub fn target_node_index(&self, py: Python<'_>) -> Py<PyAny> {
1280        self.target_node_index.clone_ref(py)
1281    }
1282
1283    #[getter]
1284    pub fn attributes(&self, py: Python<'_>) -> Py<PyAny> {
1285        self.attributes.clone_ref(py)
1286    }
1287
1288    #[getter]
1289    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
1290        self.group.clone_ref(py)
1291    }
1292}
1293
1294#[pyclass(frozen)]
1295#[derive(Debug)]
1296pub struct PyPostAddEdgeWithGroupContext {
1297    edge_index: Py<PyAny>,
1298}
1299
1300impl Clone for PyPostAddEdgeWithGroupContext {
1301    fn clone(&self) -> Self {
1302        Python::attach(|py| Self {
1303            edge_index: self.edge_index.clone_ref(py),
1304        })
1305    }
1306}
1307
1308impl PyPostAddEdgeWithGroupContext {
1309    /// # Panics
1310    ///
1311    /// Panics if the python typing was not followed.
1312    pub fn bind(py: Python<'_>, context: PostAddEdgeWithGroupContext) -> Self {
1313        Self {
1314            edge_index: context
1315                .edge_index
1316                .into_py_any(py)
1317                .expect("edge_index should be creatable"),
1318        }
1319    }
1320}
1321
1322#[pymethods]
1323impl PyPostAddEdgeWithGroupContext {
1324    #[new]
1325    pub const fn new(edge_index: Py<PyAny>) -> Self {
1326        Self { edge_index }
1327    }
1328
1329    #[getter]
1330    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
1331        self.edge_index.clone_ref(py)
1332    }
1333}
1334
1335#[pyclass(frozen)]
1336#[derive(Debug)]
1337pub struct PyPreRemoveEdgeContext {
1338    edge_index: Py<PyAny>,
1339}
1340
1341impl Clone for PyPreRemoveEdgeContext {
1342    fn clone(&self) -> Self {
1343        Python::attach(|py| Self {
1344            edge_index: self.edge_index.clone_ref(py),
1345        })
1346    }
1347}
1348
1349impl PyPreRemoveEdgeContext {
1350    /// # Panics
1351    ///
1352    /// Panics if the python typing was not followed.
1353    pub fn bind(py: Python<'_>, context: PreRemoveEdgeContext) -> Self {
1354        Self {
1355            edge_index: context
1356                .edge_index
1357                .into_py_any(py)
1358                .expect("edge_index should be creatable"),
1359        }
1360    }
1361
1362    /// # Panics
1363    ///
1364    /// Panics if the python typing was not followed.
1365    pub fn extract(self, py: Python<'_>) -> PreRemoveEdgeContext {
1366        PreRemoveEdgeContext {
1367            edge_index: self
1368                .edge_index
1369                .extract(py)
1370                .expect("edge_index should be extractable"),
1371        }
1372    }
1373}
1374
1375#[pymethods]
1376impl PyPreRemoveEdgeContext {
1377    #[new]
1378    pub const fn new(edge_index: Py<PyAny>) -> Self {
1379        Self { edge_index }
1380    }
1381
1382    #[getter]
1383    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
1384        self.edge_index.clone_ref(py)
1385    }
1386}
1387
1388#[pyclass(frozen)]
1389#[derive(Debug)]
1390pub struct PyPostRemoveEdgeContext {
1391    edge_index: Py<PyAny>,
1392}
1393
1394impl Clone for PyPostRemoveEdgeContext {
1395    fn clone(&self) -> Self {
1396        Python::attach(|py| Self {
1397            edge_index: self.edge_index.clone_ref(py),
1398        })
1399    }
1400}
1401
1402impl PyPostRemoveEdgeContext {
1403    /// # Panics
1404    ///
1405    /// Panics if the python typing was not followed.
1406    pub fn bind(py: Python<'_>, context: PostRemoveEdgeContext) -> Self {
1407        Self {
1408            edge_index: context
1409                .edge_index
1410                .into_py_any(py)
1411                .expect("edge_index should be creatable"),
1412        }
1413    }
1414}
1415
1416#[pymethods]
1417impl PyPostRemoveEdgeContext {
1418    #[new]
1419    pub const fn new(edge_index: Py<PyAny>) -> Self {
1420        Self { edge_index }
1421    }
1422
1423    #[getter]
1424    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
1425        self.edge_index.clone_ref(py)
1426    }
1427}
1428
1429#[pyclass(frozen)]
1430#[derive(Debug)]
1431pub struct PyPreAddEdgesContext {
1432    edges: Py<PyAny>,
1433}
1434
1435impl Clone for PyPreAddEdgesContext {
1436    fn clone(&self) -> Self {
1437        Python::attach(|py| Self {
1438            edges: self.edges.clone_ref(py),
1439        })
1440    }
1441}
1442
1443impl PyPreAddEdgesContext {
1444    /// # Panics
1445    ///
1446    /// Panics if the python typing was not followed.
1447    pub fn bind(py: Python<'_>, context: PreAddEdgesContext) -> Self {
1448        let edges: Vec<(PyNodeIndex, PyNodeIndex, PyAttributes)> = context.edges.deep_into();
1449
1450        Self {
1451            edges: edges.into_py_any(py).expect("edges should be creatable"),
1452        }
1453    }
1454
1455    /// # Panics
1456    ///
1457    /// Panics if the python typing was not followed.
1458    pub fn extract(self, py: Python<'_>) -> PreAddEdgesContext {
1459        let edges: Vec<(PyNodeIndex, PyNodeIndex, PyAttributes)> =
1460            self.edges.extract(py).expect("edges should be extractable");
1461
1462        PreAddEdgesContext {
1463            edges: edges.deep_into(),
1464        }
1465    }
1466}
1467
1468#[pymethods]
1469impl PyPreAddEdgesContext {
1470    #[new]
1471    pub const fn new(edges: Py<PyAny>) -> Self {
1472        Self { edges }
1473    }
1474
1475    #[getter]
1476    pub fn edges(&self, py: Python<'_>) -> Py<PyAny> {
1477        self.edges.clone_ref(py)
1478    }
1479}
1480
1481#[pyclass(frozen)]
1482#[derive(Debug)]
1483pub struct PyPostAddEdgesContext {
1484    edge_indices: Py<PyAny>,
1485}
1486
1487impl Clone for PyPostAddEdgesContext {
1488    fn clone(&self) -> Self {
1489        Python::attach(|py| Self {
1490            edge_indices: self.edge_indices.clone_ref(py),
1491        })
1492    }
1493}
1494
1495impl PyPostAddEdgesContext {
1496    /// # Panics
1497    ///
1498    /// Panics if the python typing was not followed.
1499    pub fn bind(py: Python<'_>, context: PostAddEdgesContext) -> Self {
1500        Self {
1501            edge_indices: context
1502                .edge_indices
1503                .into_py_any(py)
1504                .expect("edge_indices should be creatable"),
1505        }
1506    }
1507}
1508
1509#[pymethods]
1510impl PyPostAddEdgesContext {
1511    #[new]
1512    pub const fn new(edge_indices: Py<PyAny>) -> Self {
1513        Self { edge_indices }
1514    }
1515
1516    #[getter]
1517    pub fn edge_indices(&self, py: Python<'_>) -> Py<PyAny> {
1518        self.edge_indices.clone_ref(py)
1519    }
1520}
1521
1522#[pyclass(frozen)]
1523#[derive(Debug)]
1524pub struct PyPreAddEdgesWithGroupContext {
1525    edges: Py<PyAny>,
1526    group: Py<PyAny>,
1527}
1528
1529impl Clone for PyPreAddEdgesWithGroupContext {
1530    fn clone(&self) -> Self {
1531        Python::attach(|py| Self {
1532            edges: self.edges.clone_ref(py),
1533            group: self.group.clone_ref(py),
1534        })
1535    }
1536}
1537
1538impl PyPreAddEdgesWithGroupContext {
1539    /// # Panics
1540    ///
1541    /// Panics if the python typing was not followed.
1542    pub fn bind(py: Python<'_>, context: PreAddEdgesWithGroupContext) -> Self {
1543        let edges: Vec<(PyNodeIndex, PyNodeIndex, PyAttributes)> = context.edges.deep_into();
1544
1545        Self {
1546            edges: edges.into_py_any(py).expect("edges should be creatable"),
1547            group: PyGroup::from(context.group)
1548                .into_py_any(py)
1549                .expect("PyGroup should be creatable"),
1550        }
1551    }
1552
1553    /// # Panics
1554    ///
1555    /// Panics if the python typing was not followed.
1556    pub fn extract(self, py: Python<'_>) -> PreAddEdgesWithGroupContext {
1557        let edges: Vec<(PyNodeIndex, PyNodeIndex, PyAttributes)> =
1558            self.edges.extract(py).expect("edges should be extractable");
1559
1560        let group: PyGroup = self
1561            .group
1562            .extract(py)
1563            .expect("PyGroup should be extractable");
1564
1565        PreAddEdgesWithGroupContext {
1566            edges: edges.deep_into(),
1567            group: group.into(),
1568        }
1569    }
1570}
1571
1572#[pymethods]
1573impl PyPreAddEdgesWithGroupContext {
1574    #[new]
1575    pub const fn new(edges: Py<PyAny>, group: Py<PyAny>) -> Self {
1576        Self { edges, group }
1577    }
1578
1579    #[getter]
1580    pub fn edges(&self, py: Python<'_>) -> Py<PyAny> {
1581        self.edges.clone_ref(py)
1582    }
1583
1584    #[getter]
1585    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
1586        self.group.clone_ref(py)
1587    }
1588}
1589
1590#[pyclass(frozen)]
1591#[derive(Debug)]
1592pub struct PyPostAddEdgesWithGroupContext {
1593    edge_indices: Py<PyAny>,
1594}
1595
1596impl Clone for PyPostAddEdgesWithGroupContext {
1597    fn clone(&self) -> Self {
1598        Python::attach(|py| Self {
1599            edge_indices: self.edge_indices.clone_ref(py),
1600        })
1601    }
1602}
1603
1604impl PyPostAddEdgesWithGroupContext {
1605    /// # Panics
1606    ///
1607    /// Panics if the python typing was not followed.
1608    pub fn bind(py: Python<'_>, context: PostAddEdgesWithGroupContext) -> Self {
1609        Self {
1610            edge_indices: context
1611                .edge_indices
1612                .into_py_any(py)
1613                .expect("edge_indices should be creatable"),
1614        }
1615    }
1616}
1617
1618#[pymethods]
1619impl PyPostAddEdgesWithGroupContext {
1620    #[new]
1621    pub const fn new(edge_indices: Py<PyAny>) -> Self {
1622        Self { edge_indices }
1623    }
1624
1625    #[getter]
1626    pub fn edge_indices(&self, py: Python<'_>) -> Py<PyAny> {
1627        self.edge_indices.clone_ref(py)
1628    }
1629}
1630
1631#[pyclass(frozen)]
1632#[derive(Debug)]
1633pub struct PyPreAddEdgesDataframesContext {
1634    edges_dataframes: Py<PyAny>,
1635}
1636
1637impl Clone for PyPreAddEdgesDataframesContext {
1638    fn clone(&self) -> Self {
1639        Python::attach(|py| Self {
1640            edges_dataframes: self.edges_dataframes.clone_ref(py),
1641        })
1642    }
1643}
1644
1645impl PyPreAddEdgesDataframesContext {
1646    /// # Panics
1647    ///
1648    /// Panics if the python typing was not followed.
1649    pub fn bind(py: Python<'_>, context: PreAddEdgesDataframesContext) -> Self {
1650        let edges_dataframes = edge_dataframe_inputs_to_py(context.edges_dataframes);
1651
1652        Self {
1653            edges_dataframes: edges_dataframes
1654                .into_py_any(py)
1655                .expect("edges_dataframes should be creatable"),
1656        }
1657    }
1658
1659    /// # Panics
1660    ///
1661    /// Panics if the python typing was not followed.
1662    pub fn extract(self, py: Python<'_>) -> PreAddEdgesDataframesContext {
1663        let edges_dataframes: Vec<(PyDataFrame, String, String)> = self
1664            .edges_dataframes
1665            .extract(py)
1666            .expect("edges_dataframes should be extractable");
1667
1668        PreAddEdgesDataframesContext {
1669            edges_dataframes: py_to_edge_dataframe_inputs(edges_dataframes),
1670        }
1671    }
1672}
1673
1674#[pymethods]
1675impl PyPreAddEdgesDataframesContext {
1676    #[new]
1677    pub const fn new(edges_dataframes: Py<PyAny>) -> Self {
1678        Self { edges_dataframes }
1679    }
1680
1681    #[getter]
1682    pub fn edges_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
1683        self.edges_dataframes.clone_ref(py)
1684    }
1685}
1686
1687#[pyclass(frozen)]
1688#[derive(Debug)]
1689pub struct PyPostAddEdgesDataframesContext {
1690    edges_dataframes: Py<PyAny>,
1691}
1692
1693impl Clone for PyPostAddEdgesDataframesContext {
1694    fn clone(&self) -> Self {
1695        Python::attach(|py| Self {
1696            edges_dataframes: self.edges_dataframes.clone_ref(py),
1697        })
1698    }
1699}
1700
1701impl PyPostAddEdgesDataframesContext {
1702    /// # Panics
1703    ///
1704    /// Panics if the python typing was not followed.
1705    pub fn bind(py: Python<'_>, context: PostAddEdgesDataframesContext) -> Self {
1706        let edges_dataframes = edge_dataframe_inputs_to_py(context.edges_dataframes);
1707
1708        Self {
1709            edges_dataframes: edges_dataframes
1710                .into_py_any(py)
1711                .expect("edges_dataframes should be creatable"),
1712        }
1713    }
1714}
1715
1716#[pymethods]
1717impl PyPostAddEdgesDataframesContext {
1718    #[new]
1719    pub const fn new(edges_dataframes: Py<PyAny>) -> Self {
1720        Self { edges_dataframes }
1721    }
1722
1723    #[getter]
1724    pub fn edges_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
1725        self.edges_dataframes.clone_ref(py)
1726    }
1727}
1728
1729#[pyclass(frozen)]
1730#[derive(Debug)]
1731pub struct PyPreAddEdgesDataframesWithGroupContext {
1732    edges_dataframes: Py<PyAny>,
1733    group: Py<PyAny>,
1734}
1735
1736impl Clone for PyPreAddEdgesDataframesWithGroupContext {
1737    fn clone(&self) -> Self {
1738        Python::attach(|py| Self {
1739            edges_dataframes: self.edges_dataframes.clone_ref(py),
1740            group: self.group.clone_ref(py),
1741        })
1742    }
1743}
1744
1745impl PyPreAddEdgesDataframesWithGroupContext {
1746    /// # Panics
1747    ///
1748    /// Panics if the python typing was not followed.
1749    pub fn bind(py: Python<'_>, context: PreAddEdgesDataframesWithGroupContext) -> Self {
1750        let edges_dataframes = edge_dataframe_inputs_to_py(context.edges_dataframes);
1751
1752        Self {
1753            edges_dataframes: edges_dataframes
1754                .into_py_any(py)
1755                .expect("edges_dataframes should be creatable"),
1756            group: PyGroup::from(context.group)
1757                .into_py_any(py)
1758                .expect("PyGroup should be creatable"),
1759        }
1760    }
1761
1762    /// # Panics
1763    ///
1764    /// Panics if the python typing was not followed.
1765    pub fn extract(self, py: Python<'_>) -> PreAddEdgesDataframesWithGroupContext {
1766        let edges_dataframes: Vec<(PyDataFrame, String, String)> = self
1767            .edges_dataframes
1768            .extract(py)
1769            .expect("edges_dataframes should be extractable");
1770
1771        let group: PyGroup = self
1772            .group
1773            .extract(py)
1774            .expect("PyGroup should be extractable");
1775
1776        PreAddEdgesDataframesWithGroupContext {
1777            edges_dataframes: py_to_edge_dataframe_inputs(edges_dataframes),
1778            group: group.into(),
1779        }
1780    }
1781}
1782
1783#[pymethods]
1784impl PyPreAddEdgesDataframesWithGroupContext {
1785    #[new]
1786    pub const fn new(edges_dataframes: Py<PyAny>, group: Py<PyAny>) -> Self {
1787        Self {
1788            edges_dataframes,
1789            group,
1790        }
1791    }
1792
1793    #[getter]
1794    pub fn edges_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
1795        self.edges_dataframes.clone_ref(py)
1796    }
1797
1798    #[getter]
1799    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
1800        self.group.clone_ref(py)
1801    }
1802}
1803
1804#[pyclass(frozen)]
1805#[derive(Debug)]
1806pub struct PyPostAddEdgesDataframesWithGroupContext {
1807    edges_dataframes: Py<PyAny>,
1808    group: Py<PyAny>,
1809}
1810
1811impl Clone for PyPostAddEdgesDataframesWithGroupContext {
1812    fn clone(&self) -> Self {
1813        Python::attach(|py| Self {
1814            edges_dataframes: self.edges_dataframes.clone_ref(py),
1815            group: self.group.clone_ref(py),
1816        })
1817    }
1818}
1819
1820impl PyPostAddEdgesDataframesWithGroupContext {
1821    /// # Panics
1822    ///
1823    /// Panics if the python typing was not followed.
1824    pub fn bind(py: Python<'_>, context: PostAddEdgesDataframesWithGroupContext) -> Self {
1825        let edges_dataframes = edge_dataframe_inputs_to_py(context.edges_dataframes);
1826
1827        Self {
1828            edges_dataframes: edges_dataframes
1829                .into_py_any(py)
1830                .expect("edges_dataframes should be creatable"),
1831            group: PyGroup::from(context.group)
1832                .into_py_any(py)
1833                .expect("PyGroup should be creatable"),
1834        }
1835    }
1836}
1837
1838#[pymethods]
1839impl PyPostAddEdgesDataframesWithGroupContext {
1840    #[new]
1841    pub const fn new(edges_dataframes: Py<PyAny>, group: Py<PyAny>) -> Self {
1842        Self {
1843            edges_dataframes,
1844            group,
1845        }
1846    }
1847
1848    #[getter]
1849    pub fn edges_dataframes(&self, py: Python<'_>) -> Py<PyAny> {
1850        self.edges_dataframes.clone_ref(py)
1851    }
1852
1853    #[getter]
1854    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
1855        self.group.clone_ref(py)
1856    }
1857}
1858
1859#[pyclass(frozen)]
1860#[derive(Debug)]
1861pub struct PyPreAddGroupContext {
1862    group: Py<PyAny>,
1863    node_indices: Py<PyAny>,
1864    edge_indices: Py<PyAny>,
1865}
1866
1867impl Clone for PyPreAddGroupContext {
1868    fn clone(&self) -> Self {
1869        Python::attach(|py| Self {
1870            group: self.group.clone_ref(py),
1871            node_indices: self.node_indices.clone_ref(py),
1872            edge_indices: self.edge_indices.clone_ref(py),
1873        })
1874    }
1875}
1876
1877impl PyPreAddGroupContext {
1878    /// # Panics
1879    ///
1880    /// Panics if the python typing was not followed.
1881    pub fn bind(py: Python<'_>, context: PreAddGroupContext) -> Self {
1882        let node_indices: Option<Vec<PyNodeIndex>> = context.node_indices.deep_into();
1883
1884        Self {
1885            group: PyGroup::from(context.group)
1886                .into_py_any(py)
1887                .expect("PyGroup should be creatable"),
1888            node_indices: node_indices
1889                .into_py_any(py)
1890                .expect("node_indices should be creatable"),
1891            edge_indices: context
1892                .edge_indices
1893                .into_py_any(py)
1894                .expect("edge_indices should be creatable"),
1895        }
1896    }
1897
1898    /// # Panics
1899    ///
1900    /// Panics if the python typing was not followed.
1901    pub fn extract(self, py: Python<'_>) -> PreAddGroupContext {
1902        let group: PyGroup = self
1903            .group
1904            .extract(py)
1905            .expect("PyGroup should be extractable");
1906
1907        let node_indices: Option<Vec<PyNodeIndex>> = self
1908            .node_indices
1909            .extract(py)
1910            .expect("node_indices should be extractable");
1911
1912        let edge_indices: Option<Vec<EdgeIndex>> = self
1913            .edge_indices
1914            .extract(py)
1915            .expect("edge_indices should be extractable");
1916
1917        PreAddGroupContext {
1918            group: group.into(),
1919            node_indices: node_indices.deep_into(),
1920            edge_indices,
1921        }
1922    }
1923}
1924
1925#[pymethods]
1926impl PyPreAddGroupContext {
1927    #[new]
1928    pub const fn new(group: Py<PyAny>, node_indices: Py<PyAny>, edge_indices: Py<PyAny>) -> Self {
1929        Self {
1930            group,
1931            node_indices,
1932            edge_indices,
1933        }
1934    }
1935
1936    #[getter]
1937    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
1938        self.group.clone_ref(py)
1939    }
1940
1941    #[getter]
1942    pub fn node_indices(&self, py: Python<'_>) -> Py<PyAny> {
1943        self.node_indices.clone_ref(py)
1944    }
1945
1946    #[getter]
1947    pub fn edge_indices(&self, py: Python<'_>) -> Py<PyAny> {
1948        self.edge_indices.clone_ref(py)
1949    }
1950}
1951
1952#[pyclass(frozen)]
1953#[derive(Debug)]
1954pub struct PyPostAddGroupContext {
1955    group: Py<PyAny>,
1956    node_indices: Py<PyAny>,
1957    edge_indices: Py<PyAny>,
1958}
1959
1960impl Clone for PyPostAddGroupContext {
1961    fn clone(&self) -> Self {
1962        Python::attach(|py| Self {
1963            group: self.group.clone_ref(py),
1964            node_indices: self.node_indices.clone_ref(py),
1965            edge_indices: self.edge_indices.clone_ref(py),
1966        })
1967    }
1968}
1969
1970impl PyPostAddGroupContext {
1971    /// # Panics
1972    ///
1973    /// Panics if the python typing was not followed.
1974    pub fn bind(py: Python<'_>, context: PostAddGroupContext) -> Self {
1975        let node_indices: Option<Vec<PyNodeIndex>> = context.node_indices.deep_into();
1976
1977        Self {
1978            group: PyGroup::from(context.group)
1979                .into_py_any(py)
1980                .expect("PyGroup should be creatable"),
1981            node_indices: node_indices
1982                .into_py_any(py)
1983                .expect("node_indices should be creatable"),
1984            edge_indices: context
1985                .edge_indices
1986                .into_py_any(py)
1987                .expect("edge_indices should be creatable"),
1988        }
1989    }
1990}
1991
1992#[pymethods]
1993impl PyPostAddGroupContext {
1994    #[new]
1995    pub const fn new(group: Py<PyAny>, node_indices: Py<PyAny>, edge_indices: Py<PyAny>) -> Self {
1996        Self {
1997            group,
1998            node_indices,
1999            edge_indices,
2000        }
2001    }
2002
2003    #[getter]
2004    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2005        self.group.clone_ref(py)
2006    }
2007
2008    #[getter]
2009    pub fn node_indices(&self, py: Python<'_>) -> Py<PyAny> {
2010        self.node_indices.clone_ref(py)
2011    }
2012
2013    #[getter]
2014    pub fn edge_indices(&self, py: Python<'_>) -> Py<PyAny> {
2015        self.edge_indices.clone_ref(py)
2016    }
2017}
2018
2019#[pyclass(frozen)]
2020#[derive(Debug)]
2021pub struct PyPreRemoveGroupContext {
2022    group: Py<PyAny>,
2023}
2024
2025impl Clone for PyPreRemoveGroupContext {
2026    fn clone(&self) -> Self {
2027        Python::attach(|py| Self {
2028            group: self.group.clone_ref(py),
2029        })
2030    }
2031}
2032
2033impl PyPreRemoveGroupContext {
2034    /// # Panics
2035    ///
2036    /// Panics if the python typing was not followed.
2037    pub fn bind(py: Python<'_>, context: PreRemoveGroupContext) -> Self {
2038        Self {
2039            group: PyGroup::from(context.group)
2040                .into_py_any(py)
2041                .expect("PyGroup should be creatable"),
2042        }
2043    }
2044
2045    /// # Panics
2046    ///
2047    /// Panics if the python typing was not followed.
2048    pub fn extract(self, py: Python<'_>) -> PreRemoveGroupContext {
2049        let group: PyGroup = self
2050            .group
2051            .extract(py)
2052            .expect("PyGroup should be extractable");
2053
2054        PreRemoveGroupContext {
2055            group: group.into(),
2056        }
2057    }
2058}
2059
2060#[pymethods]
2061impl PyPreRemoveGroupContext {
2062    #[new]
2063    pub const fn new(group: Py<PyAny>) -> Self {
2064        Self { group }
2065    }
2066
2067    #[getter]
2068    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2069        self.group.clone_ref(py)
2070    }
2071}
2072
2073#[pyclass(frozen)]
2074#[derive(Debug)]
2075pub struct PyPostRemoveGroupContext {
2076    group: Py<PyAny>,
2077}
2078
2079impl Clone for PyPostRemoveGroupContext {
2080    fn clone(&self) -> Self {
2081        Python::attach(|py| Self {
2082            group: self.group.clone_ref(py),
2083        })
2084    }
2085}
2086
2087impl PyPostRemoveGroupContext {
2088    /// # Panics
2089    ///
2090    /// Panics if the python typing was not followed.
2091    pub fn bind(py: Python<'_>, context: PostRemoveGroupContext) -> Self {
2092        Self {
2093            group: PyGroup::from(context.group)
2094                .into_py_any(py)
2095                .expect("PyGroup should be creatable"),
2096        }
2097    }
2098}
2099
2100#[pymethods]
2101impl PyPostRemoveGroupContext {
2102    #[new]
2103    pub const fn new(group: Py<PyAny>) -> Self {
2104        Self { group }
2105    }
2106
2107    #[getter]
2108    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2109        self.group.clone_ref(py)
2110    }
2111}
2112
2113#[pyclass(frozen)]
2114#[derive(Debug)]
2115pub struct PyPreAddNodeToGroupContext {
2116    group: Py<PyAny>,
2117    node_index: Py<PyAny>,
2118}
2119
2120impl Clone for PyPreAddNodeToGroupContext {
2121    fn clone(&self) -> Self {
2122        Python::attach(|py| Self {
2123            group: self.group.clone_ref(py),
2124            node_index: self.node_index.clone_ref(py),
2125        })
2126    }
2127}
2128
2129impl PyPreAddNodeToGroupContext {
2130    /// # Panics
2131    ///
2132    /// Panics if the python typing was not followed.
2133    pub fn bind(py: Python<'_>, context: PreAddNodeToGroupContext) -> Self {
2134        Self {
2135            group: PyGroup::from(context.group)
2136                .into_py_any(py)
2137                .expect("PyGroup should be creatable"),
2138            node_index: PyNodeIndex::from(context.node_index)
2139                .into_py_any(py)
2140                .expect("PyNodeIndex should be creatable"),
2141        }
2142    }
2143
2144    /// # Panics
2145    ///
2146    /// Panics if the python typing was not followed.
2147    pub fn extract(self, py: Python<'_>) -> PreAddNodeToGroupContext {
2148        let group: PyGroup = self
2149            .group
2150            .extract(py)
2151            .expect("PyGroup should be extractable");
2152
2153        let node_index: PyNodeIndex = self
2154            .node_index
2155            .extract(py)
2156            .expect("PyNodeIndex should be extractable");
2157
2158        PreAddNodeToGroupContext {
2159            group: group.into(),
2160            node_index: node_index.into(),
2161        }
2162    }
2163}
2164
2165#[pymethods]
2166impl PyPreAddNodeToGroupContext {
2167    #[new]
2168    pub const fn new(group: Py<PyAny>, node_index: Py<PyAny>) -> Self {
2169        Self { group, node_index }
2170    }
2171
2172    #[getter]
2173    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2174        self.group.clone_ref(py)
2175    }
2176
2177    #[getter]
2178    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
2179        self.node_index.clone_ref(py)
2180    }
2181}
2182
2183#[pyclass(frozen)]
2184#[derive(Debug)]
2185pub struct PyPostAddNodeToGroupContext {
2186    group: Py<PyAny>,
2187    node_index: Py<PyAny>,
2188}
2189
2190impl Clone for PyPostAddNodeToGroupContext {
2191    fn clone(&self) -> Self {
2192        Python::attach(|py| Self {
2193            group: self.group.clone_ref(py),
2194            node_index: self.node_index.clone_ref(py),
2195        })
2196    }
2197}
2198
2199impl PyPostAddNodeToGroupContext {
2200    /// # Panics
2201    ///
2202    /// Panics if the python typing was not followed.
2203    pub fn bind(py: Python<'_>, context: PostAddNodeToGroupContext) -> Self {
2204        Self {
2205            group: PyGroup::from(context.group)
2206                .into_py_any(py)
2207                .expect("PyGroup should be creatable"),
2208            node_index: PyNodeIndex::from(context.node_index)
2209                .into_py_any(py)
2210                .expect("PyNodeIndex should be creatable"),
2211        }
2212    }
2213}
2214
2215#[pymethods]
2216impl PyPostAddNodeToGroupContext {
2217    #[new]
2218    pub const fn new(group: Py<PyAny>, node_index: Py<PyAny>) -> Self {
2219        Self { group, node_index }
2220    }
2221
2222    #[getter]
2223    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2224        self.group.clone_ref(py)
2225    }
2226
2227    #[getter]
2228    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
2229        self.node_index.clone_ref(py)
2230    }
2231}
2232
2233#[pyclass(frozen)]
2234#[derive(Debug)]
2235pub struct PyPreAddEdgeToGroupContext {
2236    group: Py<PyAny>,
2237    edge_index: Py<PyAny>,
2238}
2239
2240impl Clone for PyPreAddEdgeToGroupContext {
2241    fn clone(&self) -> Self {
2242        Python::attach(|py| Self {
2243            group: self.group.clone_ref(py),
2244            edge_index: self.edge_index.clone_ref(py),
2245        })
2246    }
2247}
2248
2249impl PyPreAddEdgeToGroupContext {
2250    /// # Panics
2251    ///
2252    /// Panics if the python typing was not followed.
2253    pub fn bind(py: Python<'_>, context: PreAddEdgeToGroupContext) -> Self {
2254        Self {
2255            group: PyGroup::from(context.group)
2256                .into_py_any(py)
2257                .expect("PyGroup should be creatable"),
2258            edge_index: context
2259                .edge_index
2260                .into_py_any(py)
2261                .expect("edge_index should be creatable"),
2262        }
2263    }
2264
2265    /// # Panics
2266    ///
2267    /// Panics if the python typing was not followed.
2268    pub fn extract(self, py: Python<'_>) -> PreAddEdgeToGroupContext {
2269        let group: PyGroup = self
2270            .group
2271            .extract(py)
2272            .expect("PyGroup should be extractable");
2273
2274        PreAddEdgeToGroupContext {
2275            group: group.into(),
2276            edge_index: self
2277                .edge_index
2278                .extract(py)
2279                .expect("edge_index should be extractable"),
2280        }
2281    }
2282}
2283
2284#[pymethods]
2285impl PyPreAddEdgeToGroupContext {
2286    #[new]
2287    pub const fn new(group: Py<PyAny>, edge_index: Py<PyAny>) -> Self {
2288        Self { group, edge_index }
2289    }
2290
2291    #[getter]
2292    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2293        self.group.clone_ref(py)
2294    }
2295
2296    #[getter]
2297    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
2298        self.edge_index.clone_ref(py)
2299    }
2300}
2301
2302#[pyclass(frozen)]
2303#[derive(Debug)]
2304pub struct PyPostAddEdgeToGroupContext {
2305    group: Py<PyAny>,
2306    edge_index: Py<PyAny>,
2307}
2308
2309impl Clone for PyPostAddEdgeToGroupContext {
2310    fn clone(&self) -> Self {
2311        Python::attach(|py| Self {
2312            group: self.group.clone_ref(py),
2313            edge_index: self.edge_index.clone_ref(py),
2314        })
2315    }
2316}
2317
2318impl PyPostAddEdgeToGroupContext {
2319    /// # Panics
2320    ///
2321    /// Panics if the python typing was not followed.
2322    pub fn bind(py: Python<'_>, context: PostAddEdgeToGroupContext) -> Self {
2323        Self {
2324            group: PyGroup::from(context.group)
2325                .into_py_any(py)
2326                .expect("PyGroup should be creatable"),
2327            edge_index: context
2328                .edge_index
2329                .into_py_any(py)
2330                .expect("edge_index should be creatable"),
2331        }
2332    }
2333}
2334
2335#[pymethods]
2336impl PyPostAddEdgeToGroupContext {
2337    #[new]
2338    pub const fn new(group: Py<PyAny>, edge_index: Py<PyAny>) -> Self {
2339        Self { group, edge_index }
2340    }
2341
2342    #[getter]
2343    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2344        self.group.clone_ref(py)
2345    }
2346
2347    #[getter]
2348    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
2349        self.edge_index.clone_ref(py)
2350    }
2351}
2352
2353#[pyclass(frozen)]
2354#[derive(Debug)]
2355pub struct PyPreRemoveNodeFromGroupContext {
2356    group: Py<PyAny>,
2357    node_index: Py<PyAny>,
2358}
2359
2360impl Clone for PyPreRemoveNodeFromGroupContext {
2361    fn clone(&self) -> Self {
2362        Python::attach(|py| Self {
2363            group: self.group.clone_ref(py),
2364            node_index: self.node_index.clone_ref(py),
2365        })
2366    }
2367}
2368
2369impl PyPreRemoveNodeFromGroupContext {
2370    /// # Panics
2371    ///
2372    /// Panics if the python typing was not followed.
2373    pub fn bind(py: Python<'_>, context: PreRemoveNodeFromGroupContext) -> Self {
2374        Self {
2375            group: PyGroup::from(context.group)
2376                .into_py_any(py)
2377                .expect("PyGroup should be creatable"),
2378            node_index: PyNodeIndex::from(context.node_index)
2379                .into_py_any(py)
2380                .expect("PyNodeIndex should be creatable"),
2381        }
2382    }
2383
2384    /// # Panics
2385    ///
2386    /// Panics if the python typing was not followed.
2387    pub fn extract(self, py: Python<'_>) -> PreRemoveNodeFromGroupContext {
2388        let group: PyGroup = self
2389            .group
2390            .extract(py)
2391            .expect("PyGroup should be extractable");
2392
2393        let node_index: PyNodeIndex = self
2394            .node_index
2395            .extract(py)
2396            .expect("PyNodeIndex should be extractable");
2397
2398        PreRemoveNodeFromGroupContext {
2399            group: group.into(),
2400            node_index: node_index.into(),
2401        }
2402    }
2403}
2404
2405#[pymethods]
2406impl PyPreRemoveNodeFromGroupContext {
2407    #[new]
2408    pub const fn new(group: Py<PyAny>, node_index: Py<PyAny>) -> Self {
2409        Self { group, node_index }
2410    }
2411
2412    #[getter]
2413    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2414        self.group.clone_ref(py)
2415    }
2416
2417    #[getter]
2418    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
2419        self.node_index.clone_ref(py)
2420    }
2421}
2422
2423#[pyclass(frozen)]
2424#[derive(Debug)]
2425pub struct PyPostRemoveNodeFromGroupContext {
2426    group: Py<PyAny>,
2427    node_index: Py<PyAny>,
2428}
2429
2430impl Clone for PyPostRemoveNodeFromGroupContext {
2431    fn clone(&self) -> Self {
2432        Python::attach(|py| Self {
2433            group: self.group.clone_ref(py),
2434            node_index: self.node_index.clone_ref(py),
2435        })
2436    }
2437}
2438
2439impl PyPostRemoveNodeFromGroupContext {
2440    /// # Panics
2441    ///
2442    /// Panics if the python typing was not followed.
2443    pub fn bind(py: Python<'_>, context: PostRemoveNodeFromGroupContext) -> Self {
2444        Self {
2445            group: PyGroup::from(context.group)
2446                .into_py_any(py)
2447                .expect("PyGroup should be creatable"),
2448            node_index: PyNodeIndex::from(context.node_index)
2449                .into_py_any(py)
2450                .expect("PyNodeIndex should be creatable"),
2451        }
2452    }
2453}
2454
2455#[pymethods]
2456impl PyPostRemoveNodeFromGroupContext {
2457    #[new]
2458    pub const fn new(group: Py<PyAny>, node_index: Py<PyAny>) -> Self {
2459        Self { group, node_index }
2460    }
2461
2462    #[getter]
2463    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2464        self.group.clone_ref(py)
2465    }
2466
2467    #[getter]
2468    pub fn node_index(&self, py: Python<'_>) -> Py<PyAny> {
2469        self.node_index.clone_ref(py)
2470    }
2471}
2472
2473#[pyclass(frozen)]
2474#[derive(Debug)]
2475pub struct PyPreRemoveEdgeFromGroupContext {
2476    group: Py<PyAny>,
2477    edge_index: Py<PyAny>,
2478}
2479
2480impl Clone for PyPreRemoveEdgeFromGroupContext {
2481    fn clone(&self) -> Self {
2482        Python::attach(|py| Self {
2483            group: self.group.clone_ref(py),
2484            edge_index: self.edge_index.clone_ref(py),
2485        })
2486    }
2487}
2488
2489impl PyPreRemoveEdgeFromGroupContext {
2490    /// # Panics
2491    ///
2492    /// Panics if the python typing was not followed.
2493    pub fn bind(py: Python<'_>, context: PreRemoveEdgeFromGroupContext) -> Self {
2494        Self {
2495            group: PyGroup::from(context.group)
2496                .into_py_any(py)
2497                .expect("PyGroup should be creatable"),
2498            edge_index: context
2499                .edge_index
2500                .into_py_any(py)
2501                .expect("edge_index should be creatable"),
2502        }
2503    }
2504
2505    /// # Panics
2506    ///
2507    /// Panics if the python typing was not followed.
2508    pub fn extract(self, py: Python<'_>) -> PreRemoveEdgeFromGroupContext {
2509        let group: PyGroup = self
2510            .group
2511            .extract(py)
2512            .expect("PyGroup should be extractable");
2513
2514        PreRemoveEdgeFromGroupContext {
2515            group: group.into(),
2516            edge_index: self
2517                .edge_index
2518                .extract(py)
2519                .expect("edge_index should be extractable"),
2520        }
2521    }
2522}
2523
2524#[pymethods]
2525impl PyPreRemoveEdgeFromGroupContext {
2526    #[new]
2527    pub const fn new(group: Py<PyAny>, edge_index: Py<PyAny>) -> Self {
2528        Self { group, edge_index }
2529    }
2530
2531    #[getter]
2532    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2533        self.group.clone_ref(py)
2534    }
2535
2536    #[getter]
2537    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
2538        self.edge_index.clone_ref(py)
2539    }
2540}
2541
2542#[pyclass(frozen)]
2543#[derive(Debug)]
2544pub struct PyPostRemoveEdgeFromGroupContext {
2545    group: Py<PyAny>,
2546    edge_index: Py<PyAny>,
2547}
2548
2549impl Clone for PyPostRemoveEdgeFromGroupContext {
2550    fn clone(&self) -> Self {
2551        Python::attach(|py| Self {
2552            group: self.group.clone_ref(py),
2553            edge_index: self.edge_index.clone_ref(py),
2554        })
2555    }
2556}
2557
2558impl PyPostRemoveEdgeFromGroupContext {
2559    /// # Panics
2560    ///
2561    /// Panics if the python typing was not followed.
2562    pub fn bind(py: Python<'_>, context: PostRemoveEdgeFromGroupContext) -> Self {
2563        Self {
2564            group: PyGroup::from(context.group)
2565                .into_py_any(py)
2566                .expect("PyGroup should be creatable"),
2567            edge_index: context
2568                .edge_index
2569                .into_py_any(py)
2570                .expect("edge_index should be creatable"),
2571        }
2572    }
2573}
2574
2575#[pymethods]
2576impl PyPostRemoveEdgeFromGroupContext {
2577    #[new]
2578    pub const fn new(group: Py<PyAny>, edge_index: Py<PyAny>) -> Self {
2579        Self { group, edge_index }
2580    }
2581
2582    #[getter]
2583    pub fn group(&self, py: Python<'_>) -> Py<PyAny> {
2584        self.group.clone_ref(py)
2585    }
2586
2587    #[getter]
2588    pub fn edge_index(&self, py: Python<'_>) -> Py<PyAny> {
2589        self.edge_index.clone_ref(py)
2590    }
2591}
2592
2593#[typetag::serde]
2594impl Plugin for PyPlugin {
2595    fn clone_box(&self) -> Box<dyn Plugin> {
2596        Python::attach(|py| Box::new(Self(self.0.clone_ref(py))))
2597    }
2598
2599    fn initialize(&self, graphrecord: &mut GraphRecord) -> GraphRecordResult<()> {
2600        Python::attach(|py| {
2601            PyGraphRecord::scope_mut(py, graphrecord, |py, graphrecord| {
2602                self.0
2603                    .call_method1(py, "initialize", (graphrecord,))
2604                    .map_err(|err| GraphRecordError::ConversionError(format!("{err}")))?;
2605
2606                Ok(())
2607            })
2608        })
2609    }
2610
2611    fn finalize(&self, graphrecord: &mut GraphRecord) -> GraphRecordResult<()> {
2612        Python::attach(|py| {
2613            PyGraphRecord::scope_mut(py, graphrecord, |py, graphrecord| {
2614                self.0
2615                    .call_method1(py, "finalize", (graphrecord,))
2616                    .map_err(|err| GraphRecordError::ConversionError(format!("{err}")))?;
2617
2618                Ok(())
2619            })
2620        })
2621    }
2622
2623    impl_pre_hook!(pre_set_schema, PyPreSetSchemaContext, PreSetSchemaContext);
2624    impl_post_hook!(post_set_schema);
2625    impl_post_hook!(pre_freeze_schema);
2626    impl_post_hook!(post_freeze_schema);
2627    impl_post_hook!(pre_unfreeze_schema);
2628    impl_post_hook!(post_unfreeze_schema);
2629    impl_pre_hook!(pre_add_node, PyPreAddNodeContext, PreAddNodeContext);
2630    impl_post_hook!(post_add_node, PyPostAddNodeContext, PostAddNodeContext);
2631    impl_pre_hook!(
2632        pre_add_node_with_group,
2633        PyPreAddNodeWithGroupContext,
2634        PreAddNodeWithGroupContext
2635    );
2636    impl_post_hook!(
2637        post_add_node_with_group,
2638        PyPostAddNodeWithGroupContext,
2639        PostAddNodeWithGroupContext
2640    );
2641    impl_pre_hook!(
2642        pre_remove_node,
2643        PyPreRemoveNodeContext,
2644        PreRemoveNodeContext
2645    );
2646    impl_post_hook!(
2647        post_remove_node,
2648        PyPostRemoveNodeContext,
2649        PostRemoveNodeContext
2650    );
2651    impl_pre_hook!(pre_add_nodes, PyPreAddNodesContext, PreAddNodesContext);
2652    impl_post_hook!(post_add_nodes, PyPostAddNodesContext, PostAddNodesContext);
2653    impl_pre_hook!(
2654        pre_add_nodes_with_group,
2655        PyPreAddNodesWithGroupContext,
2656        PreAddNodesWithGroupContext
2657    );
2658    impl_post_hook!(
2659        post_add_nodes_with_group,
2660        PyPostAddNodesWithGroupContext,
2661        PostAddNodesWithGroupContext
2662    );
2663    impl_pre_hook!(
2664        pre_add_nodes_dataframes,
2665        PyPreAddNodesDataframesContext,
2666        PreAddNodesDataframesContext
2667    );
2668    impl_post_hook!(
2669        post_add_nodes_dataframes,
2670        PyPostAddNodesDataframesContext,
2671        PostAddNodesDataframesContext
2672    );
2673    impl_pre_hook!(
2674        pre_add_nodes_dataframes_with_group,
2675        PyPreAddNodesDataframesWithGroupContext,
2676        PreAddNodesDataframesWithGroupContext
2677    );
2678    impl_post_hook!(
2679        post_add_nodes_dataframes_with_group,
2680        PyPostAddNodesDataframesWithGroupContext,
2681        PostAddNodesDataframesWithGroupContext
2682    );
2683    impl_pre_hook!(pre_add_edge, PyPreAddEdgeContext, PreAddEdgeContext);
2684    impl_post_hook!(post_add_edge, PyPostAddEdgeContext, PostAddEdgeContext);
2685    impl_pre_hook!(
2686        pre_add_edge_with_group,
2687        PyPreAddEdgeWithGroupContext,
2688        PreAddEdgeWithGroupContext
2689    );
2690    impl_post_hook!(
2691        post_add_edge_with_group,
2692        PyPostAddEdgeWithGroupContext,
2693        PostAddEdgeWithGroupContext
2694    );
2695    impl_pre_hook!(
2696        pre_remove_edge,
2697        PyPreRemoveEdgeContext,
2698        PreRemoveEdgeContext
2699    );
2700    impl_post_hook!(
2701        post_remove_edge,
2702        PyPostRemoveEdgeContext,
2703        PostRemoveEdgeContext
2704    );
2705    impl_pre_hook!(pre_add_edges, PyPreAddEdgesContext, PreAddEdgesContext);
2706    impl_post_hook!(post_add_edges, PyPostAddEdgesContext, PostAddEdgesContext);
2707    impl_pre_hook!(
2708        pre_add_edges_with_group,
2709        PyPreAddEdgesWithGroupContext,
2710        PreAddEdgesWithGroupContext
2711    );
2712    impl_post_hook!(
2713        post_add_edges_with_group,
2714        PyPostAddEdgesWithGroupContext,
2715        PostAddEdgesWithGroupContext
2716    );
2717    impl_pre_hook!(
2718        pre_add_edges_dataframes,
2719        PyPreAddEdgesDataframesContext,
2720        PreAddEdgesDataframesContext
2721    );
2722    impl_post_hook!(
2723        post_add_edges_dataframes,
2724        PyPostAddEdgesDataframesContext,
2725        PostAddEdgesDataframesContext
2726    );
2727    impl_pre_hook!(
2728        pre_add_edges_dataframes_with_group,
2729        PyPreAddEdgesDataframesWithGroupContext,
2730        PreAddEdgesDataframesWithGroupContext
2731    );
2732    impl_post_hook!(
2733        post_add_edges_dataframes_with_group,
2734        PyPostAddEdgesDataframesWithGroupContext,
2735        PostAddEdgesDataframesWithGroupContext
2736    );
2737    impl_pre_hook!(pre_add_group, PyPreAddGroupContext, PreAddGroupContext);
2738    impl_post_hook!(post_add_group, PyPostAddGroupContext, PostAddGroupContext);
2739    impl_pre_hook!(
2740        pre_remove_group,
2741        PyPreRemoveGroupContext,
2742        PreRemoveGroupContext
2743    );
2744    impl_post_hook!(
2745        post_remove_group,
2746        PyPostRemoveGroupContext,
2747        PostRemoveGroupContext
2748    );
2749    impl_pre_hook!(
2750        pre_add_node_to_group,
2751        PyPreAddNodeToGroupContext,
2752        PreAddNodeToGroupContext
2753    );
2754    impl_post_hook!(
2755        post_add_node_to_group,
2756        PyPostAddNodeToGroupContext,
2757        PostAddNodeToGroupContext
2758    );
2759    impl_pre_hook!(
2760        pre_add_edge_to_group,
2761        PyPreAddEdgeToGroupContext,
2762        PreAddEdgeToGroupContext
2763    );
2764    impl_post_hook!(
2765        post_add_edge_to_group,
2766        PyPostAddEdgeToGroupContext,
2767        PostAddEdgeToGroupContext
2768    );
2769    impl_pre_hook!(
2770        pre_remove_node_from_group,
2771        PyPreRemoveNodeFromGroupContext,
2772        PreRemoveNodeFromGroupContext
2773    );
2774    impl_post_hook!(
2775        post_remove_node_from_group,
2776        PyPostRemoveNodeFromGroupContext,
2777        PostRemoveNodeFromGroupContext
2778    );
2779    impl_pre_hook!(
2780        pre_remove_edge_from_group,
2781        PyPreRemoveEdgeFromGroupContext,
2782        PreRemoveEdgeFromGroupContext
2783    );
2784    impl_post_hook!(
2785        post_remove_edge_from_group,
2786        PyPostRemoveEdgeFromGroupContext,
2787        PostRemoveEdgeFromGroupContext
2788    );
2789    impl_post_hook!(pre_clear);
2790    impl_post_hook!(post_clear);
2791}