rbbt-util 2.1.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/bin/rbbt_query.rb +63 -0
  2. data/lib/rbbt-util.rb +5 -5
  3. data/lib/rbbt.rb +2 -11
  4. data/lib/rbbt/util/cmd.rb +1 -1
  5. data/lib/rbbt/util/fix_width_table.rb +9 -3
  6. data/lib/rbbt/util/log.rb +23 -7
  7. data/lib/rbbt/util/misc.rb +121 -15
  8. data/lib/rbbt/util/open.rb +14 -4
  9. data/lib/rbbt/util/persistence.rb +52 -21
  10. data/lib/rbbt/util/rake.rb +108 -21
  11. data/lib/rbbt/util/resource.rb +338 -0
  12. data/lib/rbbt/util/simpleDSL.rb +1 -1
  13. data/lib/rbbt/util/simpleopt.rb +1 -1
  14. data/lib/rbbt/util/task.rb +340 -0
  15. data/lib/rbbt/util/tc_hash.rb +19 -2
  16. data/lib/rbbt/util/tsv.rb +15 -10
  17. data/lib/rbbt/util/tsv/accessor.rb +16 -7
  18. data/lib/rbbt/util/tsv/attach.rb +220 -17
  19. data/lib/rbbt/util/tsv/index.rb +6 -1
  20. data/lib/rbbt/util/tsv/manipulate.rb +4 -5
  21. data/lib/rbbt/util/tsv/parse.rb +45 -21
  22. data/lib/rbbt/util/tsv/resource.rb +74 -0
  23. data/lib/rbbt/util/workflow.rb +99 -75
  24. data/test/rbbt/util/test_filecache.rb +2 -2
  25. data/test/rbbt/util/test_misc.rb +7 -2
  26. data/test/rbbt/util/test_persistence.rb +40 -5
  27. data/test/rbbt/util/test_resource.rb +92 -0
  28. data/test/rbbt/util/test_task.rb +118 -0
  29. data/test/rbbt/util/test_tsv.rb +5 -1
  30. data/test/rbbt/util/test_workflow.rb +77 -62
  31. data/test/rbbt/util/tsv/test_attach.rb +95 -7
  32. data/test/rbbt/util/tsv/test_index.rb +0 -1
  33. data/test/rbbt/util/tsv/test_manipulate.rb +20 -0
  34. data/test/rbbt/util/tsv/test_resource.rb +9 -0
  35. data/test/test_helper.rb +10 -0
  36. data/test/test_rbbt.rb +2 -37
  37. metadata +16 -18
  38. data/lib/rbbt/util/data_module.rb +0 -93
  39. data/lib/rbbt/util/path.rb +0 -155
  40. data/lib/rbbt/util/pkg_config.rb +0 -78
  41. data/lib/rbbt/util/pkg_data.rb +0 -119
  42. data/lib/rbbt/util/pkg_software.rb +0 -145
  43. data/test/rbbt/util/test_data_module.rb +0 -50
  44. data/test/rbbt/util/test_path.rb +0 -10
  45. data/test/rbbt/util/test_pkg_data.rb +0 -129
  46. data/test/test_pkg.rb +0 -28
@@ -67,7 +67,7 @@ module SimpleDSL
67
67
  def load_config(method = nil, file = nil, &block)
68
68
  @config = {}
69
69
  if file
70
- raise ConfigFileMissingError.new "File '#{ file }' is missing. Have you installed the config files? (use rbbt_config)." unless File.exists? file
70
+ raise ConfigFileMissingError.new "Config file '#{ file }' is missing" unless File.exists? file
71
71
  parse(method, file)
72
72
  end
73
73
 
@@ -8,7 +8,7 @@ module SOPT
8
8
  opts.split(/:/).each do |opt|
9
9
  short, long = opt.sub(/\*$/,'').split('--').values_at(0,1)
10
10
  i= {
11
- :arg => !opt.match(/\*$/).nil?,
11
+ :arg => !!opt.match(/\*$/),
12
12
  }
