File tree Expand file tree Collapse file tree 6 files changed +76
-0
lines changed Expand file tree Collapse file tree 6 files changed +76
-0
lines changed Original file line number Diff line number Diff line change @@ -5,6 +5,7 @@ module PyCall
55 require 'pycall/pyobject_wrapper'
66 require 'pycall/pytypeobject_wrapper'
77 require 'pycall/pymodule_wrapper'
8+ require 'pycall/iterable_wrapper'
89 require 'pycall/init'
910
1011 module_function
@@ -73,6 +74,10 @@ def import_module(name)
7374 LibPython ::Helpers . import_module ( name )
7475 end
7576
77+ def iterable ( obj )
78+ IterableWrapper . new ( obj )
79+ end
80+
7681 def len ( obj )
7782 case obj
7883 when PyObjectWrapper
Original file line number Diff line number Diff line change 1+ module PyCall
2+ class IterableWrapper
3+ include Enumerable
4+
5+ def initialize ( obj )
6+ @obj = check_iterable ( obj )
7+ end
8+
9+ private def check_iterable ( obj )
10+ unless PyCall . hasattr? ( obj , :__iter__ )
11+ raise ArgumentError , "%p object is not iterable" % obj
12+ end
13+ obj
14+ end
15+
16+ def each
17+ return enum_for ( __method__ ) unless block_given?
18+ iter = @obj . __iter__ ( )
19+ while true
20+ begin
21+ yield iter . __next__ ( )
22+ rescue PyCall ::PyError => err
23+ if err . type == PyCall . builtins . StopIteration
24+ break
25+ else
26+ raise err
27+ end
28+ end
29+ end
30+ end
31+ end
32+ end
Original file line number Diff line number Diff line change 11require "pycall"
2+ require "pathname"
23require "test-unit"
4+
5+ test_dir = Pathname . new ( __dir__ )
6+ python_dir = test_dir + "python"
7+
8+ PyCall . sys . path . append ( python_dir . to_s )
Original file line number Diff line number Diff line change 1+ class IntGenerator (object ):
2+ def __init__ (self , start , stop ):
3+ self .start = start
4+ self .stop = stop
5+ self .current = None
6+
7+ def __iter__ (self ):
8+ self .current = self .start
9+ return self
10+
11+ def __next__ (self ):
12+ if self .current == self .stop :
13+ raise StopIteration ()
14+ value = self .current
15+ self .current += 1
16+ return value
17+
18+ if __name__ == "__main__" :
19+ print (list (IntGenerator (105 , 115 )))
Original file line number Diff line number Diff line change @@ -2,4 +2,18 @@ class PyCallTest < Test::Unit::TestCase
22 def test_VERSION
33 assert_not_nil ( PyCall ::VERSION )
44 end
5+
6+ def test_iterable
7+ simple_iterable = PyCall . import_module ( "pycall.simple_iterable" )
8+ int_gen = simple_iterable . IntGenerator . new ( 10 , 25 )
9+ iterable = PyCall . iterable ( int_gen )
10+ assert_equal ( {
11+ enumerable_p : true ,
12+ each_to_a : ( 10 .. 24 ) . to_a ,
13+ } ,
14+ {
15+ enumerable_p : iterable . is_a? ( Enumerable ) ,
16+ each_to_a : iterable . each . to_a
17+ } )
18+ end
519end
You can’t perform that action at this time.
0 commit comments