jkr 0.1.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5cc3028f9f18f51c7dae2c3c382bfa44763c0df2
4
- data.tar.gz: 538c2f84ff9a128ef584be7d5f37d9e9c9263731
3
+ metadata.gz: c2aa3b45798602f7adfa2ef39671bbd0c67248ad
4
+ data.tar.gz: 9033b8152c9b54663ba76df543cb11546bdb5f39
5
5
  SHA512:
6
- metadata.gz: 8ccfb21a505843e30005c5a402fcbf6da1cab077a25f8781d7e3b3ee5df3761567bbfccbcf4abd07585e9f06466b0587db63c3d55994160de3f6ed34cbcc49ff
7
- data.tar.gz: 55ec247337556c9fd37c6d446934f3962b34e932615acb478ad9018ae36c0fd365e7c04a1dc34bc4e9e7ee3b7326cc002751e2fe4ddd37fad8390e72849c0ede
6
+ metadata.gz: 9dc067dcb1007050e2317a34a2c6afa23a1dd82caa66b06fdef2e58b8d2779fab496780f39efedfbbd338cd41d7408faf3569273cb608eefa4cf3772c2f45128
7
+ data.tar.gz: 37d50d20c882cde08ed6527131f5d3ed4c2e690c60c7f05052727bb5244877449aa36ad45310e0e12a0e19f9c61696309f70891a06b7c892b3839cdf2f68962e
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  /bin/rake2thor
12
12
  /bin/thor
