@@ -3,6 +3,7 @@ use std::str::from_utf8;
33use pyo3:: intern;
44use pyo3:: prelude:: * ;
55
6+ use pyo3:: sync:: GILOnceCell ;
67use pyo3:: types:: PyType ;
78use pyo3:: types:: {
89 PyBool , PyByteArray , PyBytes , PyComplex , PyDate , PyDateTime , PyDict , PyFloat , PyFrozenSet , PyInt , PyIterator ,
@@ -30,7 +31,8 @@ use super::input_abstract::ValMatch;
3031use super :: return_enums:: EitherComplex ;
3132use super :: return_enums:: { iterate_attributes, iterate_mapping_items, ValidationMatch } ;
3233use 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,
3436} ;
3537use super :: Arguments ;
3638use super :: ConsumeIterator ;
@@ -45,6 +47,20 @@ use super::{
4547 Input ,
4648} ;
4749
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+
4864pub ( crate ) fn downcast_python_input < ' py , T : PyTypeCheck > ( input : & ( impl Input < ' py > + ?Sized ) ) -> Option < & Bound < ' py , T > > {
4965 input. as_python ( ) . and_then ( |any| any. downcast :: < T > ( ) . ok ( ) )
5066}
@@ -269,6 +285,8 @@ impl<'py> Input<'py> for Bound<'py, PyAny> {
269285 float_as_int ( self , self . extract :: < f64 > ( ) ?)
270286 } else if let Ok ( decimal) = self . validate_decimal ( true , self . py ( ) ) {
271287 decimal_as_int ( self , & decimal. into_inner ( ) )
288+ } else if self . is_instance ( get_fraction_type ( self . py ( ) ) ) ? {
289+ fraction_as_int ( self )
272290 } else if let Ok ( float) = self . extract :: < f64 > ( ) {
273291 float_as_int ( self , float)
274292 } else if let Some ( enum_val) = maybe_as_enum ( self ) {
0 commit comments