scout-gear 10.7.5 → 10.7.6
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 +4 -4
- data/.vimproject +7 -0
- data/VERSION +1 -1
- data/lib/scout/association/index.rb +2 -2
- data/lib/scout/knowledge_base/description.rb +108 -0
- data/lib/scout/knowledge_base/entity.rb +6 -1
- data/lib/scout/knowledge_base/registry.rb +43 -15
- data/lib/scout/knowledge_base.rb +3 -2
- data/lib/scout/tsv/change_id/translate.rb +1 -0
- data/lib/scout/tsv/open.rb +8 -0
- data/lib/scout/tsv/parser.rb +14 -3
- data/lib/scout/workflow/deployment/orchestrator.rb +9 -1
- data/lib/scout/workflow/deployment/queue.rb +26 -0
- data/lib/scout/workflow/export.rb +6 -0
- data/lib/scout/workflow/persist.rb +6 -0
- data/lib/scout/workflow/step/info.rb +1 -0
- data/lib/scout/workflow/step/inputs.rb +11 -1
- data/lib/scout/workflow/task.rb +2 -1
- data/lib/scout/workflow.rb +7 -1
- data/scout-gear.gemspec +10 -3
- data/scout_commands/kb/config +3 -0
- data/scout_commands/kb/list +1 -0
- data/scout_commands/kb/query +2 -1
- data/scout_commands/kb/register +3 -1
- data/scout_commands/kb/show +4 -2
- data/scout_commands/workflow/cmd +116 -0
- data/scout_commands/workflow/process +82 -0
- data/scout_commands/workflow/task +15 -3
- data/test/data/person/README.md +17 -0
- data/test/scout/knowledge_base/test_description.rb +59 -0
- data/test/scout/workflow/test_entity.rb +3 -3
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f346d283c182fbb5a090329100ad4bd32a50e7e84c058c156014ca1fd2e64772
|
4
|
+
data.tar.gz: d4457afe22a81e426232ee94ddc798921fc69dfcf35a628c8ecafa39fb3a271b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27ac7e8599c5caabad5d63282c2f316404bce25d82dc0cb302acbb249c1ddb76eff171044b0f9c766e05ee582f399f4ba27076c6514bb3abab16857f11974846
|
7
|
+
data.tar.gz: 475df8c7b163a30dd09d608119633443c8bfc9eec1f6bcc657e3f2116bf23a678e18f3224f8da399c6923ac222f5cc1b953dd4035f44514bff90d1ee2b1ffcb7
|
data/.vimproject
CHANGED
@@ -10,6 +10,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
10
10
|
exceptions.rb
|
11
11
|
export.rb
|
12
12
|
definition.rb
|
13
|
+
persist.rb
|
13
14
|
documentation.rb
|
14
15
|
usage.rb
|
15
16
|
util.rb
|
@@ -36,6 +37,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
36
37
|
}
|
37
38
|
deployment.rb
|
38
39
|
deployment=deployment{
|
40
|
+
queue.rb
|
39
41
|
trace.rb
|
40
42
|
orchestrator.rb
|
41
43
|
}
|
@@ -123,6 +125,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
123
125
|
traverse.rb
|
124
126
|
enrichment.rb
|
125
127
|
list.rb
|
128
|
+
description.rb
|
126
129
|
}
|
127
130
|
semaphore.rb
|
128
131
|
}
|
@@ -157,6 +160,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
157
160
|
install
|
158
161
|
trace
|
159
162
|
prov
|
163
|
+
queue
|
164
|
+
process
|
165
|
+
cmd
|
160
166
|
}
|
161
167
|
batch=batch{
|
162
168
|
list
|
@@ -172,6 +178,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
172
178
|
test_scout.rb
|
173
179
|
data=data filter="*"{
|
174
180
|
person=person{
|
181
|
+
README.md
|
175
182
|
brothers
|
176
183
|
identifiers
|
177
184
|
marriages
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
10.7.
|
1
|
+
10.7.6
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'scout/annotation'
|
2
2
|
module Association
|
3
3
|
|
4
|
-
def self.index(file, source: nil, target: nil, source_format: nil, target_format: nil, format: nil, **kwargs)
|
4
|
+
def self.index(file, source: nil, target: nil, source_format: nil, target_format: nil, format: nil, database: nil, **kwargs)
|
5
5
|
IndiferentHash.setup(kwargs)
|
6
6
|
source = kwargs.delete :source if kwargs.include?(:source)
|
7
7
|
target = kwargs.delete :target if kwargs.include?(:target)
|
@@ -14,7 +14,7 @@ module Association
|
|
14
14
|
index = Persist.tsv(file, kwargs, engine: "BDB", persist_options: index_persist_options) do |data|
|
15
15
|
recycle, undirected = IndiferentHash.process_options kwargs, :recycle, :undirected
|
16
16
|
|
17
|
-
database
|
17
|
+
database ||= Association.open(file, source: source, target: target, source_format: source_format, target_format: target_format, **kwargs.merge(persist_prefix: "Association::Database"))
|
18
18
|
|
19
19
|
source_field = database.key_field
|
20
20
|
target_field, *fields = database.fields
|
@@ -0,0 +1,108 @@
|
|
1
|
+
class KnowledgeBase
|
2
|
+
def self.doc_parse_up_to(str, pattern, keep = false)
|
3
|
+
pre, _pat, _post = str.partition pattern
|
4
|
+
if _pat
|
5
|
+
[pre, (keep ? _pat << _post : _post)]
|
6
|
+
else
|
7
|
+
_post
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.doc_parse_chunks(str, pattern)
|
12
|
+
parts = str.split(pattern)
|
13
|
+
return {} if parts.length < 2
|
14
|
+
databases = Hash[*parts[1..-1].collect{|v| v.strip }]
|
15
|
+
databases.delete_if{|t,d| d.empty?}
|
16
|
+
databases.transform_keys!(&:downcase)
|
17
|
+
databases
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.parse_knowledge_base_doc(doc)
|
21
|
+
description, db_description = doc_parse_up_to doc, /^#/, true
|
22
|
+
databases = doc_parse_chunks db_description, /^# (.*)/
|
23
|
+
IndiferentHash.setup({:description => description.strip, :databases => databases})
|
24
|
+
end
|
25
|
+
|
26
|
+
def documentation_markdown
|
27
|
+
return "" if @libdir.nil?
|
28
|
+
file = @libdir['README.md'].find unless file.exists?
|
29
|
+
if file.exists?
|
30
|
+
file.read
|
31
|
+
else
|
32
|
+
""
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def database_description_file(name)
|
37
|
+
dir[name.to_s + '.md']
|
38
|
+
end
|
39
|
+
|
40
|
+
def knowledge_base_description_file(name)
|
41
|
+
file = dir['README.md']
|
42
|
+
return file if file.exists?
|
43
|
+
|
44
|
+
file, options = registry[name]
|
45
|
+
file = Path.setup(file.dup) unless file.nil? or Path === file
|
46
|
+
source_readme = file.dirname['README.md'] if file
|
47
|
+
return source_readme if source_readme && source_readme.exists?
|
48
|
+
end
|
49
|
+
|
50
|
+
def description(name)
|
51
|
+
return registered_options(name)[:description] if registered_options(name)[:description]
|
52
|
+
|
53
|
+
return database_description_file(name).read if database_description_file(name).exist?
|
54
|
+
|
55
|
+
if knowledge_base_description_file(name)
|
56
|
+
KnowledgeBase.parse_knowledge_base_doc(knowledge_base_description_file(name).read)[:databases][name.to_s.downcase]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def markdown(name)
|
61
|
+
description = description(name)
|
62
|
+
source_type = source_type(name)
|
63
|
+
target_type = target_type(name)
|
64
|
+
|
65
|
+
full_description = []
|
66
|
+
empty_line = ''
|
67
|
+
full_description << ("# " << Misc.humanize(name))
|
68
|
+
full_description << empty_line
|
69
|
+
|
70
|
+
source_formats = begin
|
71
|
+
source_index(name).key_field.split(',')
|
72
|
+
rescue
|
73
|
+
[]
|
74
|
+
end
|
75
|
+
|
76
|
+
target_formats = begin
|
77
|
+
target_index(name).key_field.split(',')
|
78
|
+
rescue
|
79
|
+
[]
|
80
|
+
end
|
81
|
+
|
82
|
+
if source_type
|
83
|
+
full_description << "Source: #{source_type} - #{source(name)}"
|
84
|
+
else
|
85
|
+
full_description << "Source: #{source(name)}"
|
86
|
+
end
|
87
|
+
#full_description.last << ". Accepted formats: #{source_formats*", "}" if source_formats.any?
|
88
|
+
|
89
|
+
if target_type
|
90
|
+
full_description << "Target: #{target_type} - #{target(name)}"
|
91
|
+
else
|
92
|
+
full_description << "Target: #{target(name)}"
|
93
|
+
end
|
94
|
+
#full_description.last << ". Accepted formats: #{target_formats*", "}" if target_formats.any?
|
95
|
+
|
96
|
+
if undirected?(name)
|
97
|
+
full_description << "Undirected database, source and target can be reversed."
|
98
|
+
end
|
99
|
+
|
100
|
+
if description
|
101
|
+
full_description << empty_line
|
102
|
+
full_description << description
|
103
|
+
full_description << empty_line
|
104
|
+
end
|
105
|
+
|
106
|
+
full_description * "\n"
|
107
|
+
end
|
108
|
+
end
|
@@ -80,6 +80,7 @@ class KnowledgeBase
|
|
80
80
|
end
|
81
81
|
identifier_files.concat Entity.identifier_files(source(name)) if defined? Entity
|
82
82
|
identifier_files.uniq!
|
83
|
+
identifier_files.collect!{|f| (Path === f) ? f : Path.setup(f.dup) }
|
83
84
|
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, namespace))} if namespace
|
84
85
|
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, db_namespace(name)))} if not namespace and db_namespace(name)
|
85
86
|
identifier_files.reject!{|f| f.match(/\bNAMESPACE\b/)}
|
@@ -89,7 +90,11 @@ class KnowledgeBase
|
|
89
90
|
|
90
91
|
def target_index(name)
|
91
92
|
Persist.memory("Target index #{name}: KB directory #{dir}") do
|
92
|
-
identifier_files
|
93
|
+
if @identifier_files && @identifier_files.any?
|
94
|
+
identifier_files = @identifier_files
|
95
|
+
else
|
96
|
+
identifier_files = database_identifier_files(name)
|
97
|
+
end
|
93
98
|
identifier_files.concat Entity.identifier_files(target(name)) if defined? Entity
|
94
99
|
identifier_files.uniq!
|
95
100
|
identifier_files.collect!{|f| f.annotate(f.gsub(/\bNAMESPACE\b/, namespace))} if self.namespace
|
@@ -15,9 +15,29 @@ class KnowledgeBase
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
def present_databases
|
19
|
+
dir.glob("*.database").collect{|file| File.basename(file, '.database')}
|
20
|
+
end
|
21
|
+
|
18
22
|
def all_databases
|
19
23
|
return [] unless @registry
|
20
|
-
@registry.keys
|
24
|
+
(@registry.keys + present_databases).uniq
|
25
|
+
end
|
26
|
+
|
27
|
+
def database_file(name)
|
28
|
+
if @registry[name].nil?
|
29
|
+
nil
|
30
|
+
else
|
31
|
+
@registry[name].first
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def registered_options(name)
|
36
|
+
if @registry[name].nil?
|
37
|
+
IndiferentHash.setup({})
|
38
|
+
else
|
39
|
+
IndiferentHash.setup(@registry[name].last)
|
40
|
+
end
|
21
41
|
end
|
22
42
|
|
23
43
|
def include?(name)
|
@@ -29,21 +49,21 @@ class KnowledgeBase
|
|
29
49
|
@fields[name] ||= get_index(name).fields
|
30
50
|
end
|
31
51
|
|
32
|
-
def
|
33
|
-
@
|
34
|
-
@
|
52
|
+
def pair(name)
|
53
|
+
@pairs ||= {}
|
54
|
+
@pairs[name] ||= get_index(name).key_field.split("~")
|
35
55
|
end
|
36
56
|
|
37
57
|
def source(name)
|
38
|
-
|
58
|
+
pair(name)[0]
|
39
59
|
end
|
40
60
|
|
41
61
|
def target(name)
|
42
|
-
|
62
|
+
pair(name)[1]
|
43
63
|
end
|
44
64
|
|
45
65
|
def undirected(name)
|
46
|
-
|
66
|
+
pair(name).length == 3
|
47
67
|
end
|
48
68
|
|
49
69
|
alias undirected? undirected
|
@@ -69,7 +89,12 @@ class KnowledgeBase
|
|
69
89
|
|
70
90
|
persist_dir = dir
|
71
91
|
persist_path = persist_dir[key].find
|
72
|
-
|
92
|
+
|
93
|
+
file = database_file(name)
|
94
|
+
registered_options = registered_options(name)
|
95
|
+
registered_options = IndiferentHash.setup(registered_options).except(:description)
|
96
|
+
|
97
|
+
registered_options = IndiferentHash.add_defaults registered_options, identifiers: self.identifier_files if registered_options
|
73
98
|
|
74
99
|
options = IndiferentHash.add_defaults options, registered_options if registered_options and registered_options.any?
|
75
100
|
options = IndiferentHash.add_defaults options, :persist_path => persist_path, :persist_dir => persist_dir, :persist => true
|
@@ -89,11 +114,11 @@ class KnowledgeBase
|
|
89
114
|
Log.low "Re-opening index #{ name } from #{ Log.fingerprint persist_path }. #{options}"
|
90
115
|
Association.index(file, **options, persist_options: persist_options.dup)
|
91
116
|
else
|
92
|
-
|
93
|
-
raise "Repo #{ name } not found and not registered" if file.nil?
|
94
|
-
Log.medium "Opening index #{ name } from #{ Log.fingerprint file }. #{options}"
|
117
|
+
database = get_database name if file.nil?
|
95
118
|
file = file.call if Proc === file
|
96
|
-
|
119
|
+
Log.medium "Opening index #{ name } from #{ Log.fingerprint database }. #{options}"
|
120
|
+
options = IndiferentHash.add_defaults options, registered_options if registered_options
|
121
|
+
Association.index(file, **options, persist_options: persist_options.dup, database: database)
|
97
122
|
end
|
98
123
|
|
99
124
|
index.namespace = self.namespace unless self.namespace
|
@@ -128,7 +153,12 @@ class KnowledgeBase
|
|
128
153
|
|
129
154
|
persist_dir = dir
|
130
155
|
persist_path = persist_dir[key].find
|
131
|
-
|
156
|
+
|
157
|
+
file = database_file(name)
|
158
|
+
registered_options = registered_options(name)
|
159
|
+
registered_options = IndiferentHash.setup(registered_options).except(:description)
|
160
|
+
|
161
|
+
registered_options = IndiferentHash.add_defaults registered_options, identifiers: self.identifier_files if registered_options
|
132
162
|
|
133
163
|
options = IndiferentHash.add_defaults options, registered_options if registered_options and registered_options.any?
|
134
164
|
options = IndiferentHash.add_defaults options, :persist_path => persist_path, :persist => true
|
@@ -145,7 +175,6 @@ class KnowledgeBase
|
|
145
175
|
|
146
176
|
database = if persist_path.exists? and persist_options[:persist] and not persist_options[:update]
|
147
177
|
Log.low "Re-opening database #{ name } from #{ Log.fingerprint persist_path }. #{options}"
|
148
|
-
#Association.database(file, **options, persist_options: persist_options)
|
149
178
|
Association.database(file, **options.merge(persist_options: persist_options))
|
150
179
|
else
|
151
180
|
options = IndiferentHash.add_defaults options, registered_options if registered_options
|
@@ -153,7 +182,6 @@ class KnowledgeBase
|
|
153
182
|
raise "Repo #{ name } not found and not registered" if file.nil?
|
154
183
|
Log.medium "Opening database #{ name } from #{ Log.fingerprint file }. #{options}"
|
155
184
|
file = file.call if Proc === file
|
156
|
-
#Association.database(file, **options, persist_options: persist_options)
|
157
185
|
Association.database(file, **options.merge(persist_options: persist_options))
|
158
186
|
end
|
159
187
|
|
data/lib/scout/knowledge_base.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative 'knowledge_base/entity'
|
|
5
5
|
require_relative 'knowledge_base/query'
|
6
6
|
require_relative 'knowledge_base/traverse'
|
7
7
|
require_relative 'knowledge_base/list'
|
8
|
+
require_relative 'knowledge_base/description'
|
8
9
|
#require 'scout/knowledge_base/query'
|
9
10
|
#require 'scout/knowledge_base/syndicate'
|
10
11
|
|
@@ -23,12 +24,12 @@ class KnowledgeBase
|
|
23
24
|
@entity_options ||= IndiferentHash.setup({})
|
24
25
|
|
25
26
|
@format ||= IndiferentHash.setup({})
|
26
|
-
|
27
|
+
pairs ||= IndiferentHash.setup({})
|
27
28
|
@indices ||= IndiferentHash.setup({})
|
28
29
|
end
|
29
30
|
|
30
31
|
def config_file(name)
|
31
|
-
@dir
|
32
|
+
@dir['config'][name.to_s]
|
32
33
|
end
|
33
34
|
|
34
35
|
def save_variable(name)
|
data/lib/scout/tsv/open.rb
CHANGED
@@ -153,6 +153,14 @@ module Open
|
|
153
153
|
end
|
154
154
|
obj.close
|
155
155
|
obj.join if obj.respond_to? :join
|
156
|
+
elsif options[:type] == :matrix
|
157
|
+
Log.low "Traverse stream by lines #{Log.fingerprint obj}"
|
158
|
+
parser = options[:sep].nil? ? TSV::Parser.new(obj) : TSV::Parser.new(obj, sep: options[:sep])
|
159
|
+
parser.traverse **options do |parts|
|
160
|
+
res = block.call parts
|
161
|
+
callback.call res if callback
|
162
|
+
nil
|
163
|
+
end
|
156
164
|
else
|
157
165
|
Log.low "Traverse stream with parser #{Log.fingerprint obj}"
|
158
166
|
parser = options[:sep].nil? ? TSV::Parser.new(obj) : TSV::Parser.new(obj, sep: options[:sep])
|
data/lib/scout/tsv/parser.rb
CHANGED
@@ -31,6 +31,12 @@ module TSV
|
|
31
31
|
|
32
32
|
return nil if select && ! TSV.select(items[0], items[1..-1], select, fields: field_names, type: type, sep: sep2)
|
33
33
|
|
34
|
+
if String === key
|
35
|
+
raise "Key by name, but no field names" if field_names.nil?
|
36
|
+
key = field_names.index key
|
37
|
+
raise "Key #{key} not found in field names #{Log.fingerprint field_names}" if key.nil?
|
38
|
+
end
|
39
|
+
|
34
40
|
if positions.nil? && key == 0
|
35
41
|
key = items.shift
|
36
42
|
elsif positions.nil?
|
@@ -65,7 +71,7 @@ module TSV
|
|
65
71
|
[key, items]
|
66
72
|
end
|
67
73
|
|
68
|
-
def self.parse_stream(stream, data: nil, source_type: nil, type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, field_names: nil, head: nil, **kwargs, &block)
|
74
|
+
def self.parse_stream(stream, data: nil, source_type: nil, sep: "\t", type: :list, merge: true, one2one: false, fix: true, bar: false, first_line: nil, field_names: nil, head: nil, **kwargs, &block)
|
69
75
|
begin
|
70
76
|
bar = "Parsing #{Log.fingerprint stream}" if TrueClass === bar
|
71
77
|
bar = Log::ProgressBar.get_obj_bar(stream, bar) if bar
|
@@ -81,7 +87,7 @@ module TSV
|
|
81
87
|
data.serializer.to_s.include?("String") &&
|
82
88
|
same_type &&
|
83
89
|
! (head || kwargs[:cast] || kwargs[:positions] || (kwargs[:key] && kwargs[:key] != 0) || Proc === fix ) &&
|
84
|
-
(
|
90
|
+
(sep.nil? || sep == "\t")
|
85
91
|
|
86
92
|
|
87
93
|
Log.debug "Loading #{Log.fingerprint stream} directly into #{Log.fingerprint data}"
|
@@ -114,12 +120,17 @@ module TSV
|
|
114
120
|
line = Misc.fixutf8(line)
|
115
121
|
end
|
116
122
|
bar.tick if bar
|
123
|
+
|
117
124
|
if type == :array || type == :line
|
118
125
|
block.call line
|
119
126
|
next
|
127
|
+
elsif type == :matrix
|
128
|
+
parts = line.split(sep)
|
129
|
+
block.call parts
|
130
|
+
next
|
120
131
|
end
|
121
132
|
|
122
|
-
key, items = parse_line(line, type: source_type, field_names: field_names, **kwargs)
|
133
|
+
key, items = parse_line(line, type: source_type, field_names: field_names, sep: sep, **kwargs)
|
123
134
|
|
124
135
|
next if key.nil?
|
125
136
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Workflow
|
2
2
|
class Orchestrator
|
3
3
|
|
4
|
+
class NoWork < Exception; end
|
5
|
+
|
4
6
|
def self.job_workload(job)
|
5
7
|
workload = {job => []}
|
6
8
|
return workload if job.done? && job.updated?
|
@@ -202,7 +204,7 @@ module Workflow
|
|
202
204
|
|
203
205
|
candidates = resources_used.keys + Orchestrator.candidates(workload, rules)
|
204
206
|
candidates.uniq!
|
205
|
-
raise "No candidates and no running jobs" if candidates.empty?
|
207
|
+
raise NoWork, "No candidates and no running jobs" if candidates.empty?
|
206
208
|
|
207
209
|
candidates.each do |job|
|
208
210
|
case
|
@@ -272,4 +274,10 @@ module Workflow
|
|
272
274
|
orchestrator.process({}, produce_list)
|
273
275
|
produce_list
|
274
276
|
end
|
277
|
+
|
278
|
+
def self.produce(jobs, produce_cpus: Etc.nprocessors, produce_timer: 5)
|
279
|
+
jobs = [jobs] unless Array === jobs
|
280
|
+
orchestrator = Orchestrator.new produce_timer.to_i, cpus: produce_cpus.to_i
|
281
|
+
orchestrator.process({}, jobs)
|
282
|
+
end
|
275
283
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Workflow
|
2
|
+
def self.name2clean_name(name)
|
3
|
+
name.reverse.partition("_").last.reverse
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.queue_job(file)
|
7
|
+
workflow, task, name = file.split("/").values_at(-3, -2, -1) if file
|
8
|
+
workflow = Workflow.require_workflow workflow
|
9
|
+
|
10
|
+
if Open.directory?(file)
|
11
|
+
clean_name = name2clean_name name
|
12
|
+
inputs = workflow.tasks[task].load_inputs(file)
|
13
|
+
workflow.job(task, clean_name, inputs)
|
14
|
+
else
|
15
|
+
workflow.job(task, name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.unqueue(file, &block)
|
20
|
+
Open.lock file do
|
21
|
+
job = queue_job(file)
|
22
|
+
puts job.run
|
23
|
+
Open.rm_rf file
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -18,6 +18,12 @@ module Workflow
|
|
18
18
|
@exec_exports ||= []
|
19
19
|
end
|
20
20
|
|
21
|
+
def clear_exports
|
22
|
+
asynchronous_exports.clear
|
23
|
+
synchronous_exports.clear
|
24
|
+
exec_exports.clear
|
25
|
+
stream_exports.clear
|
26
|
+
end
|
21
27
|
|
22
28
|
def all_exports
|
23
29
|
asynchronous_exports + synchronous_exports + exec_exports + stream_exports
|
@@ -1,5 +1,15 @@
|
|
1
1
|
class Step
|
2
2
|
def save_inputs(inputs_dir)
|
3
|
-
|
3
|
+
if clean_name != name
|
4
|
+
hash = name[clean_name.length..-1]
|
5
|
+
inputs_dir += hash
|
6
|
+
Log.medium "Saving job inputs to: #{Log.fingerprint inputs_dir}"
|
7
|
+
self.task.save_inputs(inputs_dir, provided_inputs)
|
8
|
+
inputs_dir
|
9
|
+
else
|
10
|
+
Log.medium "Saving no input job: #{Log.fingerprint inputs_dir}"
|
11
|
+
Open.touch(inputs_dir)
|
12
|
+
inputs_dir
|
13
|
+
end
|
4
14
|
end
|
5
15
|
end
|
data/lib/scout/workflow/task.rb
CHANGED
@@ -34,6 +34,7 @@ module Task
|
|
34
34
|
def job(id = nil, provided_inputs = nil)
|
35
35
|
|
36
36
|
if Hash === provided_inputs
|
37
|
+
IndiferentHash.setup provided_inputs
|
37
38
|
memory_inputs = provided_inputs.values_at *self.recursive_inputs.collect{|t| t.first }.uniq
|
38
39
|
memory_inputs += provided_inputs.select{|k,v| k.to_s.include?("#") }.collect{|p| p * "=" }
|
39
40
|
memory_inputs << provided_inputs[:load_inputs]
|
@@ -41,7 +42,7 @@ module Task
|
|
41
42
|
memory_inputs = provided_inputs
|
42
43
|
end
|
43
44
|
|
44
|
-
Persist.memory("Task job #{self.name}
|
45
|
+
Persist.memory("Task job #{self.name}", repo: Workflow.job_cache, other: {task: self.name, id: id, provided_inputs: memory_inputs}) do
|
45
46
|
provided_inputs, id = id, nil if (provided_inputs.nil? || provided_inputs.empty?) && (Hash === id || Array === id)
|
46
47
|
provided_inputs = {} if provided_inputs.nil?
|
47
48
|
IndiferentHash.setup(provided_inputs)
|
data/lib/scout/workflow.rb
CHANGED
@@ -9,13 +9,19 @@ require_relative 'workflow/exceptions'
|
|
9
9
|
require_relative 'workflow/path'
|
10
10
|
require_relative 'workflow/entity'
|
11
11
|
require_relative 'workflow/export'
|
12
|
+
require_relative 'workflow/persist'
|
12
13
|
|
13
14
|
require 'scout/resource'
|
14
15
|
require 'scout/resource/scout'
|
15
16
|
|
16
17
|
module Workflow
|
17
18
|
class << self
|
18
|
-
attr_accessor :workflows, :main, :workflow_dir, :autoinstall, :workflow_repo
|
19
|
+
attr_accessor :workflows, :main, :workflow_dir, :autoinstall, :workflow_repo, :job_cache
|
20
|
+
|
21
|
+
def job_cache
|
22
|
+
@job_cache ||={}
|
23
|
+
end
|
24
|
+
|
19
25
|
def workflows
|
20
26
|
@workflows ||= []
|
21
27
|
end
|
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.
|
5
|
+
# stub: scout-gear 10.7.6 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "scout-gear".freeze
|
9
|
-
s.version = "10.7.
|
9
|
+
s.version = "10.7.6".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 = "2025-
|
14
|
+
s.date = "2025-04-08"
|
15
15
|
s.description = "Scout gear: workflow, TSVs, persistence, entities, associations, and knowledge_bases.".freeze
|
16
16
|
s.email = "mikisvaz@gmail.com".freeze
|
17
17
|
s.executables = ["scout".freeze]
|
@@ -45,6 +45,7 @@ Gem::Specification.new do |s|
|
|
45
45
|
"lib/scout/entity/object.rb",
|
46
46
|
"lib/scout/entity/property.rb",
|
47
47
|
"lib/scout/knowledge_base.rb",
|
48
|
+
"lib/scout/knowledge_base/description.rb",
|
48
49
|
"lib/scout/knowledge_base/enrichment.rb",
|
49
50
|
"lib/scout/knowledge_base/entity.rb",
|
50
51
|
"lib/scout/knowledge_base/list.rb",
|
@@ -98,12 +99,14 @@ Gem::Specification.new do |s|
|
|
98
99
|
"lib/scout/workflow/definition.rb",
|
99
100
|
"lib/scout/workflow/deployment.rb",
|
100
101
|
"lib/scout/workflow/deployment/orchestrator.rb",
|
102
|
+
"lib/scout/workflow/deployment/queue.rb",
|
101
103
|
"lib/scout/workflow/deployment/trace.rb",
|
102
104
|
"lib/scout/workflow/documentation.rb",
|
103
105
|
"lib/scout/workflow/entity.rb",
|
104
106
|
"lib/scout/workflow/exceptions.rb",
|
105
107
|
"lib/scout/workflow/export.rb",
|
106
108
|
"lib/scout/workflow/path.rb",
|
109
|
+
"lib/scout/workflow/persist.rb",
|
107
110
|
"lib/scout/workflow/step.rb",
|
108
111
|
"lib/scout/workflow/step/archive.rb",
|
109
112
|
"lib/scout/workflow/step/children.rb",
|
@@ -142,9 +145,11 @@ Gem::Specification.new do |s|
|
|
142
145
|
"scout_commands/resource/produce",
|
143
146
|
"scout_commands/template",
|
144
147
|
"scout_commands/update",
|
148
|
+
"scout_commands/workflow/cmd",
|
145
149
|
"scout_commands/workflow/info",
|
146
150
|
"scout_commands/workflow/install",
|
147
151
|
"scout_commands/workflow/list",
|
152
|
+
"scout_commands/workflow/process",
|
148
153
|
"scout_commands/workflow/prov",
|
149
154
|
"scout_commands/workflow/task",
|
150
155
|
"scout_commands/workflow/trace",
|
@@ -154,6 +159,7 @@ Gem::Specification.new do |s|
|
|
154
159
|
"share/software/install_helpers",
|
155
160
|
"share/templates/command",
|
156
161
|
"share/templates/workflow.rb",
|
162
|
+
"test/data/person/README.md",
|
157
163
|
"test/data/person/brothers",
|
158
164
|
"test/data/person/identifiers",
|
159
165
|
"test/data/person/marriages",
|
@@ -166,6 +172,7 @@ Gem::Specification.new do |s|
|
|
166
172
|
"test/scout/entity/test_named_array.rb",
|
167
173
|
"test/scout/entity/test_object.rb",
|
168
174
|
"test/scout/entity/test_property.rb",
|
175
|
+
"test/scout/knowledge_base/test_description.rb",
|
169
176
|
"test/scout/knowledge_base/test_enrichment.rb",
|
170
177
|
"test/scout/knowledge_base/test_entity.rb",
|
171
178
|
"test/scout/knowledge_base/test_list.rb",
|
data/scout_commands/kb/config
CHANGED
@@ -12,6 +12,7 @@ Configure a knowlege base
|
|
12
12
|
$ #{$0} [<options>] <name> [knowledge_base]
|
13
13
|
|
14
14
|
-h--help Print this help
|
15
|
+
-kb--knowledge_base* Knowlege base name (or :default)
|
15
16
|
-i--identifier_files* Identifier files separated by ','
|
16
17
|
-n--namespace* Namespace
|
17
18
|
EOF
|
@@ -26,8 +27,10 @@ end
|
|
26
27
|
|
27
28
|
knowledge_base_name = ARGV.first
|
28
29
|
|
30
|
+
knowledge_base_name ||= options[:knowledge_base] || :default
|
29
31
|
knowledge_base = KnowledgeBase.load knowledge_base_name || :default
|
30
32
|
|
31
33
|
knowledge_base.namespace = options[:namespace] if options.include? :namespace
|
32
34
|
knowledge_base.identifier_files += options[:identifier_files].split(",") if options.include? :identifier_files
|
35
|
+
knowledge_base.identifier_files.uniq!
|
33
36
|
knowledge_base.save
|
data/scout_commands/kb/list
CHANGED
data/scout_commands/kb/query
CHANGED
@@ -34,7 +34,8 @@ raise MissingParameterException, :name if name.nil?
|
|
34
34
|
raise MissingParameterException, :entity if entity.nil?
|
35
35
|
|
36
36
|
|
37
|
-
knowledge_base =
|
37
|
+
knowledge_base = IndiferentHash.process_options options, :knowledge_base
|
38
|
+
knowledge_base = KnowledgeBase.load knowledge_base || :default
|
38
39
|
|
39
40
|
list = IndiferentHash.process_options options, :list
|
40
41
|
|
data/scout_commands/kb/register
CHANGED
@@ -19,6 +19,7 @@ $ #{$0} [<options>] <name> <filename>
|
|
19
19
|
-n--namespace* Namespace
|
20
20
|
-i--identifiers* Identifiers
|
21
21
|
-u--undirected
|
22
|
+
-d--description* Database description
|
22
23
|
EOF
|
23
24
|
if options.delete :help
|
24
25
|
if defined? scout_usage
|
@@ -35,7 +36,8 @@ name, file = ARGV
|
|
35
36
|
raise MissingParameterException, :name if name.nil?
|
36
37
|
raise MissingParameterException, :file if file.nil?
|
37
38
|
|
38
|
-
knowledge_base =
|
39
|
+
knowledge_base = IndiferentHash.process_options options, :knowledge_base
|
40
|
+
knowledge_base = KnowledgeBase.load knowledge_base || :default
|
39
41
|
|
40
42
|
options[:fields] = options[:fields].split(/,\s*/) if options[:fields]
|
41
43
|
file = Scout.identify(File.expand_path(file))
|
data/scout_commands/kb/show
CHANGED
@@ -23,7 +23,8 @@ if options[:help]
|
|
23
23
|
exit 0
|
24
24
|
end
|
25
25
|
|
26
|
-
knowledge_base =
|
26
|
+
knowledge_base = IndiferentHash.process_options options, :knowledge_base
|
27
|
+
knowledge_base = KnowledgeBase.load knowledge_base || :default
|
27
28
|
|
28
29
|
name = ARGV.first
|
29
30
|
|
@@ -31,7 +32,8 @@ if name.nil?
|
|
31
32
|
puts knowledge_base.all_databases * "\n"
|
32
33
|
else
|
33
34
|
|
34
|
-
raise ParameterException "Database #{name} not found Options: #{Log.fingerprint knowledge_base.all_databases}" unless knowledge_base.include? name
|
35
|
+
raise ParameterException, "Database #{name} not found Options: #{Log.fingerprint knowledge_base.all_databases}" unless knowledge_base.include? name
|
35
36
|
|
37
|
+
puts knowledge_base.markdown(name)
|
36
38
|
Log.tsv knowledge_base.get_database(name, options)
|
37
39
|
end
|
@@ -0,0 +1,116 @@
|
|
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
|
+
Run a workflow command
|
10
|
+
|
11
|
+
$ #{$0} <workflow> <command> [<subcommands>] [<options>] [<arg> ...]
|
12
|
+
|
13
|
+
-h--help Print this help
|
14
|
+
EOF
|
15
|
+
if options[:help]
|
16
|
+
if defined? scout_usage
|
17
|
+
scout_usage
|
18
|
+
else
|
19
|
+
puts SOPT.doc
|
20
|
+
end
|
21
|
+
exit 0
|
22
|
+
end
|
23
|
+
|
24
|
+
workflow = ARGV.shift
|
25
|
+
|
26
|
+
if workflow == '-h'
|
27
|
+
if defined? scout_usage
|
28
|
+
scout_usage
|
29
|
+
else
|
30
|
+
puts SOPT.doc
|
31
|
+
end
|
32
|
+
exit 0
|
33
|
+
end
|
34
|
+
|
35
|
+
raise ParameterException, "No workflow specified" if workflow.nil?
|
36
|
+
|
37
|
+
require 'scout/workflow'
|
38
|
+
|
39
|
+
wf = Workflow.require_workflow workflow
|
40
|
+
dir = $command_dir = wf.libdir.share.scout_commands.find
|
41
|
+
|
42
|
+
def prev_dir(prev)
|
43
|
+
scout_command_dir = $command_dir
|
44
|
+
|
45
|
+
prev.each do |previous_command|
|
46
|
+
scout_command_dir = scout_command_dir[previous_command]
|
47
|
+
end
|
48
|
+
|
49
|
+
scout_command_dir
|
50
|
+
end
|
51
|
+
|
52
|
+
def commands(prev)
|
53
|
+
scout_command_dir = prev_dir(prev)
|
54
|
+
|
55
|
+
command_file_dirs = scout_command_dir.find_all
|
56
|
+
command_files = command_file_dirs.collect{|d| d.glob('*') }.flatten
|
57
|
+
command_files.collect{|p| File.basename(p) }.uniq.reject{|p| p =~ /\.desc$/}.sort
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
prev = []
|
62
|
+
|
63
|
+
$previous_commands << ' cmd'
|
64
|
+
$previous_commands << ' ' << workflow
|
65
|
+
|
66
|
+
begin
|
67
|
+
while ARGV.any?
|
68
|
+
command = ARGV.shift
|
69
|
+
case
|
70
|
+
when File.directory?(dir[command].find)
|
71
|
+
prev << command
|
72
|
+
$previous_commands << command
|
73
|
+
dir = dir[command]
|
74
|
+
when File.directory?(dir[command].find)
|
75
|
+
prev << command
|
76
|
+
dir = dir[command]
|
77
|
+
when dir[command].exists?
|
78
|
+
load dir[command].find
|
79
|
+
exit 0
|
80
|
+
else
|
81
|
+
if command == 'bootstrap'
|
82
|
+
if wf.libdir["test_workflow.rb"].exists?
|
83
|
+
Log.info "No bootstrap for #{ workflow }, running test_workflow.rb instead"
|
84
|
+
CMD.cmd_log('ruby', wf.libdir["test_workflow.rb"].find)
|
85
|
+
else
|
86
|
+
Log.info "No bootstrap for #{ workflow }, running examples instead"
|
87
|
+
CMD.cmd_log("scout workflow example #{ workflow }")
|
88
|
+
exit 0
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
raise ParameterException, "Error: Command not understood: #{command}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
puts SOPT.doc
|
98
|
+
puts
|
99
|
+
puts Log.color :magenta, "## COMMANDS"
|
100
|
+
puts
|
101
|
+
puts Log.color :magenta, "Command:"
|
102
|
+
puts
|
103
|
+
puts " scout #{$previous_commands * " "} "
|
104
|
+
puts
|
105
|
+
puts Log.color :magenta, "Subcommands:"
|
106
|
+
puts
|
107
|
+
|
108
|
+
commands(prev).each do |command|
|
109
|
+
directory = File.directory? dir[command].find
|
110
|
+
if directory
|
111
|
+
puts " " << Log.color(:blue, command)
|
112
|
+
else
|
113
|
+
puts " " << command
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'scout'
|
4
|
+
require 'scout/workflow/deployment/queue'
|
5
|
+
require 'scout/workflow/deployment/orchestrator'
|
6
|
+
|
7
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
8
|
+
|
9
|
+
options = SOPT.setup <<EOF
|
10
|
+
|
11
|
+
Process the queue
|
12
|
+
|
13
|
+
$ #{$0} [<options>] ([<workflow>] [<task>] [<name>] | <filename>)
|
14
|
+
|
15
|
+
-h--help Print this help
|
16
|
+
-l--list List queue jobs
|
17
|
+
--continuous Process continuously
|
18
|
+
--produce_timer* Produce timer for sleeping
|
19
|
+
--produce_cpus* Cpus to use concurrently producing jobs
|
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
|
+
list, continuous = IndiferentHash.process_options options, :list, :continuous
|
30
|
+
|
31
|
+
queue_dir = Scout.var.queue
|
32
|
+
|
33
|
+
class TrayAgain < Exception; end
|
34
|
+
|
35
|
+
begin
|
36
|
+
if ARGV.empty?
|
37
|
+
files = queue_dir.glob("*/*/*")
|
38
|
+
if list
|
39
|
+
puts files * "\n"
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
else
|
43
|
+
workflow, task, name = ARGV
|
44
|
+
|
45
|
+
# First deal with fixed files
|
46
|
+
if task.nil?
|
47
|
+
if Open.exists?(workflow)
|
48
|
+
Workflow.unqueue files.first
|
49
|
+
exit
|
50
|
+
|
51
|
+
else
|
52
|
+
files = queue_dir.glob("#{workflow}/*/*")
|
53
|
+
end
|
54
|
+
elsif name.nil?
|
55
|
+
files = queue_dir.glob("#{workflow}/#{task}/*")
|
56
|
+
else
|
57
|
+
files = queue_dir.glob("#{workflow}/#{task}/#{name}*")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
jobs = files.collect{|file| Workflow.queue_job(file) }
|
62
|
+
begin
|
63
|
+
options.keys.each do |key|
|
64
|
+
options[key.to_sym] = options.delete(key)
|
65
|
+
end
|
66
|
+
Workflow.produce(jobs, **options)
|
67
|
+
rescue Workflow::Orchestrator::NoWork
|
68
|
+
end
|
69
|
+
|
70
|
+
files.each do |f| Open.rm_rf f end
|
71
|
+
|
72
|
+
Workflow.job_cache.clear
|
73
|
+
|
74
|
+
if continuous
|
75
|
+
Log.debug "Continuous processing"
|
76
|
+
sleep 1
|
77
|
+
raise Workflow::Orchestrator::NoWork
|
78
|
+
end
|
79
|
+
rescue Workflow::Orchestrator::NoWork
|
80
|
+
retry
|
81
|
+
end
|
82
|
+
|
@@ -20,8 +20,9 @@ $ #{$0} [<options>] <workflow> <task>
|
|
20
20
|
--update Update jobs with newer dependencies
|
21
21
|
--deploy* Deploy mode: serial, local, or SLURM (default 'serial')
|
22
22
|
--fork Fork and return path
|
23
|
+
--load_inputs* Directory or file with inputs files to load
|
24
|
+
--save_inputs* Directory or tar.gz file path to store inputs
|
23
25
|
-jn--jobname* Name to use as job identifier
|
24
|
-
-li--load_inputs* Directory with inputs files to load
|
25
26
|
-pf--printpath Print the file path
|
26
27
|
-prov--provenance Print the step provenance
|
27
28
|
-cl--clean Clean the last step
|
@@ -40,8 +41,8 @@ task = workflow.tasks[task_name.to_sym] if task_name
|
|
40
41
|
|
41
42
|
options[:help] = true if task.nil?
|
42
43
|
|
43
|
-
help, provenance, clean, recursive_clean, clean_task, load_inputs, jobname, printpath, deploy, override_deps, do_fork = IndiferentHash.process_options options,
|
44
|
-
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :jobname, :printpath, :deploy, :override_deps, :fork,
|
44
|
+
help, provenance, clean, recursive_clean, clean_task, load_inputs, save_inputs, jobname, printpath, deploy, override_deps, do_fork = IndiferentHash.process_options options,
|
45
|
+
:help, :provenance, :clean, :recursive_clean, :clean_task, :load_inputs, :save_inputs, :jobname, :printpath, :deploy, :override_deps, :fork,
|
45
46
|
:deploy => 'serial'
|
46
47
|
|
47
48
|
if help
|
@@ -93,12 +94,23 @@ end
|
|
93
94
|
|
94
95
|
if provenance
|
95
96
|
puts Step.prov_report(job)
|
97
|
+
|
96
98
|
elsif do_fork
|
97
99
|
job.fork
|
98
100
|
puts job.path
|
99
101
|
exit 0
|
102
|
+
elsif save_inputs
|
103
|
+
puts job.save_inputs(save_inputs)
|
104
|
+
exit 0
|
100
105
|
else
|
106
|
+
|
101
107
|
case deploy
|
108
|
+
when "queue"
|
109
|
+
if ! job.done?
|
110
|
+
save_inputs = Scout.var.queue[workflow.to_s][task_name][job.clean_name].find
|
111
|
+
puts job.save_inputs(save_inputs)
|
112
|
+
exit
|
113
|
+
end
|
102
114
|
when "serial"
|
103
115
|
job.run(true)
|
104
116
|
when "local"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
Databases describing people and their relationships.
|
2
|
+
|
3
|
+
# Brothers
|
4
|
+
|
5
|
+
Sibling relationships. The first of the pair is the Older
|
6
|
+
|
7
|
+
# Marriages
|
8
|
+
|
9
|
+
Marriages between people.
|
10
|
+
|
11
|
+
Date: Date when the marriage occurred
|
12
|
+
|
13
|
+
# Parents
|
14
|
+
|
15
|
+
List parents.
|
16
|
+
|
17
|
+
Type of parent: father or mother
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.expand_path(__FILE__).sub(%r(/test/.*), '/test/test_helper.rb')
|
2
|
+
require File.expand_path(__FILE__).sub(%r(.*/test/), '').sub(/test_(.*)\.rb/,'\1')
|
3
|
+
|
4
|
+
require 'scout/knowledge_base'
|
5
|
+
class TestKnowledgebaseDesc < Test::Unit::TestCase
|
6
|
+
def test_brothers_registry
|
7
|
+
TmpFile.with_dir do |dir|
|
8
|
+
brothers = datafile_test(:person).brothers
|
9
|
+
kb = KnowledgeBase.new dir
|
10
|
+
kb.register :brothers, brothers, description: "Sibling relationships."
|
11
|
+
assert_equal "Sibling relationships.", kb.description(:brothers)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_brothers_README
|
16
|
+
TmpFile.with_dir do |dir|
|
17
|
+
brothers = datafile_test(:person).brothers
|
18
|
+
kb = KnowledgeBase.new dir
|
19
|
+
kb.register :brothers, brothers
|
20
|
+
kb.dir['brothers.md'].write "Sibling relationships."
|
21
|
+
assert_equal "Sibling relationships.", kb.description(:brothers)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_broters_kb_README
|
26
|
+
TmpFile.with_dir do |dir|
|
27
|
+
brothers = datafile_test(:person).brothers
|
28
|
+
kb = KnowledgeBase.new dir
|
29
|
+
kb.register :brothers, brothers
|
30
|
+
kb.dir['README.md'].write <<-EOF
|
31
|
+
Databases describing people and their relationships.
|
32
|
+
|
33
|
+
# Brothers
|
34
|
+
|
35
|
+
Sibling relationships.
|
36
|
+
EOF
|
37
|
+
assert_equal "Sibling relationships.", kb.description(:brothers)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_brothers_kb_source_README
|
42
|
+
TmpFile.with_dir do |dir|
|
43
|
+
brothers = datafile_test(:person).brothers
|
44
|
+
kb = KnowledgeBase.new dir
|
45
|
+
kb.register :brothers, brothers
|
46
|
+
assert_include kb.description(:brothers), "Sibling relationships."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_full_description
|
51
|
+
TmpFile.with_dir do |dir|
|
52
|
+
brothers = datafile_test(:person).brothers
|
53
|
+
kb = KnowledgeBase.new dir
|
54
|
+
kb.register :brothers, brothers
|
55
|
+
assert_include kb.markdown(:brothers), "Older"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -12,15 +12,15 @@ class TestWorkflowEntity < Test::Unit::TestCase
|
|
12
12
|
"Mi name is #{self}"
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
entity_task hi: :string do
|
16
16
|
"Hi. #{entity.introduction}"
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
list_task group_hi: :string do
|
20
20
|
"Here is the group: " + entity_list.hi * "; "
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
list_task bye: :array do
|
24
24
|
entity_list.collect do |e|
|
25
25
|
"Bye from #{e}"
|
26
26
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout-gear
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 10.7.
|
4
|
+
version: 10.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miguel Vazquez
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-08 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: scout-essentials
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/scout/entity/object.rb
|
115
115
|
- lib/scout/entity/property.rb
|
116
116
|
- lib/scout/knowledge_base.rb
|
117
|
+
- lib/scout/knowledge_base/description.rb
|
117
118
|
- lib/scout/knowledge_base/enrichment.rb
|
118
119
|
- lib/scout/knowledge_base/entity.rb
|
119
120
|
- lib/scout/knowledge_base/list.rb
|
@@ -167,12 +168,14 @@ files:
|
|
167
168
|
- lib/scout/workflow/definition.rb
|
168
169
|
- lib/scout/workflow/deployment.rb
|
169
170
|
- lib/scout/workflow/deployment/orchestrator.rb
|
171
|
+
- lib/scout/workflow/deployment/queue.rb
|
170
172
|
- lib/scout/workflow/deployment/trace.rb
|
171
173
|
- lib/scout/workflow/documentation.rb
|
172
174
|
- lib/scout/workflow/entity.rb
|
173
175
|
- lib/scout/workflow/exceptions.rb
|
174
176
|
- lib/scout/workflow/export.rb
|
175
177
|
- lib/scout/workflow/path.rb
|
178
|
+
- lib/scout/workflow/persist.rb
|
176
179
|
- lib/scout/workflow/step.rb
|
177
180
|
- lib/scout/workflow/step/archive.rb
|
178
181
|
- lib/scout/workflow/step/children.rb
|
@@ -211,9 +214,11 @@ files:
|
|
211
214
|
- scout_commands/resource/produce
|
212
215
|
- scout_commands/template
|
213
216
|
- scout_commands/update
|
217
|
+
- scout_commands/workflow/cmd
|
214
218
|
- scout_commands/workflow/info
|
215
219
|
- scout_commands/workflow/install
|
216
220
|
- scout_commands/workflow/list
|
221
|
+
- scout_commands/workflow/process
|
217
222
|
- scout_commands/workflow/prov
|
218
223
|
- scout_commands/workflow/task
|
219
224
|
- scout_commands/workflow/trace
|
@@ -223,6 +228,7 @@ files:
|
|
223
228
|
- share/software/install_helpers
|
224
229
|
- share/templates/command
|
225
230
|
- share/templates/workflow.rb
|
231
|
+
- test/data/person/README.md
|
226
232
|
- test/data/person/brothers
|
227
233
|
- test/data/person/identifiers
|
228
234
|
- test/data/person/marriages
|
@@ -235,6 +241,7 @@ files:
|
|
235
241
|
- test/scout/entity/test_named_array.rb
|
236
242
|
- test/scout/entity/test_object.rb
|
237
243
|
- test/scout/entity/test_property.rb
|
244
|
+
- test/scout/knowledge_base/test_description.rb
|
238
245
|
- test/scout/knowledge_base/test_enrichment.rb
|
239
246
|
- test/scout/knowledge_base/test_entity.rb
|
240
247
|
- test/scout/knowledge_base/test_list.rb
|