scout-gear 10.7.0 → 10.7.2

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +8 -1
  3. data/VERSION +1 -1
  4. data/lib/scout/association/index.rb +1 -1
  5. data/lib/scout/association.rb +21 -5
  6. data/lib/scout/entity/format.rb +9 -4
  7. data/lib/scout/entity/identifiers.rb +2 -2
  8. data/lib/scout/entity/named_array.rb +13 -0
  9. data/lib/scout/entity/property.rb +2 -1
  10. data/lib/scout/entity.rb +9 -4
  11. data/lib/scout/persist/tsv/adapter/base.rb +13 -1
  12. data/lib/scout/persist/tsv.rb +2 -1
  13. data/lib/scout/tsv/attach.rb +10 -2
  14. data/lib/scout/tsv/change_id.rb +3 -0
  15. data/lib/scout/tsv/dumper.rb +34 -30
  16. data/lib/scout/tsv/open.rb +1 -0
  17. data/lib/scout/tsv/parser.rb +22 -10
  18. data/lib/scout/tsv/path.rb +8 -0
  19. data/lib/scout/tsv/stream.rb +15 -8
  20. data/lib/scout/tsv/traverse.rb +12 -2
  21. data/lib/scout/tsv/util/process.rb +4 -1
  22. data/lib/scout/tsv/util/select.rb +8 -2
  23. data/lib/scout/tsv/util/sort.rb +23 -15
  24. data/lib/scout/tsv/util.rb +11 -2
  25. data/lib/scout/tsv.rb +23 -11
  26. data/lib/scout/workflow/definition.rb +24 -9
  27. data/lib/scout/workflow/deployment/orchestrator.rb +10 -7
  28. data/lib/scout/workflow/exceptions.rb +1 -0
  29. data/lib/scout/workflow/path.rb +40 -0
  30. data/lib/scout/workflow/step/dependencies.rb +36 -12
  31. data/lib/scout/workflow/step/file.rb +2 -1
  32. data/lib/scout/workflow/step/info.rb +20 -4
  33. data/lib/scout/workflow/step/load.rb +5 -3
  34. data/lib/scout/workflow/step/progress.rb +6 -0
  35. data/lib/scout/workflow/step/provenance.rb +1 -1
  36. data/lib/scout/workflow/step/status.rb +11 -4
  37. data/lib/scout/workflow/step.rb +33 -12
  38. data/lib/scout/workflow/task/dependencies.rb +33 -24
  39. data/lib/scout/workflow/task/inputs.rb +42 -12
  40. data/lib/scout/workflow/task.rb +22 -11
  41. data/lib/scout/workflow/usage.rb +3 -3
  42. data/lib/scout/workflow.rb +3 -0
  43. data/scout-gear.gemspec +13 -4
  44. data/scout_commands/db/query +83 -0
  45. data/scout_commands/db/register +43 -0
  46. data/scout_commands/db/show +47 -0
  47. data/test/scout/entity/test_named_array.rb +21 -0
  48. data/test/scout/persist/test_tsv.rb +20 -0
  49. data/test/scout/persist/tsv/adapter/test_base.rb +20 -0
  50. data/test/scout/test_tsv.rb +40 -0
  51. data/test/scout/tsv/test_dumper.rb +24 -0
  52. data/test/scout/tsv/test_path.rb +24 -0
  53. data/test/scout/tsv/test_stream.rb +93 -0
  54. data/test/scout/tsv/test_traverse.rb +99 -0
  55. data/test/scout/tsv/test_util.rb +2 -0
  56. data/test/scout/tsv/util/test_select.rb +22 -0
  57. data/test/scout/tsv/util/test_sort.rb +24 -0
  58. data/test/scout/workflow/step/test_dependencies.rb +26 -0
  59. data/test/scout/workflow/step/test_info.rb +35 -0
  60. data/test/scout/workflow/task/test_dependencies.rb +67 -1
  61. data/test/scout/workflow/task/test_inputs.rb +24 -7
  62. data/test/scout/workflow/test_definition.rb +31 -0
  63. data/test/scout/workflow/test_path.rb +9 -0
  64. data/test/scout/workflow/test_task.rb +36 -0
  65. data/test/scout/workflow/test_usage.rb +0 -1
  66. metadata +12 -3
