88using System . Numerics ;
99using System . Runtime . InteropServices ;
1010
11- using Microsoft . Scripting ;
12- using Microsoft . Scripting . Runtime ;
13- using Microsoft . Scripting . Utils ;
14-
1511using IronPython . Runtime ;
1612using IronPython . Runtime . Binding ;
1713using IronPython . Runtime . Exceptions ;
1814using IronPython . Runtime . Operations ;
1915using IronPython . Runtime . Types ;
2016
17+ using Microsoft . Scripting ;
18+ using Microsoft . Scripting . Runtime ;
19+ using Microsoft . Scripting . Utils ;
20+
2121[ assembly: PythonModule ( "itertools" , typeof ( IronPython . Modules . PythonIterTools ) ) ]
2222namespace IronPython . Modules {
2323 public static class PythonIterTools {
@@ -233,7 +233,7 @@ private static void EnsureIterator(CodeContext/*!*/ context, object iter) {
233233 if ( iter == null ||
234234 ! PythonOps . HasAttr ( context , iter , "__iter__" ) &&
235235 ! PythonOps . HasAttr ( context , iter , "__getitem__" ) ) {
236- throw PythonOps . TypeError ( "'{0}' object is not iterable" , PythonOps . GetPythonTypeName ( iter ) ) ;
236+ throw PythonOps . TypeError ( "'{0}' object is not iterable" , PythonOps . GetPythonTypeName ( iter ) ) ;
237237 }
238238 }
239239
@@ -276,13 +276,13 @@ public count(BigInteger start) {
276276 InnerEnumerator = BigIntYielder ( this , start , 1 ) ;
277277 }
278278
279- public count ( int start = 0 , int step = 1 ) {
279+ public count ( int start = 0 , int step = 1 ) {
280280 _curInt = start ;
281281 _step = step ;
282282 InnerEnumerator = IntYielder ( this , start , step ) ;
283283 }
284284
285- public count ( [ DefaultParameterValue ( 0 ) ] int start , BigInteger step ) {
285+ public count ( [ DefaultParameterValue ( 0 ) ] int start , BigInteger step ) {
286286 _curInt = start ;
287287 _step = step ;
288288 InnerEnumerator = IntYielder ( this , start , step ) ;
@@ -300,7 +300,7 @@ public count(BigInteger start, BigInteger step) {
300300 InnerEnumerator = BigIntYielder ( this , start , step ) ;
301301 }
302302
303- public count ( CodeContext /*!*/ context , [ DefaultParameterValue ( 0 ) ] object start , [ DefaultParameterValue ( 1 ) ] object step ) {
303+ public count ( CodeContext /*!*/ context , [ DefaultParameterValue ( 0 ) ] object start , [ DefaultParameterValue ( 1 ) ] object step ) {
304304 EnsureNumeric ( context , start ) ;
305305 EnsureNumeric ( context , step ) ;
306306 _cur = start ;
@@ -315,7 +315,7 @@ private static void EnsureNumeric(CodeContext/*!*/ context, object num) {
315315 if ( num == null ||
316316 ! PythonOps . HasAttr ( context , num , "__int__" ) &&
317317 ! PythonOps . HasAttr ( context , num , "__float__" ) ) {
318- throw PythonOps . TypeError ( "a number is required" ) ;
318+ throw PythonOps . TypeError ( "a number is required" ) ;
319319 }
320320 }
321321
@@ -548,9 +548,9 @@ private IEnumerator<object> Yielder(IEnumerator iter) {
548548 private IEnumerator < object > Grouper ( IEnumerator iter , object curKey ) {
549549 while ( PythonContext . Equal ( GetKey ( iter . Current ) , curKey ) ) {
550550 yield return iter . Current ;
551- if ( ! MoveNextHelper ( iter ) ) {
552- _fFinished = true ;
553- yield break ;
551+ if ( ! MoveNextHelper ( iter ) ) {
552+ _fFinished = true ;
553+ yield break ;
554554 }
555555 }
556556 }
@@ -675,7 +675,7 @@ public zip_longest(params object[] iterables) {
675675 }
676676 }
677677
678- public zip_longest ( [ ParamDictionary ] IDictionary < object , object > paramDict , params object [ ] iterables ) {
678+ public zip_longest ( [ ParamDictionary ] IDictionary < object , object > paramDict , params object [ ] iterables ) {
679679 object fill ;
680680
681681 if ( paramDict . TryGetValue ( "fillvalue" , out fill ) ) {
@@ -760,11 +760,14 @@ private static Exception UnexpectedKeywordArgument(IDictionary<object, object> p
760760
761761 [ PythonType ]
762762 public class product : IterBase {
763+ private PythonTuple [ ] tuples ;
764+
763765 public product ( CodeContext context , params object [ ] iterables ) {
764- InnerEnumerator = Yielder ( ArrayUtils . ConvertAll ( iterables , x => new PythonList ( context , PythonOps . GetEnumerator ( x ) ) ) ) ;
766+ tuples = ArrayUtils . ConvertAll ( iterables , x => new PythonTuple ( PythonOps . GetEnumerator ( x ) ) ) ;
767+ InnerEnumerator = Yielder ( tuples ) ;
765768 }
766769
767- public product ( CodeContext context , [ ParamDictionary ] IDictionary < object , object > paramDict , params object [ ] iterables ) {
770+ public product ( CodeContext context , [ ParamDictionary ] IDictionary < object , object > paramDict , params object [ ] iterables ) {
768771 object repeat ;
769772 int iRepeat = 1 ;
770773 if ( paramDict . TryGetValue ( "repeat" , out repeat ) ) {
@@ -782,29 +785,28 @@ public product(CodeContext context, [ParamDictionary]IDictionary<object, object>
782785 throw UnexpectedKeywordArgument ( paramDict ) ;
783786 }
784787
785- PythonList [ ] finalIterables = new PythonList [ iterables . Length * iRepeat ] ;
788+ tuples = new PythonTuple [ iterables . Length * iRepeat ] ;
786789 for ( int i = 0 ; i < iRepeat ; i ++ ) {
787790 for ( int j = 0 ; j < iterables . Length ; j ++ ) {
788- finalIterables [ i * iterables . Length + j ] = new PythonList ( context , iterables [ j ] ) ;
791+ tuples [ i * iterables . Length + j ] = new PythonTuple ( iterables [ j ] ) ;
789792 }
790793 }
791- InnerEnumerator = Yielder ( finalIterables ) ;
794+ InnerEnumerator = Yielder ( tuples ) ;
792795 }
793796
794797 public PythonTuple __reduce__ ( ) {
795- // TODO
796798 return PythonTuple . MakeTuple (
797799 DynamicHelpers . GetPythonType ( this ) ,
798- PythonTuple . MakeTuple ( ) , // arguments
799- null // state
800+ PythonTuple . MakeTuple ( tuples ) , // arguments
801+ null // TODO: state
800802 ) ;
801803 }
802804
803805 public void __setstate__ ( object state ) {
804806 // TODO
805807 }
806808
807- private IEnumerator < object > Yielder ( PythonList [ ] iterables ) {
809+ private IEnumerator < object > Yielder ( PythonTuple [ ] iterables ) {
808810 if ( iterables . Length > 0 ) {
809811 IEnumerator [ ] enums = new IEnumerator [ iterables . Length ] ;
810812 enums [ 0 ] = iterables [ 0 ] . GetEnumerator ( ) ;
@@ -833,6 +835,7 @@ private IEnumerator<object> Yielder(PythonList[] iterables) {
833835 } else {
834836 yield return PythonTuple . EMPTY ;
835837 }
838+ tuples = new PythonTuple [ 1 ] { PythonTuple . EMPTY } ;
836839 }
837840 }
838841
@@ -987,7 +990,7 @@ public permutations(CodeContext context, object iterable) {
987990
988991 public permutations ( CodeContext context , object iterable , object r ) {
989992 _data = new PythonList ( context , iterable ) ;
990-
993+
991994 InnerEnumerator = Yielder ( GetR ( r , _data ) ) ;
992995 }
993996
@@ -1078,7 +1081,7 @@ public repeat(object @object) {
10781081 public repeat ( object @object , int times ) {
10791082 _obj = @object ;
10801083 InnerEnumerator = Yielder ( ) ;
1081- _remaining = times ;
1084+ _remaining = times < 0 ? 0 : times ;
10821085 }
10831086
10841087 private IEnumerator < object > Yielder ( ) {
@@ -1094,10 +1097,9 @@ public int __length_hint__() {
10941097 }
10951098
10961099 public PythonTuple __reduce__ ( ) {
1097- // TODO
10981100 return PythonTuple . MakeTuple (
10991101 DynamicHelpers . GetPythonType ( this ) ,
1100- PythonTuple . MakeTuple ( ) // arguments
1102+ _fInfinite ? PythonTuple . MakeTuple ( _obj ) : PythonTuple . MakeTuple ( _obj , _remaining ) // arguments
11011103 ) ;
11021104 }
11031105
@@ -1150,9 +1152,9 @@ IEnumerator IEnumerable.GetEnumerator() {
11501152
11511153 #endregion
11521154 }
1153-
1155+
11541156 [ PythonType ]
1155- public class starmap : IterBase {
1157+ public class starmap : IterBase {
11561158 public starmap ( CodeContext context , object function , object iterable ) {
11571159 InnerEnumerator = Yielder ( context , function , PythonOps . GetEnumerator ( iterable ) ) ;
11581160 }
@@ -1211,7 +1213,7 @@ public void __setstate__(object state) {
12111213
12121214 private IEnumerator < object > Yielder ( object predicate , IEnumerator iter ) {
12131215 while ( MoveNextHelper ( iter ) ) {
1214- if ( ! Converter . ConvertToBoolean (
1216+ if ( ! Converter . ConvertToBoolean (
12151217 _context . LanguageContext . CallSplat ( predicate , iter . Current )
12161218 ) ) {
12171219 break ;
@@ -1222,8 +1224,8 @@ private IEnumerator<object> Yielder(object predicate, IEnumerator iter) {
12221224 }
12231225 }
12241226
1225- [ PythonHidden ]
1226- public class TeeIterator : IEnumerator , IWeakReferenceable {
1227+ [ PythonType ( "_tee" ) ]
1228+ public sealed class TeeIterator : IEnumerator , IWeakReferenceable {
12271229 internal IEnumerator _iter ;
12281230 internal PythonList _data ;
12291231 private int _curIndex = - 1 ;
0 commit comments