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