1- use super :: { PyType , PyTypeRef } ;
1+ use super :: PyType ;
22use crate :: {
3- Context , Py , PyObjectRef , PyPayload , PyResult , VirtualMachine ,
3+ AsObject , Context , Py , PyObjectRef , PyPayload , PyRef , PyResult , TryFromObject , VirtualMachine ,
44 builtins:: PyTupleRef ,
55 class:: PyClassImpl ,
6- function:: PosArgs ,
6+ function:: { ArgIntoBool , OptionalArg , PosArgs } ,
77 protocol:: { PyIter , PyIterReturn } ,
8- raise_if_stop,
98 types:: { Constructor , IterNext , Iterable , SelfIter } ,
109} ;
10+ use rustpython_common:: atomic:: { self , PyAtomic , Radium } ;
1111
1212#[ pyclass( module = false , name = "map" , traverse) ]
1313#[ derive( Debug ) ]
1414pub struct PyMap {
1515 mapper : PyObjectRef ,
1616 iterators : Vec < PyIter > ,
17+ #[ pytraverse( skip) ]
18+ strict : PyAtomic < bool > ,
1719}
1820
1921impl PyPayload for PyMap {
@@ -23,16 +25,27 @@ impl PyPayload for PyMap {
2325 }
2426}
2527
28+ #[ derive( FromArgs ) ]
29+ pub struct PyMapNewArgs {
30+ #[ pyarg( named, optional) ]
31+ strict : OptionalArg < bool > ,
32+ }
33+
2634impl Constructor for PyMap {
27- type Args = ( PyObjectRef , PosArgs < PyIter > ) ;
35+ type Args = ( PyObjectRef , PosArgs < PyIter > , PyMapNewArgs ) ;
2836
2937 fn py_new (
3038 _cls : & Py < PyType > ,
31- ( mapper, iterators) : Self :: Args ,
39+ ( mapper, iterators, args ) : Self :: Args ,
3240 _vm : & VirtualMachine ,
3341 ) -> PyResult < Self > {
3442 let iterators = iterators. into_vec ( ) ;
35- Ok ( Self { mapper, iterators } )
43+ let strict = Radium :: new ( args. strict . unwrap_or ( false ) ) ;
44+ Ok ( Self {
45+ mapper,
46+ iterators,
47+ strict,
48+ } )
3649 }
3750}
3851
@@ -48,10 +61,24 @@ impl PyMap {
4861 }
4962
5063 #[ pymethod]
51- fn __reduce__ ( & self , vm : & VirtualMachine ) -> ( PyTypeRef , PyTupleRef ) {
52- let mut vec = vec ! [ self . mapper. clone( ) ] ;
53- vec. extend ( self . iterators . iter ( ) . map ( |o| o. clone ( ) . into ( ) ) ) ;
54- ( vm. ctx . types . map_type . to_owned ( ) , vm. new_tuple ( vec) )
64+ fn __reduce__ ( zelf : PyRef < Self > , vm : & VirtualMachine ) -> PyResult < PyTupleRef > {
65+ let cls = zelf. class ( ) . to_owned ( ) ;
66+ let mut vec = vec ! [ zelf. mapper. clone( ) ] ;
67+ vec. extend ( zelf. iterators . iter ( ) . map ( |o| o. clone ( ) . into ( ) ) ) ;
68+ let tuple_args = vm. ctx . new_tuple ( vec) ;
69+ Ok ( if zelf. strict . load ( atomic:: Ordering :: Acquire ) {
70+ vm. new_tuple ( ( cls, tuple_args, true ) )
71+ } else {
72+ vm. new_tuple ( ( cls, tuple_args) )
73+ } )
74+ }
75+
76+ #[ pymethod]
77+ fn __setstate__ ( zelf : PyRef < Self > , state : PyObjectRef , vm : & VirtualMachine ) -> PyResult < ( ) > {
78+ if let Ok ( obj) = ArgIntoBool :: try_from_object ( vm, state) {
79+ zelf. strict . store ( obj. into ( ) , atomic:: Ordering :: Release ) ;
80+ }
81+ Ok ( ( ) )
5582 }
5683}
5784
@@ -60,8 +87,35 @@ impl SelfIter for PyMap {}
6087impl IterNext for PyMap {
6188 fn next ( zelf : & Py < Self > , vm : & VirtualMachine ) -> PyResult < PyIterReturn > {
6289 let mut next_objs = Vec :: new ( ) ;
63- for iterator in & zelf. iterators {
64- let item = raise_if_stop ! ( iterator. next( vm) ?) ;
90+ for ( idx, iterator) in zelf. iterators . iter ( ) . enumerate ( ) {
91+ let item = match iterator. next ( vm) ? {
92+ PyIterReturn :: Return ( obj) => obj,
93+ PyIterReturn :: StopIteration ( v) => {
94+ if zelf. strict . load ( atomic:: Ordering :: Acquire ) {
95+ if idx > 0 {
96+ let plural = if idx == 1 { " " } else { "s 1-" } ;
97+ return Err ( vm. new_value_error ( format ! (
98+ "map() argument {} is shorter than argument{}{}" ,
99+ idx + 1 ,
100+ plural,
101+ idx,
102+ ) ) ) ;
103+ }
104+ for ( idx, iterator) in zelf. iterators [ 1 ..] . iter ( ) . enumerate ( ) {
105+ if let PyIterReturn :: Return ( _) = iterator. next ( vm) ? {
106+ let plural = if idx == 0 { " " } else { "s 1-" } ;
107+ return Err ( vm. new_value_error ( format ! (
108+ "map() argument {} is longer than argument{}{}" ,
109+ idx + 2 ,
110+ plural,
111+ idx + 1 ,
112+ ) ) ) ;
113+ }
114+ }
115+ }
116+ return Ok ( PyIterReturn :: StopIteration ( v) ) ;
117+ }
118+ } ;
65119 next_objs. push ( item) ;
66120 }
67121
0 commit comments