1
1
use std:: borrow:: Cow ;
2
2
use std:: str:: from_utf8;
3
3
4
- use pyo3:: once_cell:: GILOnceCell ;
5
4
use pyo3:: prelude:: * ;
6
5
use pyo3:: types:: {
7
6
PyBool , PyByteArray , PyBytes , PyDate , PyDateTime , PyDelta , PyDict , PyFrozenSet , PyInt , PyIterator , PyList ,
@@ -22,8 +21,8 @@ use super::datetime::{
22
21
} ;
23
22
use super :: shared:: { float_as_int, int_as_bool, map_json_err, str_as_bool, str_as_int} ;
24
23
use super :: {
25
- py_string_str, EitherBytes , EitherString , EitherTimedelta , GenericArguments , GenericIterable , GenericIterator ,
26
- GenericMapping , Input , JsonInput , PyArgs ,
24
+ py_string_str, EitherBytes , EitherInt , EitherString , EitherTimedelta , GenericArguments , GenericIterable ,
25
+ GenericIterator , GenericMapping , Input , JsonInput , PyArgs ,
27
26
} ;
28
27
29
28
#[ cfg( not( PyPy ) ) ]
@@ -227,14 +226,6 @@ impl<'a> Input<'a> for PyAny {
227
226
}
228
227
}
229
228
230
- fn as_str_strict ( & self ) -> Option < & str > {
231
- if self . get_type ( ) . is ( get_py_str_type ( self . py ( ) ) ) {
232
- self . extract ( ) . ok ( )
233
- } else {
234
- None
235
- }
236
- }
237
-
238
229
fn strict_bytes ( & ' a self ) -> ValResult < EitherBytes < ' a > > {
239
230
if let Ok ( py_bytes) = self . downcast :: < PyBytes > ( ) {
240
231
Ok ( py_bytes. into ( ) )
@@ -281,37 +272,34 @@ impl<'a> Input<'a> for PyAny {
281
272
}
282
273
}
283
274
284
- fn strict_int ( & self ) -> ValResult < i64 > {
285
- // bool check has to come before int check as bools would be cast to ints below
286
- if self . extract :: < bool > ( ) . is_ok ( ) {
287
- Err ( ValError :: new ( ErrorType :: IntType , self ) )
288
- } else if let Ok ( int) = self . extract :: < i64 > ( ) {
289
- Ok ( int)
275
+ fn strict_int ( & ' a self ) -> ValResult < EitherInt < ' a > > {
276
+ if PyInt :: is_exact_type_of ( self ) {
277
+ Ok ( EitherInt :: Py ( self ) )
278
+ } else if PyInt :: is_type_of ( self ) {
279
+ // bools are a subclass of int, so check for bool type in this specific case
280
+ if PyBool :: is_exact_type_of ( self ) {
281
+ Err ( ValError :: new ( ErrorType :: IntType , self ) )
282
+ } else {
283
+ Ok ( EitherInt :: Py ( self ) )
284
+ }
290
285
} else {
291
286
Err ( ValError :: new ( ErrorType :: IntType , self ) )
292
287
}
293
288
}
294
289
295
- fn lax_int ( & self ) -> ValResult < i64 > {
296
- if let Ok ( int ) = self . extract :: < i64 > ( ) {
297
- Ok ( int )
290
+ fn lax_int ( & ' a self ) -> ValResult < EitherInt < ' a > > {
291
+ if PyInt :: is_exact_type_of ( self ) {
292
+ Ok ( EitherInt :: Py ( self ) )
298
293
} else if let Some ( cow_str) = maybe_as_string ( self , ErrorType :: IntParsing ) ? {
299
- str_as_int ( self , & cow_str)
294
+ let int = str_as_int ( self , & cow_str) ?;
295
+ Ok ( EitherInt :: Rust ( int) )
300
296
} else if let Ok ( float) = self . extract :: < f64 > ( ) {
301
- float_as_int ( self , float)
297
+ Ok ( EitherInt :: Rust ( float_as_int ( self , float) ? ) )
302
298
} else {
303
299
Err ( ValError :: new ( ErrorType :: IntType , self ) )
304
300
}
305
301
}
306
302
307
- fn as_int_strict ( & self ) -> Option < i64 > {
308
- if self . get_type ( ) . is ( get_py_int_type ( self . py ( ) ) ) {
309
- self . extract ( ) . ok ( )
310
- } else {
311
- None
312
- }
313
- }
314
-
315
303
fn ultra_strict_float ( & self ) -> ValResult < f64 > {
316
304
if matches ! ( self . is_instance_of:: <PyInt >( ) , Ok ( true ) ) {
317
305
Err ( ValError :: new ( ErrorType :: FloatType , self ) )
@@ -322,10 +310,13 @@ impl<'a> Input<'a> for PyAny {
322
310
}
323
311
}
324
312
fn strict_float ( & self ) -> ValResult < f64 > {
325
- if self . extract :: < bool > ( ) . is_ok ( ) {
326
- Err ( ValError :: new ( ErrorType :: FloatType , self ) )
327
- } else if let Ok ( float) = self . extract :: < f64 > ( ) {
328
- Ok ( float)
313
+ if let Ok ( float) = self . extract :: < f64 > ( ) {
314
+ // bools are cast to floats as either 0.0 or 1.0, so check for bool type in this specific case
315
+ if ( float == 0.0 || float == 1.0 ) && PyBool :: is_exact_type_of ( self ) {
316
+ Err ( ValError :: new ( ErrorType :: FloatType , self ) )
317
+ } else {
318
+ Ok ( float)
319
+ }
329
320
} else {
330
321
Err ( ValError :: new ( ErrorType :: FloatType , self ) )
331
322
}
@@ -515,7 +506,7 @@ impl<'a> Input<'a> for PyAny {
515
506
}
516
507
517
508
fn strict_date ( & self ) -> ValResult < EitherDate > {
518
- if self . downcast :: < PyDateTime > ( ) . is_ok ( ) {
509
+ if PyDateTime :: is_type_of ( self ) {
519
510
// have to check if it's a datetime first, otherwise the line below converts to a date
520
511
Err ( ValError :: new ( ErrorType :: DateType , self ) )
521
512
} else if let Ok ( date) = self . downcast :: < PyDate > ( ) {
@@ -526,7 +517,7 @@ impl<'a> Input<'a> for PyAny {
526
517
}
527
518
528
519
fn lax_date ( & self ) -> ValResult < EitherDate > {
529
- if self . downcast :: < PyDateTime > ( ) . is_ok ( ) {
520
+ if PyDateTime :: is_type_of ( self ) {
530
521
// have to check if it's a datetime first, otherwise the line below converts to a date
531
522
// even if we later try coercion from a datetime, we don't want to return a datetime now
532
523
Err ( ValError :: new ( ErrorType :: DateType , self ) )
@@ -558,7 +549,7 @@ impl<'a> Input<'a> for PyAny {
558
549
bytes_as_time ( self , str. as_bytes ( ) )
559
550
} else if let Ok ( py_bytes) = self . downcast :: < PyBytes > ( ) {
560
551
bytes_as_time ( self , py_bytes. as_bytes ( ) )
561
- } else if self . downcast :: < PyBool > ( ) . is_ok ( ) {
552
+ } else if PyBool :: is_exact_type_of ( self ) {
562
553
Err ( ValError :: new ( ErrorType :: TimeType , self ) )
563
554
} else if let Ok ( int) = self . extract :: < i64 > ( ) {
564
555
int_as_time ( self , int, 0 )
@@ -585,7 +576,7 @@ impl<'a> Input<'a> for PyAny {
585
576
bytes_as_datetime ( self , str. as_bytes ( ) )
586
577
} else if let Ok ( py_bytes) = self . downcast :: < PyBytes > ( ) {
587
578
bytes_as_datetime ( self , py_bytes. as_bytes ( ) )
588
- } else if self . downcast :: < PyBool > ( ) . is_ok ( ) {
579
+ } else if PyBool :: is_exact_type_of ( self ) {
589
580
Err ( ValError :: new ( ErrorType :: DatetimeType , self ) )
590
581
} else if let Ok ( int) = self . extract :: < i64 > ( ) {
591
582
int_as_datetime ( self , int, 0 )
@@ -661,7 +652,7 @@ fn is_builtin_str(py_str: &PyString) -> bool {
661
652
}
662
653
663
654
#[ cfg( PyPy ) ]
664
- static DICT_KEYS_TYPE : GILOnceCell < Py < PyType > > = GILOnceCell :: new ( ) ;
655
+ static DICT_KEYS_TYPE : pyo3 :: once_cell :: GILOnceCell < Py < PyType > > = pyo3 :: once_cell :: GILOnceCell :: new ( ) ;
665
656
666
657
#[ cfg( PyPy ) ]
667
658
fn is_dict_keys_type ( v : & PyAny ) -> bool {
@@ -679,7 +670,7 @@ fn is_dict_keys_type(v: &PyAny) -> bool {
679
670
}
680
671
681
672
#[ cfg( PyPy ) ]
682
- static DICT_VALUES_TYPE : GILOnceCell < Py < PyType > > = GILOnceCell :: new ( ) ;
673
+ static DICT_VALUES_TYPE : pyo3 :: once_cell :: GILOnceCell < Py < PyType > > = pyo3 :: once_cell :: GILOnceCell :: new ( ) ;
683
674
684
675
#[ cfg( PyPy ) ]
685
676
fn is_dict_values_type ( v : & PyAny ) -> bool {
@@ -697,7 +688,7 @@ fn is_dict_values_type(v: &PyAny) -> bool {
697
688
}
698
689
699
690
#[ cfg( PyPy ) ]
700
- static DICT_ITEMS_TYPE : GILOnceCell < Py < PyType > > = GILOnceCell :: new ( ) ;
691
+ static DICT_ITEMS_TYPE : pyo3 :: once_cell :: GILOnceCell < Py < PyType > > = pyo3 :: once_cell :: GILOnceCell :: new ( ) ;
701
692
702
693
#[ cfg( PyPy ) ]
703
694
fn is_dict_items_type ( v : & PyAny ) -> bool {
@@ -722,15 +713,3 @@ pub fn list_as_tuple(list: &PyList) -> &PyTuple {
722
713
} ;
723
714
py_tuple. into_ref ( list. py ( ) )
724
715
}
725
-
726
- static PY_INT_TYPE : GILOnceCell < PyObject > = GILOnceCell :: new ( ) ;
727
-
728
- fn get_py_int_type ( py : Python ) -> & PyObject {
729
- PY_INT_TYPE . get_or_init ( py, || PyInt :: type_object ( py) . into ( ) )
730
- }
731
-
732
- static PY_STR_TYPE : GILOnceCell < PyObject > = GILOnceCell :: new ( ) ;
733
-
734
- fn get_py_str_type ( py : Python ) -> & PyObject {
735
- PY_STR_TYPE . get_or_init ( py, || PyString :: type_object ( py) . into ( ) )
736
- }
0 commit comments