@@ -4,13 +4,15 @@ use std::str::from_utf8;
4
4
use pyo3:: exceptions:: PyAttributeError ;
5
5
use pyo3:: prelude:: * ;
6
6
use pyo3:: types:: {
7
- PyBool , PyByteArray , PyBytes , PyDate , PyDateTime , PyDelta , PyDict , PyFrozenSet , PyList , PyMapping , PySequence ,
8
- PySet , PyString , PyTime , PyTuple , PyType ,
7
+ PyBool , PyByteArray , PyBytes , PyDate , PyDateTime , PyDelta , PyDict , PyFrozenSet , PyIterator , PyList , PyMapping ,
8
+ PySequence , PySet , PyString , PyTime , PyTuple , PyType ,
9
9
} ;
10
10
use pyo3:: { intern, AsPyPointer } ;
11
11
12
12
use crate :: errors:: { py_err_string, ErrorKind , InputValue , LocItem , ValError , ValResult } ;
13
13
14
+ #[ cfg( not( PyPy ) ) ]
15
+ use super :: _pyo3_dict:: { PyDictKeys , PyDictValues } ;
14
16
use super :: datetime:: {
15
17
bytes_as_date, bytes_as_datetime, bytes_as_time, bytes_as_timedelta, date_as_datetime, float_as_datetime,
16
18
float_as_duration, float_as_time, int_as_datetime, int_as_duration, int_as_time, EitherDate , EitherDateTime ,
@@ -22,6 +24,25 @@ use super::{
22
24
GenericMapping , Input , PyArgs ,
23
25
} ;
24
26
27
+ #[ cfg( not( PyPy ) ) ]
28
+ macro_rules! extract_gen_dict {
29
+ ( $type: ty, $obj: ident) => { {
30
+ let map_err = |_| ValError :: new( ErrorKind :: IterationError , $obj) ;
31
+ if let Ok ( iterator) = $obj. cast_as:: <PyIterator >( ) {
32
+ let vec = iterator. collect:: <PyResult <Vec <_>>>( ) . map_err( map_err) ?;
33
+ Some ( <$type>:: new( $obj. py( ) , vec) )
34
+ } else if let Ok ( dict_keys) = $obj. cast_as:: <PyDictKeys >( ) {
35
+ let vec = dict_keys. iter( ) ?. collect:: <PyResult <Vec <_>>>( ) . map_err( map_err) ?;
36
+ Some ( <$type>:: new( $obj. py( ) , vec) )
37
+ } else if let Ok ( dict_values) = $obj. cast_as:: <PyDictValues >( ) {
38
+ let vec = dict_values. iter( ) ?. collect:: <PyResult <Vec <_>>>( ) . map_err( map_err) ?;
39
+ Some ( <$type>:: new( $obj. py( ) , vec) )
40
+ } else {
41
+ None
42
+ }
43
+ } } ;
44
+ }
45
+
25
46
impl < ' a > Input < ' a > for PyAny {
26
47
fn as_loc_item ( & self ) -> LocItem {
27
48
if let Ok ( py_str) = self . cast_as :: < PyString > ( ) {
@@ -261,15 +282,30 @@ impl<'a> Input<'a> for PyAny {
261
282
}
262
283
}
263
284
285
+ #[ cfg( not( PyPy ) ) ]
264
286
fn lax_list ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
265
287
if let Ok ( list) = self . cast_as :: < PyList > ( ) {
266
288
Ok ( list. into ( ) )
267
289
} else if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
268
290
Ok ( tuple. into ( ) )
269
- } else if let Ok ( set) = self . cast_as :: < PySet > ( ) {
270
- Ok ( set. into ( ) )
271
- } else if let Ok ( frozen_set) = self . cast_as :: < PyFrozenSet > ( ) {
272
- Ok ( frozen_set. into ( ) )
291
+ } else if let Some ( list) = extract_gen_dict ! ( PyList , self ) {
292
+ Ok ( list. into ( ) )
293
+ } else {
294
+ Err ( ValError :: new ( ErrorKind :: ListType , self ) )
295
+ }
296
+ }
297
+
298
+ #[ cfg( PyPy ) ]
299
+ fn lax_list ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
300
+ if let Ok ( list) = self . cast_as :: < PyList > ( ) {
301
+ Ok ( list. into ( ) )
302
+ } else if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
303
+ Ok ( tuple. into ( ) )
304
+ } else if let Ok ( iterator) = self . cast_as :: < PyIterator > ( ) {
305
+ let vec = iterator
306
+ . collect :: < PyResult < Vec < _ > > > ( )
307
+ . map_err ( |_| ValError :: new ( ErrorKind :: IterationError , self ) ) ?;
308
+ Ok ( PyList :: new ( self . py ( ) , vec) . into ( ) )
273
309
} else {
274
310
Err ( ValError :: new ( ErrorKind :: ListType , self ) )
275
311
}
@@ -283,15 +319,30 @@ impl<'a> Input<'a> for PyAny {
283
319
}
284
320
}
285
321
322
+ #[ cfg( not( PyPy ) ) ]
286
323
fn lax_tuple ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
287
324
if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
288
325
Ok ( tuple. into ( ) )
289
326
} else if let Ok ( list) = self . cast_as :: < PyList > ( ) {
290
327
Ok ( list. into ( ) )
291
- } else if let Ok ( set) = self . cast_as :: < PySet > ( ) {
292
- Ok ( set. into ( ) )
293
- } else if let Ok ( frozen_set) = self . cast_as :: < PyFrozenSet > ( ) {
294
- Ok ( frozen_set. into ( ) )
328
+ } else if let Some ( tuple) = extract_gen_dict ! ( PyTuple , self ) {
329
+ Ok ( tuple. into ( ) )
330
+ } else {
331
+ Err ( ValError :: new ( ErrorKind :: TupleType , self ) )
332
+ }
333
+ }
334
+
335
+ #[ cfg( PyPy ) ]
336
+ fn lax_tuple ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
337
+ if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
338
+ Ok ( tuple. into ( ) )
339
+ } else if let Ok ( list) = self . cast_as :: < PyList > ( ) {
340
+ Ok ( list. into ( ) )
341
+ } else if let Ok ( iterator) = self . cast_as :: < PyIterator > ( ) {
342
+ let vec = iterator
343
+ . collect :: < PyResult < Vec < _ > > > ( )
344
+ . map_err ( |_| ValError :: new ( ErrorKind :: IterationError , self ) ) ?;
345
+ Ok ( PyTuple :: new ( self . py ( ) , vec) . into ( ) )
295
346
} else {
296
347
Err ( ValError :: new ( ErrorKind :: TupleType , self ) )
297
348
}
@@ -305,6 +356,24 @@ impl<'a> Input<'a> for PyAny {
305
356
}
306
357
}
307
358
359
+ #[ cfg( not( PyPy ) ) ]
360
+ fn lax_set ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
361
+ if let Ok ( set) = self . cast_as :: < PySet > ( ) {
362
+ Ok ( set. into ( ) )
363
+ } else if let Ok ( list) = self . cast_as :: < PyList > ( ) {
364
+ Ok ( list. into ( ) )
365
+ } else if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
366
+ Ok ( tuple. into ( ) )
367
+ } else if let Ok ( frozen_set) = self . cast_as :: < PyFrozenSet > ( ) {
368
+ Ok ( frozen_set. into ( ) )
369
+ } else if let Some ( tuple) = extract_gen_dict ! ( PyTuple , self ) {
370
+ Ok ( tuple. into ( ) )
371
+ } else {
372
+ Err ( ValError :: new ( ErrorKind :: SetType , self ) )
373
+ }
374
+ }
375
+
376
+ #[ cfg( PyPy ) ]
308
377
fn lax_set ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
309
378
if let Ok ( set) = self . cast_as :: < PySet > ( ) {
310
379
Ok ( set. into ( ) )
@@ -314,6 +383,11 @@ impl<'a> Input<'a> for PyAny {
314
383
Ok ( tuple. into ( ) )
315
384
} else if let Ok ( frozen_set) = self . cast_as :: < PyFrozenSet > ( ) {
316
385
Ok ( frozen_set. into ( ) )
386
+ } else if let Ok ( iterator) = self . cast_as :: < PyIterator > ( ) {
387
+ let vec = iterator
388
+ . collect :: < PyResult < Vec < _ > > > ( )
389
+ . map_err ( |_| ValError :: new ( ErrorKind :: IterationError , self ) ) ?;
390
+ Ok ( PyTuple :: new ( self . py ( ) , vec) . into ( ) )
317
391
} else {
318
392
Err ( ValError :: new ( ErrorKind :: SetType , self ) )
319
393
}
@@ -327,6 +401,24 @@ impl<'a> Input<'a> for PyAny {
327
401
}
328
402
}
329
403
404
+ #[ cfg( not( PyPy ) ) ]
405
+ fn lax_frozenset ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
406
+ if let Ok ( frozen_set) = self . cast_as :: < PyFrozenSet > ( ) {
407
+ Ok ( frozen_set. into ( ) )
408
+ } else if let Ok ( set) = self . cast_as :: < PySet > ( ) {
409
+ Ok ( set. into ( ) )
410
+ } else if let Ok ( list) = self . cast_as :: < PyList > ( ) {
411
+ Ok ( list. into ( ) )
412
+ } else if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
413
+ Ok ( tuple. into ( ) )
414
+ } else if let Some ( tuple) = extract_gen_dict ! ( PyTuple , self ) {
415
+ Ok ( tuple. into ( ) )
416
+ } else {
417
+ Err ( ValError :: new ( ErrorKind :: FrozenSetType , self ) )
418
+ }
419
+ }
420
+
421
+ #[ cfg( PyPy ) ]
330
422
fn lax_frozenset ( & ' a self ) -> ValResult < GenericListLike < ' a > > {
331
423
if let Ok ( frozen_set) = self . cast_as :: < PyFrozenSet > ( ) {
332
424
Ok ( frozen_set. into ( ) )
@@ -336,6 +428,11 @@ impl<'a> Input<'a> for PyAny {
336
428
Ok ( list. into ( ) )
337
429
} else if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
338
430
Ok ( tuple. into ( ) )
431
+ } else if let Ok ( iterator) = self . cast_as :: < PyIterator > ( ) {
432
+ let vec = iterator
433
+ . collect :: < PyResult < Vec < _ > > > ( )
434
+ . map_err ( |_| ValError :: new ( ErrorKind :: IterationError , self ) ) ?;
435
+ Ok ( PyTuple :: new ( self . py ( ) , vec) . into ( ) )
339
436
} else {
340
437
Err ( ValError :: new ( ErrorKind :: FrozenSetType , self ) )
341
438
}
0 commit comments