13
13
  /pkg/*.gem
14
+ /Gemfile.lock
@@ -76,7 +76,10 @@ _jkr() {
76
76
 
77
77
  __jkr_subcmds() {
78
78
  _values 'Jkr command' \
79
+ 'init[Init a Jkr environment]' \
79
80
  'execute[Execute a plan]' \
81
+ 'resume[Resume in-progress execution]' \
80
82
  'list[List jkr plans]' \
81
- 'analyze[Analyze a result]'
83
+ 'analyze[Analyze a result]' \
84
+ 'query[Query interesting result]'
82
85
  }
@@ -43,13 +43,7 @@ module Jkr
43
43
 
44
44
  desc "list", "List executable plans"
45
45
  def list()
46
- begin
47
- @jkr_env = Jkr::Env.new(options[:directory])
48
- rescue Errno::ENOENT
49
- puts(red("[ERROR] jkr dir not found at #{@options[:directory]}"))
50
- puts(red(" Maybe you are in a wrong directory."))
51
- exit(false)
52
- end
46
+ @jkr_env = create_env()
53
47
 
54
48
  plans = Dir.glob("#{@jkr_env.jkr_plan_dir}/*.plan").map do |plan_file_path|
55
49
  plan = Jkr::Plan.create_by_name(@jkr_env, File.basename(plan_file_path, ".plan"))
@@ -74,7 +68,7 @@ module Jkr
74
68
 
75
69
  desc "execute <plan> [<plan> ...]", "Execute plans"
76
70
  def execute(*plan_names)
77
- @jkr_env = Jkr::Env.new(options[:directory])
71
+ @jkr_env = create_env()
78
72
 
79
73
  if options[:debug]
80
74
  delete_files_on_error = false
@@ -89,21 +83,84 @@ module Jkr
89
83
  end
90
84
  end
91
85
 
92
- desc "analyze <result> [<result> ...]", "Run analysis script for executed results"
86
+ desc "resume [<result> ...]", "Resume in-progress execution"
87
+ def resume(*result_ids)
88
+ @jkr_env = create_env()
89
+ cur_result_id = Jkr::Env.find_result(Dir.pwd)
90
+ if cur_result_id
91
+ result_ids.push(cur_result_id)
92
+ end
93
+
94
+ result_ids.each do |rid|
95
+ plan = Plan.create_by_result_id(@jkr_env, rid)
96
+ Jkr::Trial.resume(@jkr_env, plan)
97
+ end
98
+ end
99
+
100
+ desc "analyze [<result> ...]", "Run analysis script for executed results"
93
101
  def analyze(*result_ids)
94
- @jkr_env = Jkr::Env.new(options[:directory])
102
+ @jkr_env = create_env()
103
+
104
+ # check if current dir is a result dir
105
+ cur_result_id = Jkr::Env.find_result(Dir.pwd)
106
+ if cur_result_id
107
+ result_ids.push(cur_result_id)
108
+ end
95
109
 
96
110
  result_ids.each do |arg|
97
111
  Jkr::Analysis.analyze(@jkr_env, arg)
98
112
  end
99
113
  end
100
114
 
115
+ desc "query <result>", "Query interesting result"
116
+ def query(result_id = nil)
117
+ @jkr_env = create_env()
118
+
119
+ if result_id == nil
120
+ # check if current dir is a result dir
121
+ cur_result_id = Jkr::Env.find_result(Dir.pwd)
122
+ if cur_result_id
123
+ result_id = cur_result_id
124
+ else
125
+ raise ArgumentError.new("Result ID must be specified.")
126
+ end
127
+ end
128
+
129
+ result_dir = Dir.glob(sprintf("#{@jkr_env.jkr_result_dir}/%05d*", result_id.to_i)).first
130
+
131
+ Dir.glob("#{result_dir}/[0-9][0-9][0-9][0-9][0-9]/metastore.msh").sort.each do |m|
132
+ metastore = Marshal.load(File.open(m))
133
+ params = Marshal.load(File.open(File.expand_path("../params.msh", m)))
134
+
135
+ disp = metastore[:vars].map do |var|
136
+ "#{var}: #{params[var].inspect}"
137
+ end.join(", ")
138
+
139
+ puts "#{File.basename(File.dirname(m))} | #{disp}"
140
+ end
141
+ end
142
+
101
143
  no_commands do
102
144
  def find_plan_file(plan_name)
103
145
  @jkr_env.plans.find do |plan_file_path|
104
146
  File.basename(plan_file_path) == plan_name + ".plan"
105
147
  end
106
148
  end
149
+
150
+ def create_env()
151
+ begin
152
+ if options[:directory]
153
+ return Jkr::Env.new(options[:directory])
154
+ else
155
+ return Jkr::Env.new(Jkr::Env.find(Dir.pwd))
156
+ end
157
+ rescue Errno::ENOENT
158
+ $stderr.puts(red("[ERROR] jkr dir not found at #{@options[:directory]}"))
159
+ $stderr.puts(red(" Maybe you are in a wrong directory."))
160
+ exit(false)
161
+ end
162
+
163
+ end
107
164
  end
108
165
  end
109
166
 
@@ -21,7 +21,7 @@ module Jkr
21
21
  @jkr_result_dir = File.join(@jkr_dir, RESULT_DIR)
22
22
  @jkr_script_dir = File.join(@jkr_dir, SCRIPT_DIR)
23
23
 
24
- unless Dir.exists?(@jkr_dir)
24
+ unless Dir.exists?(@env_dir)
25
25
  raise Errno::ENOENT.new(@jkr_dir)
26
26
  end
27
27
 
@@ -34,5 +34,64 @@ module Jkr
34
34
  end
35
35
  end
36
36
  end
37
+
38
+ def self.valid_env_dir?(dir)
39
+ jkr_dir = File.expand_path("jkr", dir)
40
+ plan_dir = File.expand_path("plan", jkr_dir)
41
+ script_dir = File.expand_path("script", jkr_dir)
42
+ result_dir = File.expand_path("result", jkr_dir)
43
+
44
+ [jkr_dir, result_dir, plan_dir, script_dir].each do |dir_|
45
+ unless Dir.exists?(dir_)
46
+ return false
47
+ end
48
+ end
49
+
50
+ true
51
+ end
52
+
53
+ # Find Jkr env dir if 'dir' is under an valid Jkr environemnt directory.
54
+ def self.find(dir)
55
+ dir = File.expand_path("./", dir)
56
+ while true
57
+ if valid_env_dir?(dir)
58
+ return dir
59
+ end
60
+
61
+ parent_dir = File.expand_path("../", dir)
62
+ if parent_dir == dir
63
+ break
64
+ else
65
+ dir = parent_dir
66
+ end
67
+ end
68
+
69
+ nil
70
+ end
71
+
72
+ # Find an executed Jkr result if 'dir' is under the result dir, and return result id.
73
+ # return nil otherwise.
74
+ def self.find_result(dir)
75
+ dir = File.expand_path("./", dir)
76
+ while true
77
+ parent_dir = File.expand_path("../", dir)
78
+ gp_dir = File.expand_path("../../", dir) # grand parent
79
+ ggp_dir = File.expand_path("../../../", dir) # grand grand parent
80
+
81
+ if ggp_dir == gp_dir
82
+ return nil
83
+ end
84
+
85
+ if valid_env_dir?(ggp_dir)
86
+ if File.basename(gp_dir) == "jkr" &&
87
+ File.basename(parent_dir) == "result" &&
88
+ File.basename(dir) =~ /^[0-9]+/
89
+ return File.basename(dir).to_i
90
+ end
91
+ end
92
+
93
+ dir = File.expand_path("../", dir)
94
+ end
95
+ end
37
96
  end
38
97
  end
@@ -93,12 +93,22 @@ module Jkr
93
93
  plan.file_path = finder.find_by_result_id(ret_id)
94
94
 
95
95
  plan.plan_search_path = [File.expand_path("../plan", plan.file_path)]
96
- plan.script_search_path = [File.expand_path("../script", plan.file_path)]
96
+ plan.script_search_path = [File.expand_path("../script", plan.file_path),
97
+ plan.jkr_env.jkr_script_dir]
97
98
 
98
99
  unless plan.file_path
99
100
  raise ArgumentError.new("Not valid result ID: #{ret_id}")
100
101
  end
101
102
 
103
+ resultset_num = sprintf "%05d", ret_id
104
+ dirs = Dir.glob(File.join(plan.jkr_env.jkr_result_dir, resultset_num)+"*")
105
+ if dirs.size == 0
106
+ raise RuntimeError.new("Resultset not found: #{ret_id}")
107
+ elsif dirs.size > 1
108
+ raise RuntimeError.new("Cannot identify result set directory")
109
+ end
110
+ plan.resultset_dir = dirs.first
111
+
102
112
  PlanLoader.load_plan(plan)
103
113
 
104
114
  plan
@@ -185,7 +195,7 @@ module Jkr
185
195
  @plan
186
196
  end
187
197
 
188
- def use_script(name)
198
+ def use_script(name, use = true)
189
199
  # find script file
190
200
  if name.is_a? Symbol
191
201
  name = name.to_s + ".rb"
@@ -206,12 +216,18 @@ module Jkr
206
216
 
207
217
  if path
208
218
  load path
209
- @plan.used_scripts.push(path)
219
+ if use
220
+ @plan.used_scripts.push(path)
221
+ end
210
222
  else
211
223
  raise RuntimeError.new("Cannot use script: #{name}")
212
224
  end
213
225
  end
214
226
 
227
+ def load_script(name)
228
+ use_script(name, false)
229
+ end
230
+
215
231
  def extend(base_plan_name)
216
232
  base_plan = Plan.create_by_name(self.plan.jkr_env, base_plan_name.to_s,
217
233
  :plan_search_path => @plan.plan_search_path,
@@ -374,7 +390,7 @@ module Jkr
374
390
  {'message'=>message})
375
391
  end
376
392
 
377
- def sh(*args)
393
+ def sh_(*args)
378
394
  puts "sh: #{args.join(' ')}"
379
395
  return system(*args)
380
396
  end
@@ -387,8 +403,12 @@ module Jkr
387
403
  true
388
404
  end
389
405
 
406
+ # for backward compatibility
390
407
  alias :system_ :sh!
391
408
 
409
+ # raise Error on failure by default
410
+ alias :sh :sh!
411
+
392
412
  def su_sh(*args)
393
413
  puts "su_sh: #{args.join(' ')}"
394
414
  su_cmd = File.expand_path("../su_cmd", __FILE__)
@@ -6,6 +6,8 @@ require 'jkr/utils'
6
6
  module Jkr
7
7
  class Trial
8
8
  attr_reader :params
9
+ attr_reader :result_dir
10
+
9
11
  def self.make_trials(resultset_dir, plan)
10
12
  var_combs = [{}]
11
13
  plan.vars.each do |key, vals|
@@ -25,8 +27,7 @@ module Jkr
25
27
  params_list = params_list * plan.routine_nr_run
26
28
 
27
29
  params_list.map do |params|
28
- result_dir = Utils.reserve_next_dir(resultset_dir)
29
- Trial.new(result_dir, plan, params)
30
+ Trial.new(resultset_dir, plan, params)
30
31
  end
31
32
  end
32
33
 
@@ -40,7 +41,7 @@ module Jkr
40
41
 
41
42
  def self.run(env, plan, delete_files_on_error = true)
42
43
  plan_suffix = File.basename(plan.file_path, ".plan")
43
- plan_suffix += "_#{plan.short_desc}" if plan.short_desc
44
+ plan_suffix += "_#{plan.short_desc}" if plan.short_desc && plan.short_desc.size > 0
44
45
  resultset_dir = Utils.reserve_next_dir(env.jkr_result_dir, plan_suffix)
45
46
  plan.resultset_dir = resultset_dir
46
47
  FileUtils.mkdir_p(File.join(resultset_dir, "plan"))
@@ -73,28 +74,71 @@ module Jkr
73
74
  params = plan.params.merge(plan.vars)
74
75
  plan.freeze
75
76
 
77
+ save_info(plan, :start_time => Time.now)
78
+
76
79
  # show estimated execution time if available
77
80
  if plan.exec_time_estimate
78
81
  puts("")
79
82
  puts("== estimated execution time: #{pretty_time(plan.exec_time_estimate.call(plan))} ==")
80
83
  puts("")
81
84
  end
82
-
83
- plan.do_prep()
84
- trials.each do |trial|
85
- trial.run
86
- end
87
- plan.do_cleanup()
88
85
  rescue Exception => err
89
86
  if delete_files_on_error
90
87
  FileUtils.rm_rf(resultset_dir)
91
88
  end
92
89
  raise err
93
90
  end
91
+
92
+ resume(env, plan)
93
+ end
94
+
95
+ def self.resume(env, plan)
96
+ trials = self.make_trials(plan.resultset_dir, plan)
97
+
98
+ save_info(plan, :last_resume_time => Time.now)
99
+
100
+ plan.do_prep()
101
+ trials.each do |trial|
102
+ begin
103
+ trial.run
104
+ rescue Exception => err
105
+ failed_dir = File.expand_path("../_failed_" + File.basename(trial.result_dir),
106
+ trial.result_dir)
107
+ i = 1
108
+ while Dir.exists?(failed_dir)
109
+ failed_dir = File.expand_path("../_failed_" + File.basename(trial.result_dir) + "_#{i}",
110
+ trial.result_dir)
111
+ i += 1
112
+ end
113
+ FileUtils.mv(trial.result_dir, failed_dir)
114
+ save_info(plan, :last_failure_time => Time.now)
115
+
116
+ raise err
117
+ end
118
+ end
119
+ plan.do_cleanup()
120
+
121
+ save_info(plan, :finish_time => Time.now)
122
+ end
123
+
124
+ def self.save_info(plan, data = {})
125
+ info_path = File.expand_path("INFO", plan.resultset_dir)
126
+ unless File.exists?(info_path)
127
+ File.open(info_path, "w") do |f|
128
+ f.puts(JSON.pretty_generate({}))
129
+ end
130
+ end
131
+
132
+ info_data = JSON.load(File.open(info_path))
133
+ info_data = info_data.merge(data)
134
+
135
+ File.open(info_path, "w") do |f|
136
+ f.puts(JSON.pretty_generate(info_data))
137
+ end
94
138
  end
95
139
 
96
- def initialize(result_dir, plan, params)
97
- @result_dir = result_dir
140
+ def initialize(resultset_dir, plan, params)
141
+ @resultset_dir = resultset_dir
98
142
  @plan = plan
99
143
  @params = params
100
144
  end
@@ -102,27 +146,50 @@ module Jkr
102
146
 
103
147
  def run()
104
148
  plan = @plan
105
- File.open("#{@result_dir}/params.json", "w") do |f|
106
- f.puts(@params.to_json)
149
+
150
+ # check duplicate execution
151
+ Dir.glob("#{@resultset_dir}/*").select do |path|
152
+ File.basename(path) =~ /^[0-9]{5}$/
153
+ end.each do |result_dir|
154
+ params = Marshal.load(File.open("#{result_dir}/params.msh"))
155
+
156
+ if params == @params
157
+ # already executed trial. skip.
158
+ return false
159
+ end
107
160
  end
108
161
 
109
- # reset plan.metastore
110
- plan.metastore.clear
162
+ # make result dir for this trial
163
+ @result_dir = Utils.reserve_next_dir(@resultset_dir)
164
+
165
+ Dir.chdir(@result_dir) do
166
+ # save params
167
+ File.open("#{@result_dir}/params.msh", "w") do |f|
168
+ Marshal.dump(@params, f)
169
+ end
170
+ File.open("#{@result_dir}/params.json", "w") do |f|
171
+ f.puts(JSON.pretty_generate(@params))
172
+ end
111
173
 
112
- # define utility functions for plan.routine object
113
- Jkr::TrialUtils.define_routine_utils(@result_dir, @plan, @params)
174
+ # reset plan.metastore
175
+ plan.metastore.clear
114
176
 
115
- @plan.metastore[:trial_start_time] = Time.now
116
- @plan.do_routine(@plan, @params)
117
- @plan.metastore[:trial_end_time] = Time.now
177
+ # define utility functions for plan.routine object
178
+ Jkr::TrialUtils.define_routine_utils(@result_dir, @plan, @params)
118
179
 
119
- Jkr::TrialUtils.undef_routine_utils(@plan)
180
+ @plan.metastore[:vars] = @plan.vars.keys
181
+ @plan.metastore[:trial_start_time] = Time.now
182
+ @plan.do_routine(@plan, @params)
183
+ @plan.metastore[:trial_end_time] = Time.now
120
184
 
121
- # save plan.metastore
122
- Marshal.dump(@plan.metastore,
123
- File.open("#{@result_dir}/metastore.msh", "w"))
124
- File.open("#{@result_dir}/metastore.json", "w") do |f|
125
- f.puts(@plan.metastore.to_json)
185
+ Jkr::TrialUtils.undef_routine_utils(@plan)
186
+
187
+ # save plan.metastore
188
+ Marshal.dump(@plan.metastore,
189
+ File.open("#{@result_dir}/metastore.msh", "w"))
190
+ File.open("#{@result_dir}/metastore.json", "w") do |f|
191
+ f.puts(JSON.pretty_generate(@plan.metastore))
192
+ end
126
193
  end
127
194
  end
128
195
  end
@@ -1,3 +1,3 @@
1
1
  module Jkr
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jkr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuto Hayamizu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-08 00:00:00.000000000 Z
11
+ date: 2016-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -133,7 +133,6 @@ files:
133
133
  - ".gitignore"
134
134
  - ".rspec"
135
135
  - Gemfile
136
- - Gemfile.lock
137
136
  - Guardfile
138
137
  - History.txt
139
138
  - LICENSE.txt
@@ -1,81 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- jkr (0.1.0)
5
- term-ansicolor
6
- thor
7
-
8
- GEM
9
- remote: https://rubygems.org/
10
- specs:
11
- coderay (1.1.1)
12
- diff-lcs (1.2.5)
13
- ffi (1.9.14)
14
- formatador (0.2.5)
15
- guard (2.14.0)
16
- formatador (>= 0.2.4)
17
- listen (>= 2.7, < 4.0)
18
- lumberjack (~> 1.0)
19
- nenv (~> 0.1)
20
- notiffany (~> 0.0)
21
- pry (>= 0.9.12)
22
- shellany (~> 0.0)
23
- thor (>= 0.18.1)
24
- guard-compat (1.2.1)
25
- guard-rspec (4.7.3)
26
- guard (~> 2.1)
27
- guard-compat (~> 1.1)
28
- rspec (>= 2.99.0, < 4.0)
29
- listen (3.1.5)
30
- rb-fsevent (~> 0.9, >= 0.9.4)
31
- rb-inotify (~> 0.9, >= 0.9.7)
32
- ruby_dep (~> 1.2)
33
- lumberjack (1.0.10)
34
- method_source (0.8.2)
35
- nenv (0.3.0)
36
- notiffany (0.1.1)
37
- nenv (~> 0.1)
38
- shellany (~> 0.0)
39
- pry (0.10.4)
40
- coderay (~> 1.1.0)
41
- method_source (~> 0.8.1)
42
- slop (~> 3.4)
43
- rake (11.2.2)
44
- rb-fsevent (0.9.7)
45
- rb-inotify (0.9.7)
46
- ffi (>= 0.5.0)
47
- rspec (3.5.0)
48
- rspec-core (~> 3.5.0)
49
- rspec-expectations (~> 3.5.0)
50
- rspec-mocks (~> 3.5.0)
51
- rspec-core (3.5.2)
52
- rspec-support (~> 3.5.0)
53
- rspec-expectations (3.5.0)
54
- diff-lcs (>= 1.2.0, < 2.0)
55
- rspec-support (~> 3.5.0)
56
- rspec-mocks (3.5.0)
57
- diff-lcs (>= 1.2.0, < 2.0)
58
- rspec-support (~> 3.5.0)
59
- rspec-support (3.5.0)
60
- ruby_dep (1.4.0)
61
- shellany (0.0.1)
62
- slop (3.6.0)
63
- term-ansicolor (1.3.2)
64
- tins (~> 1.0)
65
- thor (0.19.1)
66
- tins (1.12.0)
67
-
68
- PLATFORMS
69
- ruby
70
-
71
- DEPENDENCIES
72
- bundler
73
- guard
74
- guard-rspec
75
- jkr!
76
- pry
77
- rake
78
- rspec
79
-
80
- BUNDLED WITH
81
- 1.11.2