pycall.rb
pycall.rb copied to clipboard
Missing wrappers for iterators and generators
I want to write the following Python code
for item in collection:
...
like the following in Ruby with PyCall:
collection.each do |item|
...
end
Now PyCall defines each
methods in PyCall::List and PyCall::Dict in specific ways.
It needs to be rewritten in more generic way.
One candidate is PyCall.enum(obj)
to get an Enumerator object.
This is a concept implementation:
module PyCall
module_function
def enum(obj)
gen = obj.__iter__
Enumerator.new do |y|
begin
yield gen.__next__ while true
obj
rescue PyError, err
# ignore StopIteration exception
return obj if err.type.match?(LibPython::API::PyExc_StopIteration)
raise
end
end
end
end
Just one note: I needed to use generator using following function PyCall.builtins.next(generator)
Here is my version of the patch:
module PyCall
module_function
def enum(generator)
Enumerator.new do |enum|
begin
loop do
enum << PyCall.builtins.next(generator)
end
rescue PyError => error
raise err unless error.type.to_s.match?("StopIteration")
end
end
end
end
@allomov Could you please make a pull-request?