dbn/python/
enums.rs

1use std::str::FromStr;
2
3use pyo3::{prelude::*, type_object::PyTypeInfo, types::PyType, Bound};
4
5use crate::{
6    enums::{Compression, Encoding, SType, Schema, SecurityUpdateAction, UserDefinedInstrument},
7    Action, ErrorCode, InstrumentClass, MatchAlgorithm, RType, Side, StatType, StatusAction,
8    StatusReason, SystemCode, TradingEvent, TriState, VersionUpgradePolicy,
9};
10
11use super::{to_py_err, EnumIterator, PyFieldDesc};
12
13#[pymethods]
14impl Side {
15    #[new]
16    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
17        let Ok(i) = value.extract::<u8>() else {
18            let t = Self::type_object(py);
19            let c = value.extract::<char>().map_err(to_py_err)?;
20            return Self::py_from_str(&t, c);
21        };
22        Self::try_from(i).map_err(to_py_err)
23    }
24
25    fn __hash__(&self) -> isize {
26        *self as isize
27    }
28
29    fn __str__(&self) -> String {
30        format!("{}", *self as u8 as char)
31    }
32
33    fn __repr__(&self) -> String {
34        format!("<Side.{}: '{}'>", self.name(), self.value())
35    }
36
37    #[getter]
38    fn name(&self) -> String {
39        self.as_ref().to_ascii_uppercase()
40    }
41
42    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
43        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
44            return false;
45        };
46        self.eq(&other_enum)
47    }
48
49    #[getter]
50    fn value(&self) -> String {
51        self.__str__()
52    }
53
54    #[classmethod]
55    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
56        EnumIterator::new::<Self>(py)
57    }
58
59    #[classmethod]
60    #[pyo3(name = "from_str")]
61    fn py_from_str(_: &Bound<PyType>, value: char) -> PyResult<Self> {
62        Self::try_from(value as u8).map_err(to_py_err)
63    }
64}
65
66#[pymethods]
67impl Action {
68    #[new]
69    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
70        let Ok(i) = value.extract::<u8>() else {
71            let t = Self::type_object(py);
72            let c = value.extract::<char>().map_err(to_py_err)?;
73            return Self::py_from_str(&t, c);
74        };
75        Self::try_from(i).map_err(to_py_err)
76    }
77
78    fn __hash__(&self) -> isize {
79        *self as isize
80    }
81
82    fn __str__(&self) -> String {
83        format!("{}", *self as u8 as char)
84    }
85
86    fn __repr__(&self) -> String {
87        format!("<Action.{}: '{}'>", self.name(), self.value())
88    }
89
90    #[getter]
91    fn name(&self) -> String {
92        self.as_ref().to_ascii_uppercase()
93    }
94
95    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
96        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
97            return false;
98        };
99        self.eq(&other_enum)
100    }
101
102    #[getter]
103    fn value(&self) -> String {
104        self.__str__()
105    }
106
107    #[classmethod]
108    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
109        EnumIterator::new::<Self>(py)
110    }
111
112    #[classmethod]
113    #[pyo3(name = "from_str")]
114    fn py_from_str(_: &Bound<PyType>, value: char) -> PyResult<Self> {
115        Self::try_from(value as u8).map_err(to_py_err)
116    }
117}
118
119#[pymethods]
120impl InstrumentClass {
121    #[new]
122    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
123        let Ok(i) = value.extract::<u8>() else {
124            let t = Self::type_object(py);
125            let c = value.extract::<char>().map_err(to_py_err)?;
126            return Self::py_from_str(&t, c);
127        };
128        Self::try_from(i).map_err(to_py_err)
129    }
130
131    fn __hash__(&self) -> isize {
132        *self as isize
133    }
134
135    fn __str__(&self) -> String {
136        format!("{}", *self as u8 as char)
137    }
138
139    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
140        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
141            return false;
142        };
143        self.eq(&other_enum)
144    }
145
146    #[getter]
147    fn value(&self) -> String {
148        self.__str__()
149    }
150
151    #[classmethod]
152    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
153        EnumIterator::new::<Self>(py)
154    }
155
156    #[classmethod]
157    #[pyo3(name = "from_str")]
158    fn py_from_str(_: &Bound<PyType>, value: char) -> PyResult<Self> {
159        Self::try_from(value as u8).map_err(to_py_err)
160    }
161}
162
163#[pymethods]
164impl MatchAlgorithm {
165    #[new]
166    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
167        let Ok(i) = value.extract::<u8>() else {
168            let t = Self::type_object(py);
169            let c = value.extract::<char>().map_err(to_py_err)?;
170            return Self::py_from_str(&t, c);
171        };
172        Self::try_from(i).map_err(to_py_err)
173    }
174
175    fn __hash__(&self) -> isize {
176        *self as isize
177    }
178
179    fn __str__(&self) -> String {
180        format!("{}", *self as u8 as char)
181    }
182
183    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
184        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
185            return false;
186        };
187        self.eq(&other_enum)
188    }
189
190    #[getter]
191    fn value(&self) -> String {
192        self.__str__()
193    }
194
195    #[classmethod]
196    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
197        EnumIterator::new::<Self>(py)
198    }
199
200    #[classmethod]
201    #[pyo3(name = "from_str")]
202    fn py_from_str(_: &Bound<PyType>, value: char) -> PyResult<Self> {
203        Self::try_from(value as u8).map_err(to_py_err)
204    }
205}
206
207#[pymethods]
208impl UserDefinedInstrument {
209    #[new]
210    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
211        let Ok(i) = value.extract::<u8>() else {
212            let t = Self::type_object(py);
213            let c = value.extract::<char>().map_err(to_py_err)?;
214            return Self::py_from_str(&t, c);
215        };
216        Self::try_from(i).map_err(to_py_err)
217    }
218
219    fn __hash__(&self) -> isize {
220        *self as isize
221    }
222
223    fn __str__(&self) -> String {
224        format!("{}", *self as u8 as char)
225    }
226
227    fn __repr__(&self) -> String {
228        format!(
229            "<UserDefinedInstrument.{}: '{}'>",
230            self.name(),
231            self.value()
232        )
233    }
234
235    #[getter]
236    fn name(&self) -> String {
237        self.as_ref().to_ascii_uppercase()
238    }
239
240    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
241        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
242            return false;
243        };
244        self.eq(&other_enum)
245    }
246
247    #[getter]
248    fn value(&self) -> String {
249        self.__str__()
250    }
251
252    #[classmethod]
253    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
254        EnumIterator::new::<Self>(py)
255    }
256
257    #[classmethod]
258    #[pyo3(name = "from_str")]
259    fn py_from_str(_: &Bound<PyType>, value: char) -> PyResult<Self> {
260        Self::try_from(value as u8).map_err(to_py_err)
261    }
262}
263
264#[pymethods]
265impl SType {
266    #[new]
267    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
268        let t = Self::type_object(py);
269        Self::py_from_str(&t, value)
270    }
271
272    fn __hash__(&self) -> isize {
273        *self as isize
274    }
275
276    fn __str__(&self) -> &'static str {
277        self.as_str()
278    }
279
280    fn __repr__(&self) -> String {
281        format!("<SType.{}: '{}'>", self.name(), self.value(),)
282    }
283
284    #[getter]
285    fn name(&self) -> String {
286        self.as_str().to_uppercase()
287    }
288
289    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
290        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
291            return false;
292        };
293        self.eq(&other_enum)
294    }
295
296    #[getter]
297    fn value(&self) -> &'static str {
298        self.as_str()
299    }
300
301    #[classmethod]
302    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
303        EnumIterator::new::<Self>(py)
304    }
305
306    #[classmethod]
307    #[pyo3(name = "from_str")]
308    fn py_from_str(_: &Bound<PyType>, value: &Bound<PyAny>) -> PyResult<Self> {
309        let value_str: String = value.str().and_then(|s| s.extract())?;
310        let tokenized = value_str.replace('-', "_").to_lowercase();
311        Ok(Self::from_str(&tokenized)?)
312    }
313}
314
315#[pymethods]
316impl RType {
317    #[new]
318    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
319        let t = Self::type_object(py);
320        Self::py_from_str(&t, value).or_else(|_| Self::py_from_int(&t, value))
321    }
322
323    fn __hash__(&self) -> isize {
324        *self as isize
325    }
326
327    fn __str__(&self) -> &'static str {
328        self.as_str()
329    }
330
331    fn __repr__(&self) -> String {
332        format!("<RType.{}: '{}'>", self.name(), self.value(),)
333    }
334
335    #[getter]
336    fn name(&self) -> String {
337        self.as_str().to_uppercase()
338    }
339
340    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
341        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
342            return false;
343        };
344        self.eq(&other_enum)
345    }
346
347    #[getter]
348    fn value(&self) -> u8 {
349        *self as u8
350    }
351
352    #[classmethod]
353    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
354        EnumIterator::new::<Self>(py)
355    }
356
357    #[classmethod]
358    #[pyo3(name = "from_str")]
359    fn py_from_str(_: &Bound<PyType>, value: &Bound<PyAny>) -> PyResult<Self> {
360        let value_str: String = value.str().and_then(|s| s.extract())?;
361        let tokenized = value_str.replace('-', "_").to_lowercase();
362        Ok(Self::from_str(&tokenized)?)
363    }
364
365    #[classmethod]
366    #[pyo3(name = "from_int")]
367    fn py_from_int(_: &Bound<PyType>, value: &Bound<PyAny>) -> PyResult<Self> {
368        let value: u8 = value.extract()?;
369        Self::try_from(value).map_err(to_py_err)
370    }
371
372    #[classmethod]
373    #[pyo3(name = "from_schema")]
374    fn py_from_schema(pytype: &Bound<PyType>, value: &Bound<PyAny>) -> PyResult<Self> {
375        let schema: Schema = value
376            .extract()
377            .or_else(|_| Schema::py_from_str(&Schema::type_object(pytype.py()), value))
378            .map_err(to_py_err)?;
379        Ok(Self::from(schema))
380    }
381}
382
383#[pymethods]
384impl Schema {
385    #[new]
386    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
387        let t = Self::type_object(py);
388        Self::py_from_str(&t, value)
389    }
390
391    fn __hash__(&self) -> isize {
392        *self as isize
393    }
394
395    fn __str__(&self) -> &'static str {
396        self.as_str()
397    }
398
399    fn __repr__(&self) -> String {
400        format!("<Schema.{}: '{}'>", self.name(), self.value(),)
401    }
402
403    #[getter]
404    fn name(&self) -> String {
405        self.as_str().to_uppercase()
406    }
407
408    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
409        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
410            return false;
411        };
412        self.eq(&other_enum)
413    }
414
415    #[getter]
416    fn value(&self) -> &'static str {
417        self.as_str()
418    }
419
420    #[classmethod]
421    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
422        EnumIterator::new::<Self>(py)
423    }
424
425    #[classmethod]
426    #[pyo3(name = "from_str")]
427    fn py_from_str(_: &Bound<PyType>, value: &Bound<PyAny>) -> PyResult<Self> {
428        let value_str: String = value.str().and_then(|s| s.extract())?;
429        let tokenized = value_str.replace('_', "-").to_lowercase();
430        Ok(Self::from_str(&tokenized)?)
431    }
432}
433
434#[pymethods]
435impl Encoding {
436    #[new]
437    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
438        let t = Self::type_object(py);
439        Self::py_from_str(&t, value)
440    }
441
442    fn __hash__(&self) -> isize {
443        *self as isize
444    }
445
446    fn __str__(&self) -> &'static str {
447        self.as_str()
448    }
449
450    fn __repr__(&self) -> String {
451        format!("<Encoding.{}: '{}'>", self.name(), self.value(),)
452    }
453
454    #[getter]
455    fn name(&self) -> String {
456        self.as_str().to_uppercase()
457    }
458
459    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
460        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
461            return false;
462        };
463        self.eq(&other_enum)
464    }
465
466    #[getter]
467    fn value(&self) -> &'static str {
468        self.as_str()
469    }
470
471    #[classmethod]
472    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
473        EnumIterator::new::<Self>(py)
474    }
475
476    #[classmethod]
477    #[pyo3(name = "from_str")]
478    fn py_from_str(_: &Bound<PyType>, value: &Bound<PyAny>) -> PyResult<Self> {
479        let value_str: String = value.str().and_then(|s| s.extract())?;
480        let tokenized = value_str.to_lowercase();
481        Ok(Self::from_str(&tokenized)?)
482    }
483}
484
485#[pymethods]
486impl Compression {
487    #[new]
488    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
489        let t = Self::type_object(py);
490        Self::py_from_str(&t, value)
491    }
492
493    fn __hash__(&self) -> isize {
494        *self as isize
495    }
496
497    fn __str__(&self) -> &'static str {
498        self.as_str()
499    }
500
501    fn __repr__(&self) -> String {
502        format!("<Compression.{}: '{}'>", self.name(), self.value(),)
503    }
504
505    #[getter]
506    fn name(&self) -> String {
507        self.as_str().to_uppercase()
508    }
509
510    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
511        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
512            return false;
513        };
514        self.eq(&other_enum)
515    }
516
517    #[getter]
518    fn value(&self) -> &'static str {
519        self.as_str()
520    }
521
522    // No metaclass support with pyo3, so `for c in Compression: ...` isn't possible
523    #[classmethod]
524    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
525        EnumIterator::new::<Self>(py)
526    }
527
528    #[classmethod]
529    #[pyo3(name = "from_str")]
530    fn py_from_str(_: &Bound<PyType>, value: &Bound<PyAny>) -> PyResult<Self> {
531        let value_str: String = value.str().and_then(|s| s.extract())?;
532        let tokenized = value_str.to_lowercase();
533        Ok(Self::from_str(&tokenized)?)
534    }
535}
536
537#[pymethods]
538impl SecurityUpdateAction {
539    #[new]
540    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
541        let Ok(i) = value.extract::<u8>() else {
542            let t = Self::type_object(py);
543            let c = value.extract::<char>().map_err(to_py_err)?;
544            return Self::py_from_str(&t, c);
545        };
546        Self::try_from(i).map_err(to_py_err)
547    }
548
549    fn __hash__(&self) -> isize {
550        *self as isize
551    }
552
553    fn __repr__(&self) -> String {
554        format!("<SecurityUpdateAction.{}: '{}'>", self.name(), self.value())
555    }
556
557    #[getter]
558    fn name(&self) -> String {
559        self.as_ref().to_ascii_uppercase()
560    }
561
562    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
563        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
564            return false;
565        };
566        self.eq(&other_enum)
567    }
568
569    #[getter]
570    fn value(&self) -> u16 {
571        *self as u16
572    }
573
574    #[classmethod]
575    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
576        EnumIterator::new::<Self>(py)
577    }
578
579    #[classmethod]
580    #[pyo3(name = "from_str")]
581    fn py_from_str(_: &Bound<PyType>, value: char) -> PyResult<Self> {
582        Self::try_from(value as u8).map_err(to_py_err)
583    }
584}
585
586#[pymethods]
587impl StatType {
588    #[new]
589    fn py_new(value: &Bound<PyAny>) -> PyResult<Self> {
590        let i = value.extract::<u16>().map_err(to_py_err)?;
591        Self::try_from(i).map_err(to_py_err)
592    }
593
594    fn __hash__(&self) -> isize {
595        *self as isize
596    }
597
598    fn __eq__(&self, other: &Bound<PyAny>) -> bool {
599        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(other)) else {
600            return false;
601        };
602        self.eq(&other_enum)
603    }
604
605    #[getter]
606    fn value(&self) -> u16 {
607        *self as u16
608    }
609
610    #[classmethod]
611    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
612        EnumIterator::new::<Self>(py)
613    }
614}
615
616#[pymethods]
617impl StatusAction {
618    #[new]
619    fn py_new(value: &Bound<PyAny>) -> PyResult<Self> {
620        let i = value.extract::<u16>().map_err(to_py_err)?;
621        Self::try_from(i).map_err(to_py_err)
622    }
623
624    fn __hash__(&self) -> isize {
625        *self as isize
626    }
627
628    fn __eq__(&self, other: &Bound<PyAny>) -> bool {
629        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(other)) else {
630            return false;
631        };
632        self.eq(&other_enum)
633    }
634
635    #[getter]
636    fn value(&self) -> u16 {
637        *self as u16
638    }
639
640    #[classmethod]
641    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
642        EnumIterator::new::<Self>(py)
643    }
644}
645
646#[pymethods]
647impl StatusReason {
648    #[new]
649    fn py_new(value: &Bound<PyAny>) -> PyResult<Self> {
650        let i = value.extract::<u16>().map_err(to_py_err)?;
651        Self::try_from(i).map_err(to_py_err)
652    }
653
654    fn __hash__(&self) -> isize {
655        *self as isize
656    }
657
658    fn __eq__(&self, other: &Bound<PyAny>) -> bool {
659        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(other)) else {
660            return false;
661        };
662        self.eq(&other_enum)
663    }
664
665    #[getter]
666    fn value(&self) -> u16 {
667        *self as u16
668    }
669
670    #[classmethod]
671    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
672        EnumIterator::new::<Self>(py)
673    }
674}
675
676#[pymethods]
677impl TradingEvent {
678    #[new]
679    fn py_new(value: &Bound<PyAny>) -> PyResult<Self> {
680        let i = value.extract::<u16>().map_err(to_py_err)?;
681        Self::try_from(i).map_err(to_py_err)
682    }
683
684    fn __hash__(&self) -> isize {
685        *self as isize
686    }
687
688    fn __eq__(&self, other: &Bound<PyAny>) -> bool {
689        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(other)) else {
690            return false;
691        };
692        self.eq(&other_enum)
693    }
694
695    #[getter]
696    fn value(&self) -> u16 {
697        *self as u16
698    }
699
700    #[classmethod]
701    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
702        EnumIterator::new::<Self>(py)
703    }
704}
705
706#[pymethods]
707impl TriState {
708    #[new]
709    fn py_new(py: Python<'_>, value: &Bound<PyAny>) -> PyResult<Self> {
710        let Ok(i) = value.extract::<u8>() else {
711            let t = Self::type_object(py);
712            let c = value.extract::<char>().map_err(to_py_err)?;
713            return Self::py_from_str(&t, c);
714        };
715        Self::try_from(i).map_err(to_py_err)
716    }
717
718    fn __hash__(&self) -> isize {
719        *self as isize
720    }
721
722    fn __str__(&self) -> String {
723        format!("{}", *self as u8 as char)
724    }
725
726    fn opt_bool(&self) -> Option<bool> {
727        Option::from(*self)
728    }
729
730    fn __eq__(&self, other: &Bound<PyAny>, py: Python<'_>) -> bool {
731        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(py, other)) else {
732            return false;
733        };
734        self.eq(&other_enum)
735    }
736
737    #[getter]
738    fn value(&self) -> String {
739        self.__str__()
740    }
741
742    #[classmethod]
743    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
744        EnumIterator::new::<Self>(py)
745    }
746
747    #[classmethod]
748    #[pyo3(name = "from_str")]
749    fn py_from_str(_: &Bound<PyType>, value: char) -> PyResult<Self> {
750        Self::try_from(value as u8).map_err(to_py_err)
751    }
752}
753
754#[pymethods]
755impl VersionUpgradePolicy {
756    fn __hash__(&self) -> isize {
757        *self as isize
758    }
759
760    #[classmethod]
761    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
762        EnumIterator::new::<Self>(py)
763    }
764}
765
766impl PyFieldDesc for SecurityUpdateAction {
767    fn field_dtypes(field_name: &str) -> Vec<(String, String)> {
768        vec![(field_name.to_owned(), "S1".to_owned())]
769    }
770}
771
772impl PyFieldDesc for UserDefinedInstrument {
773    fn field_dtypes(field_name: &str) -> Vec<(String, String)> {
774        vec![(field_name.to_owned(), "S1".to_owned())]
775    }
776}
777
778#[pymethods]
779impl ErrorCode {
780    #[new]
781    fn py_new(value: &Bound<PyAny>) -> PyResult<Self> {
782        let i = value.extract::<u8>().map_err(to_py_err)?;
783        Self::try_from(i).map_err(to_py_err)
784    }
785
786    fn __hash__(&self) -> isize {
787        *self as isize
788    }
789
790    fn __str__(&self) -> &'static str {
791        self.as_str()
792    }
793
794    fn __repr__(&self) -> String {
795        format!("<ErrorCode.{}: '{}'>", self.name(), self.value())
796    }
797
798    #[getter]
799    fn name(&self) -> String {
800        self.as_ref().to_ascii_uppercase()
801    }
802
803    fn __eq__(&self, other: &Bound<PyAny>) -> bool {
804        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(other)) else {
805            return false;
806        };
807        self.eq(&other_enum)
808    }
809
810    #[getter]
811    fn value(&self) -> &'static str {
812        self.as_str()
813    }
814
815    #[classmethod]
816    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
817        EnumIterator::new::<Self>(py)
818    }
819}
820
821#[pymethods]
822impl SystemCode {
823    #[new]
824    fn py_new(value: &Bound<PyAny>) -> PyResult<Self> {
825        let i = value.extract::<u8>().map_err(to_py_err)?;
826        Self::try_from(i).map_err(to_py_err)
827    }
828
829    fn __hash__(&self) -> isize {
830        *self as isize
831    }
832
833    fn __str__(&self) -> &'static str {
834        self.as_str()
835    }
836
837    fn __repr__(&self) -> String {
838        format!("<SystemCode.{}: '{}'>", self.name(), self.value())
839    }
840
841    #[getter]
842    fn name(&self) -> String {
843        self.as_ref().to_ascii_uppercase()
844    }
845
846    fn __eq__(&self, other: &Bound<PyAny>) -> bool {
847        let Ok(other_enum) = other.extract::<Self>().or_else(|_| Self::py_new(other)) else {
848            return false;
849        };
850        self.eq(&other_enum)
851    }
852
853    #[getter]
854    fn value(&self) -> &'static str {
855        self.as_str()
856    }
857
858    #[classmethod]
859    fn variants(_: &Bound<PyType>, py: Python<'_>) -> PyResult<EnumIterator> {
860        EnumIterator::new::<Self>(py)
861    }
862}