13
13
  i[:short] = short unless short.nil? || short.empty?
14
14
  i[:long] = '--' + long unless long.nil? || long.empty?
@@ -0,0 +1,340 @@
1
+ require 'rbbt/util/open'
2
+
3
+ class Task
4
+ class << self
5
+ attr_accessor :basedir
6
+ end
7
+
8
+ @basedir = "."
9
+
10
+ class Job
11
+ attr_accessor :task, :id, :name, :options, :dependencies, :pid, :path, :previous_jobs
12
+
13
+ IDSEP = "_"
14
+
15
+ def self.id2name(job_id)
16
+ job_id.split(IDSEP)
17
+ end
18
+
19
+ def self.load(task, id)
20
+ name, hash = id2name(id)
21
+ self.new task, id, name, nil, nil
22
+ end
23
+
24
+ def initialize(task, id, name, options, dependencies)
25
+ @task = task
26
+ @id =id
27
+ @name = name
28
+ @options = options
29
+ @dependencies = dependencies
30
+
31
+ if @dependencies
32
+ @previous_jobs = Hash[*dependencies.first.collect{|job| job.task.name}.zip(dependencies.first).flatten]
33
+ dependencies.first.collect{|job| @previous_jobs.merge! job.previous_jobs }
34
+ else
35
+ @previous_jobs = []
36
+ end
37
+
38
+ basedir = task.workflow.jobdir unless task.workflow.nil?
39
+ @path = File.join(basedir || Task.basedir, task.name, id)
40
+ end
41
+
42
+ def info_file
43
+ path + '.info'
44
+ end
45
+
46
+ def info
47
+ return {} if not File.exists?(info_file)
48
+ YAML.load(File.open(info_file))
49
+ end
50
+
51
+ def set_info(key, value)
52
+ i = self.info
53
+ new_info = i.merge(key => value)
54
+ Open.write(info_file, new_info.to_yaml)
55
+ end
56
+
57
+ def step(name = nil, message = nil)
58
+ if name.nil?
59
+ info[:step]
60
+ else
61
+ set_info(:step, name)
62
+ set_info(:messages, info[:messages] || [] << message) if not message.nil?
63
+ end
64
+ end
65
+
66
+ def messages
67
+ info[:messages] || []
68
+ end
69
+
70
+ def done?
71
+ [:done, :error, :aborted].include? info[:step]
72
+ end
73
+
74
+ def error?
75
+ step == :error or step == :aborted
76
+ end
77
+
78
+ def arguments
79
+ options.values_at *task.options
80
+ end
81
+
82
+ def block
83
+ task.block
84
+ end
85
+
86
+ def run_dependencies
87
+ jobs, files = dependencies
88
+ jobs.each do |job| job.start unless File.exists? job.path; job.step(:done) end
89
+ files.each do |file| file.produce end
90
+ end
91
+
92
+ def input
93
+ dep = dependencies.flatten.first
94
+ if Job === dep
95
+ dep.load
96
+ else
97
+ dep.read
98
+ end
99
+ end
100
+
101
+ def start
102
+ Log.medium("Starting Job '#{ name }'. Path: '#{ path }'")
103
+ set_info(:start_time, Time.now)
104
+ save_options(options)
105
+
106
+ extend task.scope unless task.scope.nil? or Object == task.scope.class
107
+
108
+ begin
109
+
110
+ if dependencies.flatten.any?
111
+ run_dependencies
112
+ end
113
+
114
+ result = instance_exec *arguments, &block
115
+
116
+
117
+ if not result.nil?
118
+ case task.persistence
119
+ when nil, :string, :tsv, :integer
120
+ Open.write(path, result.to_s)
121
+ when :marshal
122
+ Open.write(path, Marshal.dump(result))
123
+ when :yaml
124
+ Open.write(path, YAML.dump(result))
125
+ end
126
+ end
127
+
128
+ set_info(:end_time, Time.now)
129
+ Log.medium("Finished Job '#{ name }'. Path: '#{ path }'")
130
+ rescue Exception
131
+ step(:error, "#{$!.class}: #{$!.message}")
132
+ raise $!
133
+ end
134
+ end
135
+
136
+ def save_options(options)
137
+ new_options = {}
138
+ options.each do |key, value|
139
+ case
140
+ when TSV === value
141
+ new_options[key] = value.to_s
142
+ else
143
+ new_options[key] = value
144
+ end
145
+ end
146
+ set_info(:options, new_options)
147
+ end
148
+
149
+ def recursive_done?
150
+ previous_jobs.values.inject(true){|acc,j| acc and j.recursive_done?} and done?
151
+ end
152
+
153
+ def run
154
+ return self if recursive_done?
155
+ begin
156
+ step(:started)
157
+ start
158
+ step(:done)
159
+ rescue Exception
160
+ Log.debug $!.message
161
+ Log.debug $!.backtrace * "\n"
162
+ step(:error, "#{$!.class}: #{$!.message}")
163
+ end
164
+ self
165
+ end
166
+
167
+ def fork
168
+ return self if recursive_done?
169
+ @pid = Process.fork do
170
+ begin
171
+ step(:started)
172
+ start
173
+ step(:done)
174
+ rescue Exception
175
+ Log.debug $!.message
176
+ Log.debug $!.backtrace * "\n"
177
+ step(:error, "#{$!.class}: #{$!.message}")
178
+ end
179
+ exit
180
+ end
181
+
182
+ self
183
+ end
184
+
185
+ def join
186
+ if @pid.nil?
187
+ while not done? do
188
+ Log.debug "Waiting: #{info[:step]}"
189
+ sleep 5
190
+ end
191
+ else
192
+ Process.waitpid @pid
193
+ end
194
+
195
+ self
196
+ end
197
+
198
+ def open
199
+ File.open(path)
200
+ end
201
+
202
+ def read
203
+ File.open(path) do |f| f.read end
204
+ end
205
+
206
+ def load
207
+ case task.persistence
208
+ when :float
209
+ Open.read(path).to_f
210
+ when :integer
211
+ Open.read(path).to_i
212
+ when :string
213
+ Open.read(path)
214
+ when :tsv
215
+ TSV.new(path)
216
+ when :marshal
217
+ Marshal.load(Open.read(path))
218
+ when :yaml
219
+ YAML.load(Open.read(path))
220
+ end
221
+ end
222
+
223
+ def clean
224
+ FileUtils.rm path if File.exists? path
225
+ FileUtils.rm info_file if File.exists? info_file
226
+ end
227
+
228
+ def recursive_clean
229
+ dependencies.first.each do |job| job.recursive_clean end
230
+ clean
231
+ end
232
+ end # END Job
233
+
234
+ def load(job_id)
235
+ Job.load(self, job_id)
236
+ end
237
+
238
+ def job_options(run_options = nil)
239
+ return {} if options.nil?
240
+
241
+ job_options = {}
242
+ options.each do |option|
243
+ job_options[option] = Misc.process_options run_options, option
244
+ end
245
+
246
+ job_options
247
+ end
248
+
249
+ def job_id(name, job_options)
250
+ if job_options.any?
251
+ name.to_s + "_" + Misc.hash2md5(job_options)
252
+ else
253
+ name.to_s
254
+ end
255
+ end
256
+
257
+ attr_accessor :name, :persistence, :options, :option_descriptions, :option_types, :option_defaults, :workflow, :dependencies, :scope, :block
258
+ def initialize(name, persistence = nil, options = nil, option_descriptions = nil, option_types = nil, option_defaults = nil, workflow = nil, dependencies = nil, scope = nil, &block)
259
+ dependencies = [dependencies] unless dependencies.nil? or Array === dependencies
260
+ @name = name.to_s
261
+
262
+ @persistence = persistence || :marshal
263
+
264
+ @options = Array === options ? options : [options] unless options.nil?
265
+
266
+ @option_defaults = option_defaults
267
+ @option_descriptions = option_descriptions
268
+ @option_types = option_types
269
+ @workflow = workflow
270
+ @dependencies = dependencies || []
271
+ @scope = scope
272
+
273
+ @block = block unless not block_given?
274
+ end
275
+
276
+ def recursive_options
277
+ all_options = []
278
+ option_descriptions = {}
279
+ option_types = {}
280
+ option_defaults = {}
281
+
282
+ all_options.concat self.options if self.options
283
+ option_descriptions.merge! self.option_descriptions if self.option_descriptions
284
+ option_types.merge! self.option_types if self.option_types
285
+ option_defaults.merge! self.option_defaults if self.option_defaults
286
+
287
+ self.dependencies.each do |task|
288
+ task = case
289
+ when Symbol === task
290
+ workflow.tasks[task]
291
+ when Task === task
292
+ task
293
+ else
294
+ next
295
+ end
296
+
297
+ n_all_options, n_option_descriptions, n_option_types, n_option_defaults = task.recursive_options
298
+
299
+ all_options.concat n_all_options if n_all_options
300
+ option_descriptions.merge! n_option_descriptions if n_option_descriptions
301
+ option_types.merge! n_option_types if n_option_types
302
+ option_defaults.merge! n_option_defaults if n_option_defaults
303
+ end
304
+
305
+ [all_options, option_descriptions, option_types, option_defaults]
306
+ end
307
+
308
+ def job_dependencies(jobname, run_options = {})
309
+ jobs = []
310
+ files = []
311
+ dependencies.each do |dependency|
312
+ case
313
+ when Task === dependency
314
+ jobs << dependency.job(jobname, run_options)
315
+ when Symbol === dependency
316
+ raise "No workflow defined, yet dependencies include Symbols (other tasks)" if workflow.nil?
317
+ jobs << workflow.tasks[dependency].job(jobname, run_options)
318
+ else
319
+ files << dependency
320
+ end
321
+ end
322
+ [jobs, files]
323
+ end
324
+
325
+ def job(jobname, run_options = {})
326
+
327
+ job_id = self.job_id jobname, run_options
328
+
329
+ job_options = self.job_options run_options
330
+
331
+ dependencies = self.job_dependencies(jobname, run_options)
332
+
333
+ Job.new(self, job_id, jobname, job_options, dependencies)
334
+ end
335
+
336
+ def run(*args)
337
+ job(*args).start
338
+ end
339
+
340
+ end
@@ -5,6 +5,17 @@ class TCHash < TokyoCabinet::HDB
5
5
  class OpenError < StandardError;end