@@ -138,18 +138,32 @@ class Step
138
138
 
139
139
  attr_reader :result
140
140
  def run(stream = false)
141
+ case stream
142
+ when TrueClass, :stream
143
+ no_load = :stream
144
+ when :no_load
145
+ no_load = true
146
+ else
147
+ no_load = false
148
+ end
149
+
150
+ if done?
151
+ if no_load
152
+ if no_load == :stream
153
+ return self.stream
154
+ else
155
+ return self.path
156
+ end
157
+ else
158
+ return @result || self.load
159
+ end
160
+ end
161
+
162
+
141
163
  return @result || self.load if done?
142
164
  prepare_dependencies
143
165
  begin
144
166
 
145
- case stream
146
- when TrueClass, :stream
147
- no_load = :stream
148
- when :no_load
149
- no_load = true
150
- else
151
- no_load = false
152
- end
153
167
 
154
168
  @result = Persist.persist(name, type, :path => path, :tee_copies => tee_copies, no_load: no_load) do
155
169
  input_names = (task.respond_to?(:inputs) && task.inputs) ? task.inputs.collect{|name,_| name} : []
@@ -206,6 +220,7 @@ class Step
206
220
  end
207
221
 
208
222
  @result.abort_callback = proc do |exception|
223
+ Open.rm self.path
209
224
  if exception.nil? || Aborted === exception || Interrupt === exception
210
225
  merge_info :status => :aborted, :end => Time.now
211
226
  else
@@ -240,6 +255,7 @@ class Step
240
255
  run(noload)
241
256
  end
242
257
  join
258
+ exit! 0
243
259
  end
244
260
  Process.detach pid
245
261
  grace
@@ -350,6 +366,10 @@ class Step
350
366
 
351
367
  def step(task_name)
352
368
  task_name = task_name.to_sym
369
+ dependencies.each do |dep|
370
+ return dep if dep.task_name && dep.task_name.to_sym == task_name
371
+ return dep if dep.overriden_task && dep.overriden_task.to_sym == task_name
372
+ end
353
373
  dependencies.each do |dep|
354
374
  return dep if dep.task_name && dep.task_name.to_sym == task_name
355
375
  return dep if dep.overriden_task && dep.overriden_task.to_sym == task_name
@@ -359,12 +379,12 @@ class Step
359
379
  nil
360
380
  end
361
381
 
362
- def short_path
363
- Resource.identify @path
382
+ def identify_path
383
+ Resource.identify path
364
384
  end
365
385
 
366
386
  def digest_str
367
- "Step: " + short_path
387
+ "Step: " + identify_path
368
388
  end
369
389
 
370
390
  def fingerprint
@@ -372,7 +392,8 @@ class Step
372
392
  end
373
393
 
374
394
  def task_signature
375
- [workflow.to_s, task_name] * "#"
395
+ workflow_name = String === workflow ? workflow : workflow.name
396
+ [workflow_name, task_name] * "#"
376
397
  end
377
398
 
378
399
  def alias?
@@ -9,22 +9,33 @@ module Task
9
9
  load_dep = proc do |id, workflow, task, step_options, definition_options, dependencies|
10
10
  task = step_options.delete(:task) if step_options.include?(:task)
11
11
  workflow = step_options.delete(:workflow) if step_options.include?(:workflow)
12
- id = step_options.delete(:id) if step_options.include?(:id)
13
- id = step_options.delete(:jobname) if step_options.include?(:jobname)
12
+
13
+ step_id = id
14
+ step_id = step_options.delete(:jobname) if step_options.include?(:jobname)
15
+ step_id = nil if step_id == Task::DEFAULT_NAME
14
16
 
