scout-gear 10.7.4 → 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/.gitmodules +0 -4
- data/.vimproject +9 -14
- data/Rakefile +1 -4
- data/VERSION +1 -1
- data/lib/scout/association/index.rb +3 -3
- data/lib/scout/entity/identifiers.rb +5 -2
- data/lib/scout/entity/property.rb +1 -1
- 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 +9 -2
- data/lib/scout/tsv/open.rb +10 -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/entity.rb +99 -0
- data/lib/scout/workflow/export.rb +72 -0
- data/lib/scout/workflow/persist.rb +6 -0
- data/lib/scout/workflow/step/file.rb +3 -3
- data/lib/scout/workflow/step/info.rb +6 -0
- data/lib/scout/workflow/step/inputs.rb +11 -1
- data/lib/scout/workflow/step/provenance.rb +1 -2
- data/lib/scout/workflow/step/status.rb +1 -0
- data/lib/scout/workflow/step.rb +5 -3
- data/lib/scout/workflow/task/inputs.rb +2 -1
- data/lib/scout/workflow/task.rb +2 -1
- data/lib/scout/workflow.rb +11 -3
- data/lib/scout-gear.rb +5 -1
- data/scout-gear.gemspec +14 -18
- 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/task/test_dependencies.rb +7 -7
- data/test/scout/workflow/test_definition.rb +2 -2
- data/test/scout/workflow/test_entity.rb +58 -0
- data/test/scout/workflow/test_step.rb +1 -1
- metadata +14 -57
- data/lib/scout/offsite/exceptions.rb +0 -9
- data/lib/scout/offsite/ssh.rb +0 -175
- data/lib/scout/offsite/step.rb +0 -100
- data/lib/scout/offsite/sync.rb +0 -55
- data/lib/scout/offsite.rb +0 -3
- data/scout_commands/offsite +0 -30
- data/test/scout/offsite/test_ssh.rb +0 -15
- data/test/scout/offsite/test_step.rb +0 -32
- data/test/scout/offsite/test_sync.rb +0 -36
- data/test/scout/offsite/test_task.rb +0 -0
- data/test/scout/test_offsite.rb +0 -0
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/.gitmodules
CHANGED
data/.vimproject
CHANGED
@@ -8,7 +8,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
8
8
|
workflow.rb
|
9
9
|
workflow=workflow{
|
10
10
|
exceptions.rb
|
11
|
+
export.rb
|
11
12
|
definition.rb
|
13
|
+
persist.rb
|
12
14
|
documentation.rb
|
13
15
|
usage.rb
|
14
16
|
util.rb
|
@@ -35,9 +37,11 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
35
37
|
}
|
36
38
|
deployment.rb
|
37
39
|
deployment=deployment{
|
40
|
+
queue.rb
|
38
41
|
trace.rb
|
39
42
|
orchestrator.rb
|
40
43
|
}
|
44
|
+
entity.rb
|
41
45
|
}
|
42
46
|
work_queue.rb
|
43
47
|
work_queue=work_queue{
|
@@ -121,12 +125,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
121
125
|
traverse.rb
|
122
126
|
enrichment.rb
|
123
127
|
list.rb
|
124
|
-
|
125
|
-
offsite.rb
|
126
|
-
offsite=offsite{
|
127
|
-
ssh.rb
|
128
|
-
sync.rb
|
129
|
-
step.rb
|
128
|
+
description.rb
|
130
129
|
}
|
131
130
|
semaphore.rb
|
132
131
|
}
|
@@ -144,7 +143,6 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
144
143
|
doc
|
145
144
|
update
|
146
145
|
template
|
147
|
-
offsite
|
148
146
|
kb=kb{
|
149
147
|
config
|
150
148
|
entities
|
@@ -162,6 +160,9 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
162
160
|
install
|
163
161
|
trace
|
164
162
|
prov
|
163
|
+
queue
|
164
|
+
process
|
165
|
+
cmd
|
165
166
|
}
|
166
167
|
batch=batch{
|
167
168
|
list
|
@@ -177,6 +178,7 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
177
178
|
test_scout.rb
|
178
179
|
data=data filter="*"{
|
179
180
|
person=person{
|
181
|
+
README.md
|
180
182
|
brothers
|
181
183
|
identifiers
|
182
184
|
marriages
|
@@ -186,7 +188,6 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
186
188
|
scout=scout{
|
187
189
|
test_association.rb
|
188
190
|
test_entity.rb
|
189
|
-
test_offsite.rb
|
190
191
|
test_semaphore.rb
|
191
192
|
test_tsv.rb
|
192
193
|
test_workflow.rb
|
@@ -248,12 +249,6 @@ scout-gear=/$PWD filter="*.rb *.yaml" {
|
|
248
249
|
test_tokyocabinet.rb
|
249
250
|
}
|
250
251
|
}
|
251
|
-
offsite=offsite{
|
252
|
-
test_ssh.rb
|
253
|
-
test_step.rb
|
254
|
-
test_sync.rb
|
255
|
-
test_task.rb
|
256
|
-
}
|
257
252
|
}
|
258
253
|
}
|
259
254
|
share=share{
|
data/Rakefile
CHANGED
@@ -12,7 +12,7 @@ Juwelier::Tasks.new do |gem|
|
|
12
12
|
gem.homepage = "http://github.com/mikisvaz/scout-gear"
|
13
13
|
gem.license = "MIT"
|
14
14
|
gem.summary = %Q{basic gear for scouts}
|
15
|
-
gem.description = %Q{
|
15
|
+
gem.description = %Q{Scout gear: workflow, TSVs, persistence, entities, associations, and knowledge_bases.}
|
16
16
|
gem.email = "mikisvaz@gmail.com"
|
17
17
|
gem.authors = ["Miguel Vazquez"]
|
18
18
|
|
@@ -26,10 +26,7 @@ Juwelier::Tasks.new do |gem|
|
|
26
26
|
gem.add_runtime_dependency 'RubyInline'
|
27
27
|
#gem.add_runtime_dependency 'tokyocabinet'
|
28
28
|
|
29
|
-
gem.add_development_dependency "rdoc", "~> 3.12"
|
30
|
-
gem.add_development_dependency "bundler", "~> 1.0"
|
31
29
|
gem.add_development_dependency "juwelier", "~> 2.1.0"
|
32
|
-
gem.add_development_dependency "simplecov", ">= 0"
|
33
30
|
end
|
34
31
|
Juwelier::RubygemsDotOrgTasks.new
|
35
32
|
|
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
|
@@ -141,7 +141,7 @@ module Association
|
|
141
141
|
new.extend Index
|
142
142
|
new
|
143
143
|
else
|
144
|
-
|
144
|
+
Open.mkdir File.dirname(reverse_filename) unless Open.exist?(File.dirname(reverse_filename))
|
145
145
|
|
146
146
|
new = Persist.open_tokyocabinet(reverse_filename, true, serializer, TokyoCabinet::BDB)
|
147
147
|
|
@@ -64,13 +64,16 @@ module Entity
|
|
64
64
|
Persist.memory("Entity index #{identity_type}: #{format} (from #{source || "All"})", :persist => true, :format => format, :source => source) do
|
65
65
|
source ||= self.respond_to?(:format)? self.format : nil
|
66
66
|
|
67
|
+
saved_exception = nil
|
67
68
|
begin
|
68
69
|
index = TSV.translation_index(identifier_files, source, format, :persist => true)
|
69
70
|
raise "No index from #{ Misc.fingerprint source } to #{ Misc.fingerprint format }: #{Misc.fingerprint identifier_files}" if index.nil?
|
70
71
|
index.unnamed = true
|
71
72
|
index
|
72
73
|
rescue
|
73
|
-
raise $! if source.nil?
|
74
|
+
raise saved_exception || $! if source.nil?
|
75
|
+
Log.debug "Retrying identifier index without specifying source"
|
76
|
+
saved_exception = $!
|
74
77
|
source = nil
|
75
78
|
retry
|
76
79
|
end
|
@@ -93,7 +96,7 @@ module Entity
|
|
93
96
|
|
94
97
|
name = default if name.nil?
|
95
98
|
|
96
|
-
self.send(:include, Entity::Identified) unless Entity::Identified
|
99
|
+
self.send(:include, Entity::Identified) unless self.include?(Entity::Identified)
|
97
100
|
|
98
101
|
self.format = all_fields
|
99
102
|
@formats ||= []
|
@@ -148,7 +148,7 @@ module Entity
|
|
148
148
|
|
149
149
|
def persist(name, type = :marshal, options = {})
|
150
150
|
options = IndiferentHash.add_defaults options, persist: true,
|
151
|
-
dir:
|
151
|
+
dir: Entity.entity_property_cache[self.to_s][name.to_s]
|
152
152
|
@persisted_methods ||= {}
|
153
153
|
@persisted_methods[name] = [type, options]
|
154
154
|
end
|
@@ -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)
|
@@ -40,7 +40,7 @@ module TSV
|
|
40
40
|
target_file = target_files.select{|file| fields = file_fields[file]; (fields & middle_fields).any? }.collect{|file,f| file }.first
|
41
41
|
[source_file, middle_file, target_file]
|
42
42
|
else
|
43
|
-
raise "Could not traverse identifier path from #{Log.fingerprint source} to #{Log.fingerprint target}
|
43
|
+
raise "Could not traverse identifier path from #{Log.fingerprint source} to #{Log.fingerprint target}. #{file_fields.empty? ? "No identifier files" : Log.fingerprint(file_fields)}"
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -55,7 +55,14 @@ module TSV
|
|
55
55
|
files = [files] unless Array === files
|
56
56
|
|
57
57
|
files.each do |file|
|
58
|
-
next if Path === file && ! Open.exist?(file)
|
58
|
+
#next if Path === file && ! Open.exist?(file)
|
59
|
+
begin
|
60
|
+
file = file.produce if Path === file
|
61
|
+
raise "Could no produce file" if FalseClass === file
|
62
|
+
rescue
|
63
|
+
Log.warn $!.message
|
64
|
+
next
|
65
|
+
end
|
59
66
|
file = file.find if Path === file
|
60
67
|
file_fields[file] = all_fields(file)
|
61
68
|
end
|
data/lib/scout/tsv/open.rb
CHANGED
@@ -151,6 +151,16 @@ module Open
|
|
151
151
|
res = block.call(line)
|
152
152
|
callback.call res if callback
|
153
153
|
end
|
154
|
+
obj.close
|
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
|
154
164
|
else
|
155
165
|
Log.low "Traverse stream with parser #{Log.fingerprint obj}"
|
156
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
|