6
6
  class KeyFormatError < StandardError;end
7
7
 
8
+ class IntegerSerializer
9
+ def self.dump(i); [i].pack("l"); end
10
+ def self.load(str); str.unpack("l").first; end
11
+ end
12
+
13
+ class IntegerArraySerializer
14
+ def self.dump(a); a.pack("l*"); end
15
+ def self.load(str); str.unpack("l*"); end
16
+ end
17
+
18
+
8
19
  class StringSerializer
9
20
  def self.dump(str); str.to_s; end
10
21
  def self.load(str); str; end
@@ -31,7 +42,7 @@ class TCHash < TokyoCabinet::HDB
31
42
  end
32
43
 
33
44
 
34
- ALIAS = {:marshal => Marshal, nil => Marshal, :single => StringSerializer, :list => StringArraySerializer, :double => StringDoubleArraySerializer}
45
+ ALIAS = {:integer => IntegerSerializer, :integer_array => IntegerArraySerializer, :marshal => Marshal, nil => Marshal, :single => StringSerializer, :list => StringArraySerializer, :double => StringDoubleArraySerializer}
35
46
 
36
47
  CONNECTIONS = {}
37
48
 
@@ -179,7 +190,13 @@ class TCHash < TokyoCabinet::HDB
179
190
 