15
17
  step_inputs = step_options.include?(:inputs)? step_options.delete(:inputs) : step_options
16
- step_inputs = IndiferentHash.add_defaults step_inputs, definition_options
18
+ step_inputs = IndiferentHash.add_defaults step_inputs.dup, definition_options
17
19
 
18
20
  resolved_inputs = {}
19
21
  step_inputs.each do |k,v|
20
22
  if Symbol === v
21
23
  input_dep = dependencies.select{|d| d.task_name == v }.first
22
- resolved_inputs[k] = input_dep || provided_inputs[v] || step_inputs[v] || v
24
+ resolved_inputs[k] = if input_dep
25
+ input_dep
26
+ elsif provided_inputs.include?(v) && self.inputs.collect(&:first).include?(v)
27
+ provided_inputs[v]
28
+ elsif step_inputs.include?(v) && self.inputs.collect(&:first).include?(v)
29
+ step_inputs[v]
30
+ else
31
+ v
32
+ end
23
33
  else
24
34
  resolved_inputs[k] = v
25
35
  end
26
36
  end
27
- job = workflow.job(task, id, resolved_inputs)
37
+
38
+ job = workflow.job(task, step_id, resolved_inputs)
28
39
  compute_options = definition_options[:compute] || []
29
40
  compute_options = [compute_options] unless Array === compute_options
30
41
  compute_options << :canfail if definition_options[:canfail]
@@ -33,26 +44,25 @@ module Task
33
44
  compute[job.path] = compute_options if compute_options.any?
34
45
 
35
46
  job.overriden = false if definition_options[:not_overriden]
47
+ job.compute = job.compute.nil? ? compute : job.compute.merge(compute)
36
48
 
37
49
  [job, step_inputs]
38
50
  end
39
51
 
40
52
  # Helper function
41
- find_dep_non_default_inputs = proc do |dep,definition_options,step_inputs={}|
53
+ filter_dep_non_default_inputs = proc do |dep,definition_options|
42
54
  dep_non_default_inputs = dep.non_default_inputs
43
- dep_non_default_inputs.select do |name|
44
- step_inputs.include?(name)
45
- end
46
55
  dep_non_default_inputs.reject! do |name|
47
- definition_options.include?(name) &&
48
- (definition_options[name] != :placeholder || definition_options[name] != dep.inputs[name])
56
+ definition_options.include?(name)
49
57
  end
50
58
 
51
59
  dep_non_default_inputs
52
60
  end
53
61
 
54
62
  deps.each do |workflow,task,definition_options,block=nil|
55
- definition_options[:id] = definition_options.delete(:jobname) if definition_options.include?(:jobname)
63
+ definition_options = definition_options.nil? ? {} : definition_options.dup
64
+
65
+ dep_id = definition_options.include?(:jobname) ? definition_options.delete(:jobname) : id
56
66
 
57
67
  if provided_inputs.include?(overriden = [workflow.name, task] * "#")
58
68
  dep = provided_inputs[overriden]
@@ -66,51 +76,50 @@ module Task
66
76
  next
67
77
  end
68
78
 
69
- definition_options ||= {}
70
79
 
71
80
  if block
72
- fixed_provided_inputs = self.assign_inputs(provided_inputs).first.to_hash
73
- self.inputs.each do |name,type,desc,value|
81
+ fixed_provided_inputs = self.assign_inputs(provided_inputs, dep_id).first.to_hash
82
+ self.inputs.each do |name,type,desc,value,options|
74
83
  fixed_provided_inputs[name] = value unless fixed_provided_inputs.include?(name)
75
84
  end
76
85
  fixed_provided_inputs = IndiferentHash.add_defaults fixed_provided_inputs, provided_inputs
77
86
  block_options = IndiferentHash.add_defaults definition_options.dup, fixed_provided_inputs
