@@ -3,6 +3,7 @@ use std::str::from_utf8;
3
3
use pyo3:: intern;
4
4
use pyo3:: prelude:: * ;
5
5
6
+ use pyo3:: sync:: GILOnceCell ;
6
7
use pyo3:: types:: PyType ;
7
8
use pyo3:: types:: {
8
9
PyBool , PyByteArray , PyBytes , PyComplex , PyDate , PyDateTime , PyDict , PyFloat , PyFrozenSet , PyInt , PyIterator ,
@@ -30,7 +31,8 @@ use super::input_abstract::ValMatch;
30
31
use super :: return_enums:: EitherComplex ;
31
32
use super :: return_enums:: { iterate_attributes, iterate_mapping_items, ValidationMatch } ;
32
33
use super :: shared:: {
33
- decimal_as_int, float_as_int, get_enum_meta_object, int_as_bool, str_as_bool, str_as_float, str_as_int,
34
+ decimal_as_int, float_as_int, fraction_as_int, get_enum_meta_object, int_as_bool, str_as_bool, str_as_float,
35
+ str_as_int,
34
36
} ;
35
37
use super :: Arguments ;
36
38
use super :: ConsumeIterator ;
@@ -45,6 +47,20 @@ use super::{
45
47
Input ,
46
48
} ;
47
49
50
+ static FRACTION_TYPE : GILOnceCell < Py < PyType > > = GILOnceCell :: new ( ) ;
51
+
52
+ pub fn get_fraction_type ( py : Python ) -> & Bound < ' _ , PyType > {
53
+ FRACTION_TYPE
54
+ . get_or_init ( py, || {
55
+ py. import ( "fractions" )
56
+ . and_then ( |fractions_module| fractions_module. getattr ( "Fraction" ) )
57
+ . unwrap ( )
58
+ . extract ( )
59
+ . unwrap ( )
60
+ } )
61
+ . bind ( py)
62
+ }
63
+
48
64
pub ( crate ) fn downcast_python_input < ' py , T : PyTypeCheck > ( input : & ( impl Input < ' py > + ?Sized ) ) -> Option < & Bound < ' py , T > > {
49
65
input. as_python ( ) . and_then ( |any| any. downcast :: < T > ( ) . ok ( ) )
50
66
}
@@ -269,6 +285,8 @@ impl<'py> Input<'py> for Bound<'py, PyAny> {
269
285
float_as_int ( self , self . extract :: < f64 > ( ) ?)
270
286
} else if let Ok ( decimal) = self . validate_decimal ( true , self . py ( ) ) {
271
287
decimal_as_int ( self , & decimal. into_inner ( ) )
288
+ } else if self . is_instance ( get_fraction_type ( self . py ( ) ) ) ? {
289
+ fraction_as_int ( self )
272
290
} else if let Ok ( float) = self . extract :: < f64 > ( ) {
273
291
float_as_int ( self , float)
274
292
} else if let Some ( enum_val) = maybe_as_enum ( self ) {
0 commit comments