180
191
  def collect
181
192
  res = []
182
- self.each{|k, v| res << yield(k,v)}
193
+ self.each{|k, v|
194
+ if block_given?
195
+ res << yield(k,v)
196
+ else
197
+ res << [k,v]
198
+ end
199
+ }
183
200
  res
184
201
  end
185
202
 
@@ -1,6 +1,6 @@
1
+ require 'rbbt/util/resource'
1
2
  require 'rbbt/util/misc'
2
3
  require 'rbbt/util/open'
3
- require 'rbbt/util/path'
4
4
  require 'rbbt/util/tc_hash'
5
5
  require 'rbbt/util/tmpfile'
6
6
  require 'rbbt/util/log'
@@ -13,6 +13,7 @@ require 'rbbt/util/tsv/accessor'
13
13
  require 'rbbt/util/tsv/manipulate'
14
14
  require 'rbbt/util/tsv/index'
15
15
  require 'rbbt/util/tsv/attach'
16
+ require 'rbbt/util/tsv/resource'
16
17
  class TSV
17
18
 
18
19
  def self.headers(file, options = {})
@@ -65,7 +66,7 @@ class TSV
65
66
 
66
67
  @filename = Misc.process_options options, :filename
67
68
  @filename ||= case
68
- when Path === file
69
+ when Resource::Path === file
69
70
  file