78
87
 
79
- res = block.call id, block_options, dependencies
88
+ res = block.call dep_id, block_options, dependencies
80
89
 
81
90
  case res
82
91
  when Step
83
92
  dep = res
84
93
  dependencies << dep
85
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options)
94
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
86
95
  non_default_inputs.concat(dep_non_default_inputs)
87
96
  when Hash
88
97
  step_options = block_options.merge(res)
89
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, block_options, dependencies)
98
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options.dup, block_options, dependencies)
90
99
  dependencies << dep
91
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
100
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
92
101
  non_default_inputs.concat(dep_non_default_inputs)
93
102
  when Array
94
103
  res.each do |_res|
95
104
  if Hash === _res
96
105
  step_options = block_options.merge(_res)
97
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, block_options, dependencies)
106
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options.dup, block_options, dependencies)
98
107
  dependencies << dep
99
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
108
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
100
109
  non_default_inputs.concat(dep_non_default_inputs)
101
110
  else
102
111
  dep = _res
103
112
  dependencies << dep
104
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options)
113
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
105
114
  non_default_inputs.concat(dep_non_default_inputs)
106
115
  end
107
116
  end
108
117
  end
109
118
  else
110
119
  step_options = IndiferentHash.add_defaults definition_options.dup, provided_inputs
111
- dep, step_inputs = load_dep.call(id, workflow, task, step_options, definition_options, dependencies)
120
+ dep, step_inputs = load_dep.call(dep_id, workflow, task, step_options, definition_options, dependencies)
112
121
  dependencies << dep
113
- dep_non_default_inputs = find_dep_non_default_inputs.call(dep, definition_options, step_inputs)
122
+ dep_non_default_inputs = filter_dep_non_default_inputs.call(dep, definition_options)
114
123
  non_default_inputs.concat(dep_non_default_inputs)
115
124
  end
116
125
  end
@@ -3,7 +3,7 @@ module Task
3
3
  def self.format_input(value, type, options = {})
4
4
  return value if IO === value || StringIO === value || Step === value
5
5
 
6
- if String === value && ! [:path, :file, :folder, :binary, :tsv].include?(type) && ! (options && (options[:noload] || options[:stream] || options[:nofile]))
6
+ if String === value && ! [:path, :file, :folder, :binary, :tsv].include?(type) && ! (options && (options[:noload] || options[:stream] || options[:nofile] || options[:asfile]))
7
7
  if Open.exists?(value) && ! Open.directory?(value)
8
8
  Persist.load(value, type)
9
9
  else
@@ -35,11 +35,13 @@ module Task
35
35
  input_array = []
36
36
  input_names = []
37
37
  non_default_inputs = []
38
+ jobname_input = nil
38
39
  self.inputs.each_with_index do |p,i|
39
40
  name, type, desc, value, options = p
40
41
  input_names << name
41
42
  provided = Hash === provided_inputs ? provided_inputs[name] : provided_inputs[i]
42
43
  provided = Task.format_input(provided, type, options || {})
44
+
43
45
  if provided == value
44
46
  same_as_default = true
45
47
  elsif String === provided && Symbol === value && provided == value.to_s
@@ -49,25 +51,39 @@ module Task
49
51
  else
50
52
  same_as_default = false
51
53
  end
52
- if ! provided.nil? && ! same_as_default
53
- non_default_inputs << name.to_sym
54
- input_array << provided
55
- elsif options && options[:jobname]
56
- input_array << id
57
- else
58
- input_array << value
54
+
55
+ if options && options[:jobname] && id == provided
56
+ same_as_jobname = true
59
57
  end
