1use super::{
2 PyGraphRecordAttributeCardinalityWrapper, PyGroupCardinalityWrapper,
3 attributes::PyNodeAttributesTreeOperand, edges::PyEdgeOperand,
4};
5use crate::graphrecord::{
6 PyNodeIndex,
7 attribute::PyGraphRecordAttribute,
8 errors::PyGraphRecordError,
9 querying::{
10 attributes::PyNodeAttributesTreeGroupOperand,
11 edges::PyEdgeGroupOperand,
12 values::{PyNodeMultipleValuesWithIndexGroupOperand, PyNodeMultipleValuesWithIndexOperand},
13 },
14};
15use graphrecords_core::{
16 errors::GraphRecordError,
17 graphrecord::{
18 NodeIndex,
19 querying::{
20 DeepClone,
21 group_by::GroupOperand,
22 nodes::{
23 self, EdgeDirection, NodeIndexComparisonOperand, NodeIndexOperand,
24 NodeIndicesComparisonOperand, NodeIndicesOperand, NodeOperand,
25 },
26 wrapper::Wrapper,
27 },
28 },
29};
30use pyo3::{
31 Borrowed, Bound, FromPyObject, PyAny, PyErr, PyResult, pyclass, pymethods,
32 types::{PyAnyMethods, PyFunction},
33};
34use std::ops::Deref;
35
36#[pyclass(frozen, eq, eq_int)]
37#[derive(Clone, PartialEq, Eq)]
38pub enum PyEdgeDirection {
39 Incoming = 0,
40 Outgoing = 1,
41 Both = 2,
42}
43
44impl From<EdgeDirection> for PyEdgeDirection {
45 fn from(value: EdgeDirection) -> Self {
46 match value {
47 EdgeDirection::Incoming => Self::Incoming,
48 EdgeDirection::Outgoing => Self::Outgoing,
49 EdgeDirection::Both => Self::Both,
50 }
51 }
52}
53
54impl From<PyEdgeDirection> for EdgeDirection {
55 fn from(value: PyEdgeDirection) -> Self {
56 match value {
57 PyEdgeDirection::Incoming => Self::Incoming,
58 PyEdgeDirection::Outgoing => Self::Outgoing,
59 PyEdgeDirection::Both => Self::Both,
60 }
61 }
62}
63
64#[pyclass(frozen)]
65#[derive(Clone)]
66pub enum NodeOperandGroupDiscriminator {
67 Attribute(PyGraphRecordAttribute),
68}
69
70impl From<NodeOperandGroupDiscriminator> for nodes::NodeOperandGroupDiscriminator {
71 fn from(value: NodeOperandGroupDiscriminator) -> Self {
72 match value {
73 NodeOperandGroupDiscriminator::Attribute(attribute) => {
74 Self::Attribute(attribute.into())
75 }
76 }
77 }
78}
79
80#[pyclass(frozen)]
81#[repr(transparent)]
82pub struct PyNodeOperand(Wrapper<NodeOperand>);
83
84impl From<Wrapper<NodeOperand>> for PyNodeOperand {
85 fn from(operand: Wrapper<NodeOperand>) -> Self {
86 Self(operand)
87 }
88}
89
90impl From<PyNodeOperand> for Wrapper<NodeOperand> {
91 fn from(operand: PyNodeOperand) -> Self {
92 operand.0
93 }
94}
95
96#[pymethods]
97impl PyNodeOperand {
98 pub fn attribute(
99 &self,
100 attribute: PyGraphRecordAttribute,
101 ) -> PyNodeMultipleValuesWithIndexOperand {
102 self.0.attribute(attribute).into()
103 }
104
105 pub fn attributes(&self) -> PyNodeAttributesTreeOperand {
106 self.0.attributes().into()
107 }
108
109 pub fn index(&self) -> PyNodeIndicesOperand {
110 self.0.index().into()
111 }
112
113 pub fn in_group(&self, group: PyGroupCardinalityWrapper) {
114 self.0.in_group(group);
115 }
116
117 pub fn has_attribute(&self, attribute: PyGraphRecordAttributeCardinalityWrapper) {
118 self.0.has_attribute(attribute);
119 }
120
121 pub fn edges(&self, direction: PyEdgeDirection) -> PyEdgeOperand {
122 self.0.edges(direction.into()).into()
123 }
124
125 pub fn neighbors(&self, direction: PyEdgeDirection) -> Self {
126 self.0.neighbors(direction.into()).into()
127 }
128
129 pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
133 self.0.either_or(
134 |operand| {
135 either
136 .call1((Self::from(operand.clone()),))
137 .expect("Call must succeed");
138 },
139 |operand| {
140 or.call1((Self::from(operand.clone()),))
141 .expect("Call must succeed");
142 },
143 );
144 }
145
146 pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
150 self.0.exclude(|operand| {
151 query
152 .call1((Self::from(operand.clone()),))
153 .expect("Call must succeed");
154 });
155 }
156
157 pub fn group_by(&self, discriminator: NodeOperandGroupDiscriminator) -> PyNodeGroupOperand {
158 self.0.group_by(discriminator.into()).into()
159 }
160
161 pub fn deep_clone(&self) -> Self {
162 self.0.deep_clone().into()
163 }
164}
165
166#[pyclass(frozen)]
167#[repr(transparent)]
168pub struct PyNodeGroupOperand(Wrapper<GroupOperand<NodeOperand>>);
169
170impl From<Wrapper<GroupOperand<NodeOperand>>> for PyNodeGroupOperand {
171 fn from(operand: Wrapper<GroupOperand<NodeOperand>>) -> Self {
172 Self(operand)
173 }
174}
175
176impl From<PyNodeGroupOperand> for Wrapper<GroupOperand<NodeOperand>> {
177 fn from(operand: PyNodeGroupOperand) -> Self {
178 operand.0
179 }
180}
181
182#[pymethods]
183impl PyNodeGroupOperand {
184 pub fn attribute(
185 &self,
186 attribute: PyGraphRecordAttribute,
187 ) -> PyNodeMultipleValuesWithIndexGroupOperand {
188 self.0.attribute(attribute).into()
189 }
190
191 pub fn attributes(&self) -> PyNodeAttributesTreeGroupOperand {
192 self.0.attributes().into()
193 }
194
195 pub fn index(&self) -> PyNodeIndicesGroupOperand {
196 self.0.index().into()
197 }
198
199 pub fn in_group(&self, group: PyGroupCardinalityWrapper) {
200 self.0.in_group(group);
201 }
202
203 pub fn has_attribute(&self, attribute: PyGraphRecordAttributeCardinalityWrapper) {
204 self.0.has_attribute(attribute);
205 }
206
207 pub fn edges(&self, direction: PyEdgeDirection) -> PyEdgeGroupOperand {
208 self.0.edges(direction.into()).into()
209 }
210
211 pub fn neighbors(&self, direction: PyEdgeDirection) -> Self {
212 self.0.neighbors(direction.into()).into()
213 }
214 pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
218 self.0.either_or(
219 |operand| {
220 either
221 .call1((PyNodeOperand::from(operand.clone()),))
222 .expect("Call must succeed");
223 },
224 |operand| {
225 or.call1((PyNodeOperand::from(operand.clone()),))
226 .expect("Call must succeed");
227 },
228 );
229 }
230
231 pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
235 self.0.exclude(|operand| {
236 query
237 .call1((PyNodeOperand::from(operand.clone()),))
238 .expect("Call must succeed");
239 });
240 }
241
242 pub fn deep_clone(&self) -> Self {
243 self.0.deep_clone().into()
244 }
245}
246
247#[repr(transparent)]
248pub struct PyNodeIndexComparisonOperand(NodeIndexComparisonOperand);
249
250impl From<NodeIndexComparisonOperand> for PyNodeIndexComparisonOperand {
251 fn from(operand: NodeIndexComparisonOperand) -> Self {
252 Self(operand)
253 }
254}
255
256impl From<PyNodeIndexComparisonOperand> for NodeIndexComparisonOperand {
257 fn from(operand: PyNodeIndexComparisonOperand) -> Self {
258 operand.0
259 }
260}
261
262impl FromPyObject<'_, '_> for PyNodeIndexComparisonOperand {
263 type Error = PyErr;
264
265 fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
266 match ob.extract::<PyNodeIndex>() {
267 Ok(index) => Ok(NodeIndexComparisonOperand::Index(NodeIndex::from(index)).into()),
268 _ => match ob.extract::<PyNodeIndexOperand>() {
269 Ok(operand) => Ok(Self(operand.0.into())),
270 _ => Err(
271 PyGraphRecordError::from(GraphRecordError::ConversionError(format!(
272 "Failed to convert {} into NodeIndex or NodeIndexOperand",
273 ob.to_owned()
274 )))
275 .into(),
276 ),
277 },
278 }
279 }
280}
281
282#[repr(transparent)]
283pub struct PyNodeIndicesComparisonOperand(NodeIndicesComparisonOperand);
284
285impl From<NodeIndicesComparisonOperand> for PyNodeIndicesComparisonOperand {
286 fn from(operand: NodeIndicesComparisonOperand) -> Self {
287 Self(operand)
288 }
289}
290
291impl From<PyNodeIndicesComparisonOperand> for NodeIndicesComparisonOperand {
292 fn from(operand: PyNodeIndicesComparisonOperand) -> Self {
293 operand.0
294 }
295}
296
297impl FromPyObject<'_, '_> for PyNodeIndicesComparisonOperand {
298 type Error = PyErr;
299
300 fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {
301 match ob.extract::<Vec<PyNodeIndex>>() {
302 Ok(indices) => Ok(NodeIndicesComparisonOperand::Indices(
303 indices.into_iter().map(NodeIndex::from).collect(),
304 )
305 .into()),
306 _ => match ob.extract::<PyNodeIndicesOperand>() {
307 Ok(operand) => Ok(Self(operand.0.into())),
308 _ => Err(
309 PyGraphRecordError::from(GraphRecordError::ConversionError(format!(
310 "Failed to convert {} into List[NodeIndex] or NodeIndicesOperand",
311 ob.to_owned()
312 )))
313 .into(),
314 ),
315 },
316 }
317 }
318}
319
320#[pyclass(frozen)]
321#[repr(transparent)]
322#[derive(Clone)]
323pub struct PyNodeIndicesOperand(Wrapper<NodeIndicesOperand>);
324
325impl From<Wrapper<NodeIndicesOperand>> for PyNodeIndicesOperand {
326 fn from(operand: Wrapper<NodeIndicesOperand>) -> Self {
327 Self(operand)
328 }
329}
330
331impl From<PyNodeIndicesOperand> for Wrapper<NodeIndicesOperand> {
332 fn from(operand: PyNodeIndicesOperand) -> Self {
333 operand.0
334 }
335}
336
337impl Deref for PyNodeIndicesOperand {
338 type Target = Wrapper<NodeIndicesOperand>;
339
340 fn deref(&self) -> &Self::Target {
341 &self.0
342 }
343}
344
345#[pymethods]
346impl PyNodeIndicesOperand {
347 pub fn max(&self) -> PyNodeIndexOperand {
348 self.0.max().into()
349 }
350
351 pub fn min(&self) -> PyNodeIndexOperand {
352 self.0.min().into()
353 }
354
355 pub fn count(&self) -> PyNodeIndexOperand {
356 self.0.count().into()
357 }
358
359 pub fn sum(&self) -> PyNodeIndexOperand {
360 self.0.sum().into()
361 }
362
363 pub fn random(&self) -> PyNodeIndexOperand {
364 self.0.random().into()
365 }
366
367 pub fn greater_than(&self, index: PyNodeIndexComparisonOperand) {
368 self.0.greater_than(index);
369 }
370
371 pub fn greater_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
372 self.0.greater_than_or_equal_to(index);
373 }
374
375 pub fn less_than(&self, index: PyNodeIndexComparisonOperand) {
376 self.0.less_than(index);
377 }
378
379 pub fn less_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
380 self.0.less_than_or_equal_to(index);
381 }
382
383 pub fn equal_to(&self, index: PyNodeIndexComparisonOperand) {
384 self.0.equal_to(index);
385 }
386
387 pub fn not_equal_to(&self, index: PyNodeIndexComparisonOperand) {
388 self.0.not_equal_to(index);
389 }
390
391 pub fn starts_with(&self, index: PyNodeIndexComparisonOperand) {
392 self.0.starts_with(index);
393 }
394
395 pub fn ends_with(&self, index: PyNodeIndexComparisonOperand) {
396 self.0.ends_with(index);
397 }
398
399 pub fn contains(&self, index: PyNodeIndexComparisonOperand) {
400 self.0.contains(index);
401 }
402
403 pub fn is_in(&self, indices: PyNodeIndicesComparisonOperand) {
404 self.0.is_in(indices);
405 }
406
407 pub fn is_not_in(&self, indices: PyNodeIndicesComparisonOperand) {
408 self.0.is_not_in(indices);
409 }
410
411 pub fn add(&self, index: PyNodeIndexComparisonOperand) {
412 self.0.add(index);
413 }
414
415 pub fn sub(&self, index: PyNodeIndexComparisonOperand) {
416 self.0.sub(index);
417 }
418
419 pub fn mul(&self, index: PyNodeIndexComparisonOperand) {
420 self.0.mul(index);
421 }
422
423 pub fn pow(&self, index: PyNodeIndexComparisonOperand) {
424 self.0.pow(index);
425 }
426
427 pub fn r#mod(&self, index: PyNodeIndexComparisonOperand) {
428 self.0.r#mod(index);
429 }
430
431 pub fn abs(&self) {
432 self.0.abs();
433 }
434
435 pub fn trim(&self) {
436 self.0.trim();
437 }
438
439 pub fn trim_start(&self) {
440 self.0.trim_start();
441 }
442
443 pub fn trim_end(&self) {
444 self.0.trim_end();
445 }
446
447 pub fn lowercase(&self) {
448 self.0.lowercase();
449 }
450
451 pub fn uppercase(&self) {
452 self.0.uppercase();
453 }
454
455 pub fn slice(&self, start: usize, end: usize) {
456 self.0.slice(start, end);
457 }
458
459 pub fn is_string(&self) {
460 self.0.is_string();
461 }
462
463 pub fn is_int(&self) {
464 self.0.is_int();
465 }
466
467 pub fn is_max(&self) {
468 self.0.is_max();
469 }
470
471 pub fn is_min(&self) {
472 self.0.is_min();
473 }
474
475 pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
479 self.0.either_or(
480 |operand| {
481 either
482 .call1((Self::from(operand.clone()),))
483 .expect("Call must succeed");
484 },
485 |operand| {
486 or.call1((Self::from(operand.clone()),))
487 .expect("Call must succeed");
488 },
489 );
490 }
491
492 pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
496 self.0.exclude(|operand| {
497 query
498 .call1((Self::from(operand.clone()),))
499 .expect("Call must succeed");
500 });
501 }
502
503 pub fn deep_clone(&self) -> Self {
504 self.0.deep_clone().into()
505 }
506}
507
508#[pyclass(frozen)]
509#[repr(transparent)]
510#[derive(Clone)]
511pub struct PyNodeIndicesGroupOperand(Wrapper<GroupOperand<NodeIndicesOperand>>);
512
513impl From<Wrapper<GroupOperand<NodeIndicesOperand>>> for PyNodeIndicesGroupOperand {
514 fn from(operand: Wrapper<GroupOperand<NodeIndicesOperand>>) -> Self {
515 Self(operand)
516 }
517}
518
519impl From<PyNodeIndicesGroupOperand> for Wrapper<GroupOperand<NodeIndicesOperand>> {
520 fn from(operand: PyNodeIndicesGroupOperand) -> Self {
521 operand.0
522 }
523}
524
525impl Deref for PyNodeIndicesGroupOperand {
526 type Target = Wrapper<GroupOperand<NodeIndicesOperand>>;
527
528 fn deref(&self) -> &Self::Target {
529 &self.0
530 }
531}
532
533#[pymethods]
534impl PyNodeIndicesGroupOperand {
535 pub fn max(&self) -> PyNodeIndexGroupOperand {
536 self.0.max().into()
537 }
538
539 pub fn min(&self) -> PyNodeIndexGroupOperand {
540 self.0.min().into()
541 }
542
543 pub fn count(&self) -> PyNodeIndexGroupOperand {
544 self.0.count().into()
545 }
546
547 pub fn sum(&self) -> PyNodeIndexGroupOperand {
548 self.0.sum().into()
549 }
550
551 pub fn random(&self) -> PyNodeIndexGroupOperand {
552 self.0.random().into()
553 }
554
555 pub fn greater_than(&self, index: PyNodeIndexComparisonOperand) {
556 self.0.greater_than(index);
557 }
558
559 pub fn greater_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
560 self.0.greater_than_or_equal_to(index);
561 }
562
563 pub fn less_than(&self, index: PyNodeIndexComparisonOperand) {
564 self.0.less_than(index);
565 }
566
567 pub fn less_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
568 self.0.less_than_or_equal_to(index);
569 }
570
571 pub fn equal_to(&self, index: PyNodeIndexComparisonOperand) {
572 self.0.equal_to(index);
573 }
574
575 pub fn not_equal_to(&self, index: PyNodeIndexComparisonOperand) {
576 self.0.not_equal_to(index);
577 }
578
579 pub fn starts_with(&self, index: PyNodeIndexComparisonOperand) {
580 self.0.starts_with(index);
581 }
582
583 pub fn ends_with(&self, index: PyNodeIndexComparisonOperand) {
584 self.0.ends_with(index);
585 }
586
587 pub fn contains(&self, index: PyNodeIndexComparisonOperand) {
588 self.0.contains(index);
589 }
590
591 pub fn is_in(&self, indices: PyNodeIndicesComparisonOperand) {
592 self.0.is_in(indices);
593 }
594
595 pub fn is_not_in(&self, indices: PyNodeIndicesComparisonOperand) {
596 self.0.is_not_in(indices);
597 }
598
599 pub fn add(&self, index: PyNodeIndexComparisonOperand) {
600 self.0.add(index);
601 }
602
603 pub fn sub(&self, index: PyNodeIndexComparisonOperand) {
604 self.0.sub(index);
605 }
606
607 pub fn mul(&self, index: PyNodeIndexComparisonOperand) {
608 self.0.mul(index);
609 }
610
611 pub fn pow(&self, index: PyNodeIndexComparisonOperand) {
612 self.0.pow(index);
613 }
614
615 pub fn r#mod(&self, index: PyNodeIndexComparisonOperand) {
616 self.0.r#mod(index);
617 }
618
619 pub fn abs(&self) {
620 self.0.abs();
621 }
622
623 pub fn trim(&self) {
624 self.0.trim();
625 }
626
627 pub fn trim_start(&self) {
628 self.0.trim_start();
629 }
630
631 pub fn trim_end(&self) {
632 self.0.trim_end();
633 }
634
635 pub fn lowercase(&self) {
636 self.0.lowercase();
637 }
638
639 pub fn uppercase(&self) {
640 self.0.uppercase();
641 }
642
643 pub fn slice(&self, start: usize, end: usize) {
644 self.0.slice(start, end);
645 }
646
647 pub fn is_string(&self) {
648 self.0.is_string();
649 }
650
651 pub fn is_int(&self) {
652 self.0.is_int();
653 }
654
655 pub fn is_max(&self) {
656 self.0.is_max();
657 }
658
659 pub fn is_min(&self) {
660 self.0.is_min();
661 }
662
663 pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
667 self.0.either_or(
668 |operand| {
669 either
670 .call1((PyNodeIndicesOperand::from(operand.clone()),))
671 .expect("Call must succeed");
672 },
673 |operand| {
674 or.call1((PyNodeIndicesOperand::from(operand.clone()),))
675 .expect("Call must succeed");
676 },
677 );
678 }
679
680 pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
684 self.0.exclude(|operand| {
685 query
686 .call1((PyNodeIndicesOperand::from(operand.clone()),))
687 .expect("Call must succeed");
688 });
689 }
690
691 pub fn ungroup(&self) -> PyNodeIndicesOperand {
692 self.0.ungroup().into()
693 }
694
695 pub fn deep_clone(&self) -> Self {
696 self.0.deep_clone().into()
697 }
698}
699
700#[pyclass(frozen)]
701#[repr(transparent)]
702#[derive(Clone)]
703pub struct PyNodeIndexOperand(Wrapper<NodeIndexOperand>);
704
705impl From<Wrapper<NodeIndexOperand>> for PyNodeIndexOperand {
706 fn from(operand: Wrapper<NodeIndexOperand>) -> Self {
707 Self(operand)
708 }
709}
710
711impl From<PyNodeIndexOperand> for Wrapper<NodeIndexOperand> {
712 fn from(operand: PyNodeIndexOperand) -> Self {
713 operand.0
714 }
715}
716
717impl Deref for PyNodeIndexOperand {
718 type Target = Wrapper<NodeIndexOperand>;
719
720 fn deref(&self) -> &Self::Target {
721 &self.0
722 }
723}
724
725#[pymethods]
726impl PyNodeIndexOperand {
727 pub fn greater_than(&self, index: PyNodeIndexComparisonOperand) {
728 self.0.greater_than(index);
729 }
730
731 pub fn greater_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
732 self.0.greater_than_or_equal_to(index);
733 }
734
735 pub fn less_than(&self, index: PyNodeIndexComparisonOperand) {
736 self.0.less_than(index);
737 }
738
739 pub fn less_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
740 self.0.less_than_or_equal_to(index);
741 }
742
743 pub fn equal_to(&self, index: PyNodeIndexComparisonOperand) {
744 self.0.equal_to(index);
745 }
746
747 pub fn not_equal_to(&self, index: PyNodeIndexComparisonOperand) {
748 self.0.not_equal_to(index);
749 }
750
751 pub fn starts_with(&self, index: PyNodeIndexComparisonOperand) {
752 self.0.starts_with(index);
753 }
754
755 pub fn ends_with(&self, index: PyNodeIndexComparisonOperand) {
756 self.0.ends_with(index);
757 }
758
759 pub fn contains(&self, index: PyNodeIndexComparisonOperand) {
760 self.0.contains(index);
761 }
762
763 pub fn is_in(&self, indices: PyNodeIndicesComparisonOperand) {
764 self.0.is_in(indices);
765 }
766
767 pub fn is_not_in(&self, indices: PyNodeIndicesComparisonOperand) {
768 self.0.is_not_in(indices);
769 }
770
771 pub fn add(&self, index: PyNodeIndexComparisonOperand) {
772 self.0.add(index);
773 }
774
775 pub fn sub(&self, index: PyNodeIndexComparisonOperand) {
776 self.0.sub(index);
777 }
778
779 pub fn mul(&self, index: PyNodeIndexComparisonOperand) {
780 self.0.mul(index);
781 }
782
783 pub fn pow(&self, index: PyNodeIndexComparisonOperand) {
784 self.0.pow(index);
785 }
786
787 pub fn r#mod(&self, index: PyNodeIndexComparisonOperand) {
788 self.0.r#mod(index);
789 }
790
791 pub fn abs(&self) {
792 self.0.abs();
793 }
794
795 pub fn trim(&self) {
796 self.0.trim();
797 }
798
799 pub fn trim_start(&self) {
800 self.0.trim_start();
801 }
802
803 pub fn trim_end(&self) {
804 self.0.trim_end();
805 }
806
807 pub fn lowercase(&self) {
808 self.0.lowercase();
809 }
810
811 pub fn uppercase(&self) {
812 self.0.uppercase();
813 }
814
815 pub fn slice(&self, start: usize, end: usize) {
816 self.0.slice(start, end);
817 }
818
819 pub fn is_string(&self) {
820 self.0.is_string();
821 }
822
823 pub fn is_int(&self) {
824 self.0.is_int();
825 }
826
827 pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
831 self.0.either_or(
832 |operand| {
833 either
834 .call1((Self::from(operand.clone()),))
835 .expect("Call must succeed");
836 },
837 |operand| {
838 or.call1((Self::from(operand.clone()),))
839 .expect("Call must succeed");
840 },
841 );
842 }
843
844 pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
848 self.0.exclude(|operand| {
849 query
850 .call1((Self::from(operand.clone()),))
851 .expect("Call must succeed");
852 });
853 }
854
855 pub fn deep_clone(&self) -> Self {
856 self.0.deep_clone().into()
857 }
858}
859
860#[pyclass(frozen)]
861#[repr(transparent)]
862#[derive(Clone)]
863pub struct PyNodeIndexGroupOperand(Wrapper<GroupOperand<NodeIndexOperand>>);
864
865impl From<Wrapper<GroupOperand<NodeIndexOperand>>> for PyNodeIndexGroupOperand {
866 fn from(operand: Wrapper<GroupOperand<NodeIndexOperand>>) -> Self {
867 Self(operand)
868 }
869}
870
871impl From<PyNodeIndexGroupOperand> for Wrapper<GroupOperand<NodeIndexOperand>> {
872 fn from(operand: PyNodeIndexGroupOperand) -> Self {
873 operand.0
874 }
875}
876
877impl Deref for PyNodeIndexGroupOperand {
878 type Target = Wrapper<GroupOperand<NodeIndexOperand>>;
879
880 fn deref(&self) -> &Self::Target {
881 &self.0
882 }
883}
884
885#[pymethods]
886impl PyNodeIndexGroupOperand {
887 pub fn greater_than(&self, index: PyNodeIndexComparisonOperand) {
888 self.0.greater_than(index);
889 }
890
891 pub fn greater_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
892 self.0.greater_than_or_equal_to(index);
893 }
894
895 pub fn less_than(&self, index: PyNodeIndexComparisonOperand) {
896 self.0.less_than(index);
897 }
898
899 pub fn less_than_or_equal_to(&self, index: PyNodeIndexComparisonOperand) {
900 self.0.less_than_or_equal_to(index);
901 }
902
903 pub fn equal_to(&self, index: PyNodeIndexComparisonOperand) {
904 self.0.equal_to(index);
905 }
906
907 pub fn not_equal_to(&self, index: PyNodeIndexComparisonOperand) {
908 self.0.not_equal_to(index);
909 }
910
911 pub fn starts_with(&self, index: PyNodeIndexComparisonOperand) {
912 self.0.starts_with(index);
913 }
914
915 pub fn ends_with(&self, index: PyNodeIndexComparisonOperand) {
916 self.0.ends_with(index);
917 }
918
919 pub fn contains(&self, index: PyNodeIndexComparisonOperand) {
920 self.0.contains(index);
921 }
922
923 pub fn is_in(&self, indices: PyNodeIndicesComparisonOperand) {
924 self.0.is_in(indices);
925 }
926
927 pub fn is_not_in(&self, indices: PyNodeIndicesComparisonOperand) {
928 self.0.is_not_in(indices);
929 }
930
931 pub fn add(&self, index: PyNodeIndexComparisonOperand) {
932 self.0.add(index);
933 }
934
935 pub fn sub(&self, index: PyNodeIndexComparisonOperand) {
936 self.0.sub(index);
937 }
938
939 pub fn mul(&self, index: PyNodeIndexComparisonOperand) {
940 self.0.mul(index);
941 }
942
943 pub fn pow(&self, index: PyNodeIndexComparisonOperand) {
944 self.0.pow(index);
945 }
946
947 pub fn r#mod(&self, index: PyNodeIndexComparisonOperand) {
948 self.0.r#mod(index);
949 }
950
951 pub fn abs(&self) {
952 self.0.abs();
953 }
954
955 pub fn trim(&self) {
956 self.0.trim();
957 }
958
959 pub fn trim_start(&self) {
960 self.0.trim_start();
961 }
962
963 pub fn trim_end(&self) {
964 self.0.trim_end();
965 }
966
967 pub fn lowercase(&self) {
968 self.0.lowercase();
969 }
970
971 pub fn uppercase(&self) {
972 self.0.uppercase();
973 }
974
975 pub fn slice(&self, start: usize, end: usize) {
976 self.0.slice(start, end);
977 }
978
979 pub fn is_string(&self) {
980 self.0.is_string();
981 }
982
983 pub fn is_int(&self) {
984 self.0.is_int();
985 }
986
987 pub fn either_or(&self, either: &Bound<'_, PyFunction>, or: &Bound<'_, PyFunction>) {
991 self.0.either_or(
992 |operand| {
993 either
994 .call1((PyNodeIndexOperand::from(operand.clone()),))
995 .expect("Call must succeed");
996 },
997 |operand| {
998 or.call1((PyNodeIndexOperand::from(operand.clone()),))
999 .expect("Call must succeed");
1000 },
1001 );
1002 }
1003
1004 pub fn exclude(&self, query: &Bound<'_, PyFunction>) {
1008 self.0.exclude(|operand| {
1009 query
1010 .call1((PyNodeIndexOperand::from(operand.clone()),))
1011 .expect("Call must succeed");
1012 });
1013 }
1014
1015 pub fn ungroup(&self) -> PyNodeIndicesOperand {
1016 self.0.ungroup().into()
1017 }
1018
1019 pub fn deep_clone(&self) -> Self {
1020 self.0.deep_clone().into()
1021 }
1022}