70
71
  when (String === file and File.exists? file)
71
72
  File.expand_path file
@@ -89,13 +90,18 @@ class TSV
89
90
  # TSV: Duplicate
90
91
  case
91
92
  when block_given?
92
- @data, extra = Persistence.persist(@filename, :TSV, :tsv_extra, options.merge(:force_array => true)) do |filename, options| yield filename, options end
93
+ @data, extra = Persistence.persist(file, :TSV, :tsv_extra, options.merge(:force_array => true)) do |file, options, filename| yield file, options, filename end
93
94
  extra.each do |key, values|
94
95
  self.send("#{ key }=".to_sym, values) if self.respond_to? "#{ key }=".to_sym
95
96
  end if not extra.nil?
96
97
 
97
98
  else
99
+
98
100
  case
101
+ when Array === file
102
+ @data = Hash[file.collect{|v|
103
+ [v,[]]
104
+ }]
99
105
  when Hash === file
100
106
  @data = file
101
107
  when TSV === file
@@ -108,12 +114,12 @@ class TSV
108
114
  end
109
115
  end
110
116
  else
111
- @data, extra = Persistence.persist(@filename, :TSV, :tsv_extra, options) do |file, options, filename|
117
+ @data, extra = Persistence.persist(file, :TSV, :tsv_extra, options) do |file, options, filename|
112
118
  data, extra = nil
113
119
 
114
120
  case
115
121
  ## Parse source
116
- when (String === file and file.respond_to? :open)
122
+ when Resource::Path === file #(String === file and file.respond_to? :open)
117
123
  data, extra = TSV.parse(file.open(:grep => options[:grep]) , options)
118
124
  extra[:namespace] ||= file.namespace
119
125
  extra[:datadir] ||= file.datadir
@@ -123,14 +129,13 @@ class TSV
123
129
  Open.open(file, :grep => options[:grep]) do |f|
124
130
  data, extra = TSV.parse(f, options)
125
131
  end
126
- #extra[:namespace] = File.basename(File.dirname(filename))
127
- #extra.delete :namespace if extra[:namespace].empty? or extra[:namespace] == "."
128
132
  when File === file
133
+ path = file.path
134
+ file = Open.grep(file, options[:grep]) if options[:grep]
135
+ data, extra = TSV.parse(file, options)
136
+ when IO === file
129
137
  file = Open.grep(file, options[:grep]) if options[:grep]
130
138
  data, extra = TSV.parse(file, options)
131
- extra[:namespace] = File.basename(File.dirname(file.filename))
132
- extra.delete :namespace if extra[:namespace].empty? or extra[:namespace] == "."
133
- ## Encapsulate Hash or TSV
134
139
  when block_given?
135
140
  data
136
141
  else