58
+
59
+ jobname_input = name if same_as_jobname
60
+
61
+ final = if ! provided.nil? && ! same_as_default && ! same_as_jobname
62
+ non_default_inputs << name.to_sym
63
+ provided
64
+ elsif options && options[:jobname] && id
65
+ non_default_inputs << name.to_sym
66
+ provided || id
67
+ else
68
+ value
69
+ end
70
+
71
+ final = Path.setup(final.dup) if String === final && ! (Path === final) && (type == :file || type == :path || (options && options[:asfile]))
72
+
73
+ final = final.find if (Path === final) && (type == :file)
74
+
75
+ input_array << final
60
76
  end
61
77
 
62
78
  NamedArray.setup(input_array, input_names)
63
79
 
64
- [input_array, non_default_inputs]
80
+ [input_array, non_default_inputs, jobname_input]
65
81
  end
66
82
 
67
83
  def process_inputs(provided_inputs = {}, id = nil)
68
- input_array, non_default_inputs = assign_inputs provided_inputs, id
84
+ input_array, non_default_inputs, jobname_input = assign_inputs provided_inputs, id
69
85
  digest_str = Misc.digest_str(input_array)
70
- [input_array, non_default_inputs, digest_str]
86
+ [input_array, non_default_inputs, digest_str, jobname_input]
71
87
  end
72
88
 
73
89
  def self.save_file_input(orig_file, directory)
@@ -91,6 +107,8 @@ module Task
91
107
  if Path.is_filename?(value)
92
108
  if type == :path
93
109
  Open.write(input_file + ".as_path", value)
110
+ elsif Path.step_file?(value)
111
+ Open.write(input_file + ".as_path", value)
94
112
  else
95
113
  relative_file = save_file_input(value, directory)
96
114
  Open.write(input_file + ".as_file", relative_file)
@@ -137,7 +155,7 @@ module Task
137
155
  elsif filename.end_with?('.as_path')
138
156
  value = Open.read(filename).strip
139
157
  Path.setup value
140
- elsif (options && (options[:noload] || options[:stream] || options[:nofile]))
158
+ elsif (options && (options[:noload] || options[:stream] || options[:nofile] || options[:asfile]))
141
159
  filename
142
160
  else
143
161
  Persist.load(filename, type)
@@ -148,12 +166,24 @@ module Task
148
166
  end
149
167
 
150
168
  def load_inputs(directory)
169
+ if Open.exists?(directory) && ! Open.directory?(directory)
170
+ TmpFile.with_file do |tmp_directory|
171
+ Misc.in_dir tmp_directory do
172
+ CMD.cmd("tar xvfz '#{directory}'")
173
+ end
174
+ return load_inputs(tmp_directory)
175
+ end
176
+ end
177
+
151
178
  inputs = IndiferentHash.setup({})
179
+ seen = []
152
180
  self.recursive_inputs.each do |p|
153
181
  name, type, desc, value, options = p
182
+ next if seen.include?(name)
154
183
  filename = File.join(directory, name.to_s)
155
184
  value = Task.load_input_from_file(filename, type, options)
156
185
  inputs[name] = value unless value.nil?
186
+ seen << name
157
187
  end
158
188
 
159
189
  Dir.glob(File.join(directory, "*#*")).each do |file|
@@ -31,19 +31,29 @@ module Task
31
31
  end
32
32
 
33
33
  def job(id = nil, provided_inputs = nil)
34
- Persist.memory("Task job", other_options: {task: self, id: id, provided_inputs: provided_inputs}) do
34
+
35
+ if Hash === provided_inputs
36
+ memory_inputs = provided_inputs.values_at *self.recursive_inputs.collect{|t| t.first }.uniq
37
+ memory_inputs += provided_inputs.select{|k,v| k.to_s.include?("#") }.collect{|p| p * "=" }
38
+ memory_inputs << provided_inputs[:load_inputs]
39
+ else
40
+ memory_inputs = provided_inputs
41
+ end
42
+
43
+ Persist.memory("Task job #{self.name} #{id}", other_options: {task: self, id: id, provided_inputs: memory_inputs}) do
35
44
  provided_inputs, id = id, nil if (provided_inputs.nil? || provided_inputs.empty?) && (Hash === id || Array === id)
