scout-rig 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.vimproject +30 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/lib/scout/python/paths.rb +27 -0
- data/lib/scout/python/run.rb +122 -0
- data/lib/scout/python/script.rb +110 -0
- data/lib/scout/python/util.rb +52 -0
- data/lib/scout/python.rb +140 -0
- data/lib/scout-rig.rb +5 -0
- data/python/scout/__init__.py +221 -0
- data/python/scout/__pycache__/__init__.cpython-310.pyc +0 -0
- data/python/scout/__pycache__/workflow.cpython-310.pyc +0 -0
- data/python/scout/workflow/remote.py +103 -0
- data/python/scout/workflow.py +64 -0
- data/python/test.py +12 -0
- data/scout-rig.gemspec +56 -0
- data/test/scout/python/test_script.rb +61 -0
- data/test/scout/python/test_util.rb +25 -0
- data/test/scout/test_python.rb +158 -0
- data/test/test_helper.rb +5 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bcb31a6421de24abf3a11f37bcf00a295ffcf9d5163c55f02ccdb806ff54c4fb
|
4
|
+
data.tar.gz: b45379e2fb720a9e397faf467f7d3fcd9b14f0212096d40fcb62d2208a4936d1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cf8a3e4b67bdda6d867279d0b3e6166f5a942f0ee3a51d90105355121e8b2d8205b5f6468ec43c7cc487964d671bbeed73625815779fca633e64e4647e62a877
|
7
|
+
data.tar.gz: 8576a2ef1cd982db94fdab16ff207a1d9e7f189c125c5f92d4d0940091b452a64e69d3fa5af95f477131e8969686f47732ea79308c2f4f9734584e3ac3fbfffd
|
data/.document
ADDED
data/.vimproject
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
scout-rig=/$PWD filter="*" {
|
2
|
+
LICENSE.txt
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
lib=lib {
|
6
|
+
scout-rig.rb
|
7
|
+
scout=scout{
|
8
|
+
python.rb
|
9
|
+
python=python{
|
10
|
+
paths.rb
|
11
|
+
run.rb
|
12
|
+
script.rb
|
13
|
+
util.rb
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
test=test{
|
18
|
+
test_helper.rb
|
19
|
+
}
|
20
|
+
python=python{
|
21
|
+
test.py
|
22
|
+
scout=scout{
|
23
|
+
__init__.py
|
24
|
+
workflow.py
|
25
|
+
workflow=workflow{
|
26
|
+
remote.py
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2025 Miguel Vazquez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= scout-rig
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to scout-rig
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
+
* Fork the project.
|
10
|
+
* Start a feature/bugfix branch.
|
11
|
+
* Commit and push until you are happy with your contribution.
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2025 Miguel Vazquez. See LICENSE.txt for
|
18
|
+
further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
ENV["BRANCH"] = 'main'
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'rake'
|
7
|
+
require 'juwelier'
|
8
|
+
Juwelier::Tasks.new do |gem|
|
9
|
+
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
10
|
+
gem.name = "scout-rig"
|
11
|
+
gem.homepage = "http://github.com/mikisvaz/scout-rig"
|
12
|
+
gem.license = "MIT"
|
13
|
+
gem.summary = %Q{Scouts rigging things together}
|
14
|
+
gem.description = %Q{Use other coding languages in your scout applications}
|
15
|
+
gem.email = "mikisvaz@gmail.com"
|
16
|
+
gem.authors = ["Miguel Vazquez"]
|
17
|
+
|
18
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
19
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
20
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
21
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
22
|
+
gem.add_development_dependency "juwelier", "~> 2.1.0"
|
23
|
+
|
24
|
+
gem.add_runtime_dependency 'pycall', '> 0'
|
25
|
+
end
|
26
|
+
Juwelier::RubygemsDotOrgTasks.new
|
27
|
+
require 'rake/testtask'
|
28
|
+
Rake::TestTask.new(:test) do |test|
|
29
|
+
test.libs << 'lib' << 'test'
|
30
|
+
test.pattern = 'test/**/test_*.rb'
|
31
|
+
test.verbose = true
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Code coverage detail"
|
35
|
+
task :simplecov do
|
36
|
+
ENV['COVERAGE'] = "true"
|
37
|
+
Rake::Task['test'].execute
|
38
|
+
end
|
39
|
+
|
40
|
+
task :default => :test
|
41
|
+
|
42
|
+
require 'rdoc/task'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "scout-rig #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ScoutPython
|
2
|
+
class << self
|
3
|
+
attr_accessor :paths
|
4
|
+
def paths
|
5
|
+
@paths ||= []
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.add_path(path)
|
10
|
+
self.paths << path
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.add_paths(paths)
|
14
|
+
self.paths.concat paths
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.process_paths
|
18
|
+
ScoutPython.run_direct 'sys' do
|
19
|
+
ScoutPython.paths.each do |path|
|
20
|
+
sys.path.append path
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
add_paths(Scout.python.find_all)
|
27
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module ScoutPython
|
2
|
+
class << self
|
3
|
+
attr_accessor :thread
|
4
|
+
end
|
5
|
+
|
6
|
+
class Binding
|
7
|
+
include PyCall::Import
|
8
|
+
|
9
|
+
def run(*args, &block)
|
10
|
+
instance_exec(*args, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.thread
|
15
|
+
@thread ||= defined?(@thread) ? @thread : nil
|
16
|
+
end
|
17
|
+
|
18
|
+
MUTEX= Mutex.new
|
19
|
+
QUEUE_IN ||= Queue.new
|
20
|
+
QUEUE_OUT ||= Queue.new
|
21
|
+
def self.synchronize(&block)
|
22
|
+
MUTEX.synchronize &block
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.init_thread
|
26
|
+
if defined?(self.thread) && (self.thread && ! self.thread.alive?)
|
27
|
+
Log.warn "Reloading ScoutPython thread"
|
28
|
+
self.thread.join
|
29
|
+
self.thread = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
self.thread ||= Thread.new do
|
33
|
+
require 'pycall'
|
34
|
+
ScoutPython.process_paths
|
35
|
+
begin
|
36
|
+
while block = QUEUE_IN.pop
|
37
|
+
break if block == :stop
|
38
|
+
res =
|
39
|
+
begin
|
40
|
+
module_eval(&block)
|
41
|
+
rescue Exception
|
42
|
+
Log.exception $!
|
43
|
+
raise $!
|
44
|
+
end
|
45
|
+
|
46
|
+
QUEUE_OUT.push res
|
47
|
+
end
|
48
|
+
rescue Exception
|
49
|
+
Log.exception $!
|
50
|
+
raise $!
|
51
|
+
ensure
|
52
|
+
PyCall.finalize if PyCall.respond_to?(:finalize)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.run_in_thread(&block)
|
58
|
+
self.synchronize do
|
59
|
+
init_thread
|
60
|
+
QUEUE_IN.push block
|
61
|
+
QUEUE_OUT.pop
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.stop_thread
|
66
|
+
self.synchronize do
|
67
|
+
QUEUE_IN.push :stop
|
68
|
+
end if self.thread && self.thread.alive?
|
69
|
+
self.thread.join if self.thread
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.run_direct(mod = nil, imports = nil, &block)
|
73
|
+
if mod
|
74
|
+
if Hash === imports
|
75
|
+
pyimport mod, **imports
|
76
|
+
elsif imports.nil?
|
77
|
+
pyimport mod
|
78
|
+
else
|
79
|
+
pyfrom mod, :import => imports
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module_eval(&block)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.run_threaded(mod = nil, imports = nil, &block)
|
87
|
+
run_in_thread do
|
88
|
+
if Hash === imports
|
89
|
+
pyimport mod, **imports
|
90
|
+
elsif imports.nil?
|
91
|
+
pyimport mod
|
92
|
+
else
|
93
|
+
pyfrom mod, :import => imports
|
94
|
+
end
|
95
|
+
end if mod
|
96
|
+
|
97
|
+
run_in_thread(&block)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.run_simple(mod = nil, imports = nil, &block)
|
101
|
+
self.synchronize do
|
102
|
+
ScoutPython.process_paths
|
103
|
+
run_direct(mod, imports, &block)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class << self
|
108
|
+
alias run run_simple
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.run_log(mod = nil, imports = nil, severity = 0, severity_err = nil, &block)
|
112
|
+
Log.trap_std("Python STDOUT", "Python STDERR", severity, severity_err) do
|
113
|
+
run(mod, imports, &block)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.run_log_stderr(mod = nil, imports = nil, severity = 0, &block)
|
118
|
+
Log.trap_stderr("Python STDERR", severity) do
|
119
|
+
run(mod, imports, &block)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module ScoutPython
|
2
|
+
def self.ruby2python(object)
|
3
|
+
case object
|
4
|
+
when Float::INFINITY
|
5
|
+
"inf"
|
6
|
+
when nil
|
7
|
+
"None"
|
8
|
+
when ":NA"
|
9
|
+
"None"
|
10
|
+
when Symbol
|
11
|
+
"#{ object }"
|
12
|
+
when String
|
13
|
+
object = object.dup if Path === object
|
14
|
+
object[0] == ":" ? object[1..-1] : "'#{ object }'"
|
15
|
+
when Numeric
|
16
|
+
object
|
17
|
+
when TrueClass
|
18
|
+
"True"
|
19
|
+
when FalseClass
|
20
|
+
"False"
|
21
|
+
when Array
|
22
|
+
"[#{object.collect{|e| ruby2python(e) } * ", "}]"
|
23
|
+
when Hash
|
24
|
+
"{" << object.collect{|k,v| [ruby2python(k.to_s), ruby2python(v)] * ":"} * ", " << "}"
|
25
|
+
else
|
26
|
+
raise "Type of object not known: #{ object.inspect }"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.load_script_variables(variables = {})
|
31
|
+
code = "# Variables\nimport scout\n"
|
32
|
+
tmp_files = []
|
33
|
+
variables.each do |name,value|
|
34
|
+
case value
|
35
|
+
when TSV
|
36
|
+
tmp_file = TmpFile.tmp_file
|
37
|
+
tmp_files << tmp_file
|
38
|
+
Open.write(tmp_file, value.to_s)
|
39
|
+
code << "#{name} = scout.tsv('#{tmp_file}')" << "\n"
|
40
|
+
else
|
41
|
+
code << "#{name} = #{ScoutPython.ruby2python(value)}" << "\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
[code, tmp_files]
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.save_script_result_pickle(file)
|
49
|
+
<<-EOF
|
50
|
+
|
51
|
+
# Save
|
52
|
+
try: result
|
53
|
+
except NameError: result = None
|
54
|
+
if result is not None:
|
55
|
+
import pickle
|
56
|
+
file = open('#{file}', 'wb')
|
57
|
+
# dump information to that file
|
58
|
+
pickle.dump(result, file)
|
59
|
+
EOF
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.load_pickle(file)
|
63
|
+
require 'python/pickle'
|
64
|
+
Log.debug ("Loading pickle #{file}")
|
65
|
+
Python::Pickle.load_file(file)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.save_script_result_json(file)
|
69
|
+
<<-EOF
|
70
|
+
|
71
|
+
# Save
|
72
|
+
try: result
|
73
|
+
except NameError: result = None
|
74
|
+
if result is not None:
|
75
|
+
import json
|
76
|
+
file = open('#{file}', 'w', encoding='utf-8')
|
77
|
+
# dump information to that file
|
78
|
+
file.write(json.dumps(result))
|
79
|
+
file.flush
|
80
|
+
file.close
|
81
|
+
EOF
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.load_json(file)
|
85
|
+
JSON.load_file(file)
|
86
|
+
end
|
87
|
+
|
88
|
+
class << self
|
89
|
+
alias save_script_result save_script_result_pickle
|
90
|
+
alias load_result load_pickle
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.script(text, variables = {})
|
94
|
+
if variables.any?
|
95
|
+
variable_definitions, tmp_files = load_script_variables(variables)
|
96
|
+
text = variable_definitions + "\n# Script\n" + text
|
97
|
+
end
|
98
|
+
|
99
|
+
TmpFile.with_file do |tmp_file|
|
100
|
+
text += save_script_result(tmp_file)
|
101
|
+
Log.debug "Running python script:\n#{text.dup}"
|
102
|
+
path_env = ScoutPython.paths * ":"
|
103
|
+
CMD.cmd_log("env PYTHONPATH=#{path_env} python", {in: text})
|
104
|
+
tmp_files.each{|file| Open.rm_rf file } if tmp_files
|
105
|
+
if Open.exists?(tmp_file)
|
106
|
+
load_result(tmp_file)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ScoutPython
|
2
|
+
def self.py2ruby_a(array)
|
3
|
+
PyCall::List.(array).to_a
|
4
|
+
end
|
5
|
+
|
6
|
+
class << self
|
7
|
+
alias to_a py2ruby_a
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.tsv2df(tsv)
|
11
|
+
df = nil
|
12
|
+
ScoutPython.run_direct 'pandas' do
|
13
|
+
df = pandas.DataFrame.new(tsv.values, columns: tsv.fields, index: tsv.keys)
|
14
|
+
df.columns.name = tsv.key_field
|
15
|
+
end
|
16
|
+
df
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.df2tsv(tuple, options = {})
|
20
|
+
options = IndiferentHash.add_defaults options, :type => :list
|
21
|
+
IndiferentHash.setup options
|
22
|
+
tsv = TSV.setup({}, options)
|
23
|
+
tsv.key_field = options[:key_field] || tuple.columns.name.to_s
|
24
|
+
tsv.fields = py2ruby_a(tuple.columns.values)
|
25
|
+
keys = py2ruby_a(tuple.index.values)
|
26
|
+
PyCall.len(tuple.index).times do |i|
|
27
|
+
k = keys[i]
|
28
|
+
tsv[k] = py2ruby_a(tuple.values[i])
|
29
|
+
end
|
30
|
+
tsv
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.list2ruby(list)
|
34
|
+
return list unless PyCall::List === list
|
35
|
+
list.collect do |e|
|
36
|
+
list2ruby(e)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.numpy2ruby(numpy)
|
41
|
+
list2ruby(numpy.tolist)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.obj2hash(obj)
|
45
|
+
hash = {}
|
46
|
+
ScoutPython.iterate obj.keys do |k|
|
47
|
+
hash[k] = obj[k]
|
48
|
+
end
|
49
|
+
hash
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/lib/scout/python.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'scout'
|
2
|
+
require 'pycall/import'
|
3
|
+
require_relative 'python/paths'
|
4
|
+
require_relative 'python/run'
|
5
|
+
|
6
|
+
module ScoutPython
|
7
|
+
extend PyCall::Import
|
8
|
+
|
9
|
+
class ScoutPythonException < StandardError; end
|
10
|
+
|
11
|
+
def self.init_scout
|
12
|
+
if ! defined?(@@__init_scout_python) || ! @@__init_scout_python
|
13
|
+
ScoutPython.process_paths
|
14
|
+
res = ScoutPython.run do
|
15
|
+
Log.debug "Loading python 'scout' module into pycall ScoutPython module"
|
16
|
+
pyimport("scout")
|
17
|
+
end
|
18
|
+
@@__init_scout_python = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.import_method(module_name, method_name, as = nil)
|
23
|
+
init_scout
|
24
|
+
ScoutPython.pyfrom module_name, import: method_name
|
25
|
+
ScoutPython.method(method_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.call_method(module_name, method_name, *args)
|
29
|
+
ScoutPython.import_method(module_name, method_name).call(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.get_module(module_name)
|
33
|
+
init_scout
|
34
|
+
save_module_name = module_name.to_s.gsub(".", "_")
|
35
|
+
ScoutPython.pyimport(module_name, as: save_module_name)
|
36
|
+
ScoutPython.send(save_module_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.get_class(module_name, class_name)
|
40
|
+
mod = get_module(module_name)
|
41
|
+
mod.send(class_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.class_new_obj(module_name, class_name, args={})
|
45
|
+
ScoutPython.get_class(module_name, class_name).new(**args)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.exec(script)
|
49
|
+
PyCall.exec(script)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.iterate_index(elem, options = {})
|
53
|
+
bar = options[:bar]
|
54
|
+
|
55
|
+
len = PyCall.len(elem)
|
56
|
+
case bar
|
57
|
+
when TrueClass
|
58
|
+
bar = Log::ProgressBar.new nil, :desc => "ScoutPython iterate"
|
59
|
+
when String
|
60
|
+
bar = Log::ProgressBar.new nil, :desc => bar
|
61
|
+
end
|
62
|
+
|
63
|
+
len.times do |i|
|
64
|
+
begin
|
65
|
+
yield elem[i]
|
66
|
+
bar.tick if bar
|
67
|
+
rescue PyCall::PyError
|
68
|
+
if $!.type.to_s == "<class 'StopIteration'>"
|
69
|
+
break
|
70
|
+
else
|
71
|
+
raise $!
|
72
|
+
end
|
73
|
+
rescue
|
74
|
+
bar.error if bar
|
75
|
+
raise $!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Log::ProgressBar.remove_bar bar if bar
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.iterate(iterator, options = {}, &block)
|
84
|
+
if ! iterator.respond_to?(:__next__)
|
85
|
+
if iterator.respond_to?(:__iter__)
|
86
|
+
iterator = iterator.__iter__
|
87
|
+
else
|
88
|
+
return iterate_index(iterator, options, &block)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
bar = options[:bar]
|
93
|
+
|
94
|
+
case bar
|
95
|
+
when TrueClass
|
96
|
+
bar = Log::ProgressBar.new nil, :desc => "ScoutPython iterate"
|
97
|
+
when String
|
98
|
+
bar = Log::ProgressBar.new nil, :desc => bar
|
99
|
+
end
|
100
|
+
|
101
|
+
while true
|
102
|
+
begin
|
103
|
+
elem = iterator.__next__
|
104
|
+
yield elem
|
105
|
+
bar.tick if bar
|
106
|
+
rescue PyCall::PyError
|
107
|
+
if $!.type.to_s == "<class 'StopIteration'>"
|
108
|
+
break
|
109
|
+
else
|
110
|
+
raise $!
|
111
|
+
end
|
112
|
+
rescue
|
113
|
+
bar.error if bar
|
114
|
+
raise $!
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
Log::ProgressBar.remove_bar bar if bar
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.collect(iterator, options = {}, &block)
|
123
|
+
acc = []
|
124
|
+
self.iterate(iterator, options) do |elem|
|
125
|
+
res = block.call elem
|
126
|
+
acc << res
|
127
|
+
end
|
128
|
+
acc
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.new_binding
|
132
|
+
Binding.new
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.binding_run(binding = nil, *args, &block)
|
136
|
+
binding = new_binding
|
137
|
+
binding.instance_exec *args, &block
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|