36
45
  provided_inputs = {} if provided_inputs.nil?
37
46
  IndiferentHash.setup(provided_inputs)
38
47
 
39
- if id.nil?
40
- inputs.each do |name,type,desc,default,input_options|
41
- next unless input_options && input_options[:jobname]
42
- id = provided_inputs[name] || default
43
- end
44
- id = DEFAULT_NAME if id.nil?
48
+ jobname_input = nil
49
+ inputs.each do |name,type,desc,default,input_options|
50
+ next unless input_options && input_options[:jobname]
51
+ jobname_input = name
45
52
  end
46
53
 
54
+ id = provided_inputs[jobname_input] if jobname_input && id.nil?
55
+ #id = provided_inputs[:id] if provided_inputs.include?(:id)
56
+
47
57
  missing_inputs = []
48
58
  self.inputs.each do |input,type,desc,val,options|
49
59
  next unless options && options[:required]
@@ -65,11 +75,13 @@ module Task
65
75
  compute = {}
66
76
  dependencies = dependencies(id, provided_inputs, non_default_inputs, compute)
67
77
 
68
- #non_default_inputs.concat provided_inputs.keys.select{|k| String === k && k.include?("#") } if Hash === provided_inputs
69
-
70
78
  non_default_inputs.uniq!
71
79
 
72
- if non_default_inputs.any?
80
+ non_default_inputs.delete_if{|k| k.to_s.include? "#" } unless dependencies.select{|d| d.overriden? }.any?
81
+
82
+ id = DEFAULT_NAME if id.nil?
83
+
84
+ if non_default_inputs.any? && !(non_default_inputs == [jobname_input] && provided_inputs[jobname_input] == id)
73
85
  hash = Misc.digest(:inputs => input_digest_str, :dependencies => dependencies)
74
86
  name = [id, hash] * "_"
75
87
  else
@@ -92,7 +104,6 @@ module Task
92
104
  end
93
105
  end
94
106
 
95
-
96
107
  path = directory[name]
97
108
 
98
109
  path = path.set_extension(extension) if extension
@@ -138,7 +138,7 @@ module Workflow
138
138
 
139
139
  dep_tree = {}
140
140
  task = self.tasks[task_name]
141
- raise "TaskNotFound: #{task_name}" if task.nil?
141
+ raise TaskNotFound, "Task #{task_name} in #{self.to_s}" if task.nil?
142
142
  task.deps.each do |workflow, task, options|
143
143
  next if seen.include? dep
144
144
  seen << [workflow, task, options.merge(seen_options)]
@@ -162,7 +162,7 @@ module Workflow
162
162
 
163
163
  def _prov_tasks(tree)
164
164
  tasks = []
165
- heap = [tree]
165
+ heap = tree.values
166
166
  while heap.any?
167
167
  t = heap.pop
168
168
  t.each do |k,v|
@@ -271,7 +271,7 @@ module Workflow
271
271
  description = description.split("\n\n").first
272
272
 
273
273
  next if abridge && ! final.include?(name)
274
- str.puts Misc.format_definition_list_item(name.to_s, description, nil, nil, :yellow)
274
+ str.puts Misc.format_definition_list_item(name.to_s, description, nil, nil, color: :yellow)
275
275
 
276
276
  prov_string = prov_string(dep_tree(name))
277
277
  str.puts Misc.format_paragraph Log.color(:blue, "->" + prov_string) if prov_string && ! prov_string.empty?
@@ -5,6 +5,8 @@ require_relative 'workflow/step'
5
5
  require_relative 'workflow/documentation'
6
6
  require_relative 'workflow/usage'
7
7
  require_relative 'workflow/deployment'
8
+ require_relative 'workflow/exceptions'
9
+ require_relative 'workflow/path'
8
10
 
9
11
  require 'scout/resource'
10
12
  require 'scout/resource/scout'
@@ -153,6 +155,7 @@ module Workflow
153
155
 
154
156
  def job(name, *args)
155
157
  task = tasks[name]
158
+ raise TaskNotFound, "Task #{name} in #{self.to_s}" if task.nil?
156
159
  step = task.job(*args)
157
160
  step.extend step_module
158
161
  step
data/scout-gear.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: scout-gear 10.7.0 ruby lib
5
+ # stub: scout-gear 10.7.2 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "scout-gear".freeze
9
- s.version = "10.7.0".freeze
9
+ s.version = "10.7.2".freeze
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Miguel Vazquez".freeze]
14
- s.date = "2024-06-05"
14
+ s.date = "2024-12-10"
15
15
  s.description = "Temporary files, logs, path, resources, persistence, workflows, TSV, etc.".freeze
16
16
  s.email = "mikisvaz@gmail.com".freeze
17
17
  s.executables = ["scout".freeze]
@@ -41,6 +41,7 @@ Gem::Specification.new do |s|
41
41
  "lib/scout/entity.rb",
42
42
  "lib/scout/entity/format.rb",
43
43
  "lib/scout/entity/identifiers.rb",
44
+ "lib/scout/entity/named_array.rb",
44
45
  "lib/scout/entity/object.rb",
45
46
  "lib/scout/entity/property.rb",
46
47
  "lib/scout/offsite.rb",
@@ -97,6 +98,8 @@ Gem::Specification.new do |s|
97
98
  "lib/scout/workflow/deployment/orchestrator.rb",
98
99
  "lib/scout/workflow/deployment/trace.rb",
99
100
  "lib/scout/workflow/documentation.rb",
101
+ "lib/scout/workflow/exceptions.rb",
102
+ "lib/scout/workflow/path.rb",
100
103
  "lib/scout/workflow/step.rb",
101
104
  "lib/scout/workflow/step/archive.rb",
102
105
  "lib/scout/workflow/step/children.rb",
@@ -119,6 +122,9 @@ Gem::Specification.new do |s|
119
122
  "scout_commands/alias",
120
123
  "scout_commands/batch/clean",
121
124
  "scout_commands/batch/list",
125
+ "scout_commands/db/query",
126
+ "scout_commands/db/register",
127
+ "scout_commands/db/show",
122
128
  "scout_commands/doc",
123
129
  "scout_commands/find",
124
130
  "scout_commands/glob",
@@ -149,6 +155,7 @@ Gem::Specification.new do |s|
149
155
  "test/scout/association/test_item.rb",
150
156
  "test/scout/entity/test_format.rb",
151
157
  "test/scout/entity/test_identifiers.rb",
158
+ "test/scout/entity/test_named_array.rb",
152
159
  "test/scout/entity/test_object.rb",
153
160
  "test/scout/entity/test_property.rb",
154
161
  "test/scout/offsite/test_ssh.rb",
@@ -186,6 +193,7 @@ Gem::Specification.new do |s|
186
193
  "test/scout/tsv/test_index.rb",
187
194
  "test/scout/tsv/test_open.rb",
188
195
  "test/scout/tsv/test_parser.rb",
196
+ "test/scout/tsv/test_path.rb",
189
197
  "test/scout/tsv/test_stream.rb",
190
198
  "test/scout/tsv/test_transformer.rb",
191
199
  "test/scout/tsv/test_traverse.rb",
@@ -212,6 +220,7 @@ Gem::Specification.new do |s|
212
220
  "test/scout/workflow/task/test_inputs.rb",
213
221
  "test/scout/workflow/test_definition.rb",
214
222
  "test/scout/workflow/test_documentation.rb",
223
+ "test/scout/workflow/test_path.rb",
215
224
  "test/scout/workflow/test_step.rb",
216
225
  "test/scout/workflow/test_task.rb",
217
226
  "test/scout/workflow/test_usage.rb",
@@ -222,7 +231,7 @@ Gem::Specification.new do |s|
222
231
  ]
223
232
  s.homepage = "http://github.com/mikisvaz/scout-gear".freeze
224
233
  s.licenses = ["MIT".freeze]
225
- s.rubygems_version = "3.5.10".freeze
234
+ s.rubygems_version = "3.5.23".freeze
226
235
  s.summary = "basic gear for scouts".freeze
227
236
 
228
237
  s.specification_version = 4
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'scout'
4
+ require 'scout/association'
5
+
6
+ $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
7
+
8
+ options = SOPT.setup <<EOF
9
+
10
+ Query a database
11
+
12
+ $ #{$0} [<options>] <name> <entity>
13
+
14
+ -h--help Print this help
15
+ -l--list Only list matches
16
+ -s--source* Source description
17
+ -t--target* Target description
18
+ -n--namespace* Namespace
19
+ -i--identifiers* Identifiers
20
+ EOF
21
+ if options[:help]
22
+ if defined? scout_usage
23
+ scout_usage
24
+ else
25
+ puts SOPT.doc
26
+ end
27
+ exit 0
28
+ end
29
+
30
+ name, entity = ARGV
31
+
32
+ raise MissingParameterException, :name if name.nil?
33
+ raise MissingParameterException, :entity if entity.nil?
34
+
35
+ registry = begin
36
+ Scout.var.databases.registry.yaml
37
+ rescue
38
+ {}
39
+ end
40
+
41
+ list = IndiferentHash.process_options options, :list
42
+
43
+ raise ParameterException "Database #{name} not found Options: #{Log.fingerprint registry.keys}" unless registry.include? name
44
+
45
+ file, db_options = registry[name]
46
+ options = db_options.merge(options)
47
+
48
+ IndiferentHash.setup(options)
49
+ options.keys_to_sym!
50
+
51
+ index = Association.index(file, **options)
52
+
53
+ if entity.end_with?("~")
54
+ matches = index.match(entity[0..-2])
55
+ elsif entity.start_with?("~")
56
+ index = index.reverse
57
+ matches = index.match(entity[1..-1])
58
+ reverse = true
59
+ elsif entity.include?("~")
60
+ matches = [entity]
61
+ else
62
+ matches = index.match(entity)
63
+ end
64
+
65
+ AssociationItem.setup(matches) if reverse
66
+
67
+ if matches.any?
68
+ if list
69
+ if reverse
70
+ puts matches.collect(&:invert) * "\n"
71
+ else
72
+ puts matches * "\n"
73
+ end
74
+ else
75
+ matches.each do |match|
76
+ puts Log.color :magenta, (reverse ? match.invert : match)
77
+ puts index[match].prety_print
78
+ end
79
+ end
80
+ else
81
+ STDERR.puts "Query #{entity} return no results"
82
+ end
83
+
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'scout'
4
+
5
+ $0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
6
+
7
+ options = SOPT.setup <<EOF
8
+
9
+ Register a database
10
+
11
+ $ #{$0} [<options>] <name> <filename>
12
+
13
+ -h--help Print this help
14
+ -s--source* Source description
15
+ -t--target* Target description
16
+ -n--namespace* Namespace
17
+ -i--identifiers* Identifiers
18
+ EOF
19
+ if options.delete :help
20
+ if defined? scout_usage
21
+ scout_usage
22
+ else
23
+ puts SOPT.doc
24
+ end
25
+ exit 0
26
+ end
27
+
28
+ name, file = ARGV
29
+
30
+ raise MissingParameterException, :name if name.nil?
31
+ raise MissingParameterException, :file if file.nil?
32
+
33
+ registry = begin
34
+ Scout.var.databases.registry.yaml
35
+ rescue
36
+ {}
37
+ end
38
+
39
+ file = Scout.identify(File.expand_path(file))
40
+ registry[name] = [Scout.identify(file), options]
41
+
42
+ Scout.var.databases.registry.write(registry.to_yaml)
43
+