scout-gear 7.2.0 → 8.0.0

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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/.vimproject +51 -6
  3. data/VERSION +1 -1
  4. data/bin/scout +6 -3
  5. data/lib/rbbt-scout.rb +1 -0
  6. data/lib/scout/cmd.rb +1 -1
  7. data/lib/scout/concurrent_stream.rb +33 -29
  8. data/lib/scout/config.rb +1 -1
  9. data/lib/scout/exceptions.rb +1 -0
  10. data/lib/scout/log/color.rb +4 -2
  11. data/lib/scout/log/progress/report.rb +1 -1
  12. data/lib/scout/log/progress/util.rb +71 -2
  13. data/lib/scout/log/progress.rb +1 -1
  14. data/lib/scout/log/trap.rb +107 -0
  15. data/lib/scout/log.rb +56 -21
  16. data/lib/scout/meta_extension.rb +13 -6
  17. data/lib/scout/misc/digest.rb +1 -1
  18. data/lib/scout/misc/format.rb +12 -0
  19. data/lib/scout/misc/helper.rb +31 -0
  20. data/lib/scout/misc/insist.rb +1 -1
  21. data/lib/scout/misc/monitor.rb +12 -1
  22. data/lib/scout/misc/system.rb +10 -0
  23. data/lib/scout/misc.rb +1 -0
  24. data/lib/scout/named_array.rb +65 -3
  25. data/lib/scout/open/lock/lockfile.rb +587 -0
  26. data/lib/scout/open/lock.rb +28 -2
  27. data/lib/scout/open/remote.rb +4 -0
  28. data/lib/scout/open/stream.rb +111 -42
  29. data/lib/scout/open/util.rb +13 -3
  30. data/lib/scout/path/find.rb +9 -1
  31. data/lib/scout/path/util.rb +35 -0
  32. data/lib/scout/persist/serialize.rb +18 -5
  33. data/lib/scout/persist.rb +60 -30
  34. data/lib/scout/resource/path.rb +53 -0
  35. data/lib/scout/resource/produce.rb +0 -8
  36. data/lib/scout/resource/util.rb +2 -1
  37. data/lib/scout/semaphore.rb +8 -1
  38. data/lib/scout/tmpfile.rb +7 -8
  39. data/lib/scout/tsv/attach.rb +177 -0
  40. data/lib/scout/tsv/change_id.rb +40 -0
  41. data/lib/scout/tsv/dumper.rb +85 -54
  42. data/lib/scout/tsv/index.rb +188 -20
  43. data/lib/scout/tsv/open.rb +182 -0
  44. data/lib/scout/tsv/parser.rb +200 -118
  45. data/lib/scout/tsv/path.rb +5 -6
  46. data/lib/scout/tsv/persist/adapter.rb +26 -37
  47. data/lib/scout/tsv/persist/fix_width_table.rb +327 -0
  48. data/lib/scout/tsv/persist/serialize.rb +117 -0
  49. data/lib/scout/tsv/persist/tokyocabinet.rb +6 -3
  50. data/lib/scout/tsv/persist.rb +4 -2
  51. data/lib/scout/tsv/transformer.rb +141 -0
  52. data/lib/scout/tsv/traverse.rb +136 -37
  53. data/lib/scout/tsv/util/filter.rb +312 -0
  54. data/lib/scout/tsv/util/process.rb +73 -0
  55. data/lib/scout/tsv/util/reorder.rb +81 -0
  56. data/lib/scout/tsv/util/select.rb +265 -0
  57. data/lib/scout/tsv/util/unzip.rb +86 -0
  58. data/lib/scout/tsv/util.rb +126 -19
  59. data/lib/scout/tsv.rb +28 -5
  60. data/lib/scout/work_queue/socket.rb +6 -1
  61. data/lib/scout/work_queue/worker.rb +5 -2
  62. data/lib/scout/work_queue.rb +15 -8
  63. data/lib/scout/workflow/definition.rb +29 -2
  64. data/lib/scout/workflow/step/dependencies.rb +24 -4
  65. data/lib/scout/workflow/step/info.rb +40 -5
  66. data/lib/scout/workflow/step/progress.rb +14 -0
  67. data/lib/scout/workflow/step/provenance.rb +8 -7
  68. data/lib/scout/workflow/step/status.rb +45 -0
  69. data/lib/scout/workflow/step.rb +104 -33
  70. data/lib/scout/workflow/task/inputs.rb +14 -20
  71. data/lib/scout/workflow/task.rb +86 -47
  72. data/lib/scout/workflow/usage.rb +10 -6
  73. data/scout-gear.gemspec +30 -3
  74. data/scout_commands/workflow/task +37 -9
  75. data/scout_commands/workflow/task_old +2 -2
  76. data/test/scout/open/test_stream.rb +61 -59
  77. data/test/scout/path/test_find.rb +10 -1
  78. data/test/scout/resource/test_produce.rb +15 -0
  79. data/test/scout/test_meta_extension.rb +25 -0
  80. data/test/scout/test_named_array.rb +18 -0
  81. data/test/scout/test_persist.rb +67 -0
  82. data/test/scout/test_tmpfile.rb +1 -1
  83. data/test/scout/test_tsv.rb +222 -3
  84. data/test/scout/test_work_queue.rb +21 -18
  85. data/test/scout/tsv/persist/test_adapter.rb +11 -1
  86. data/test/scout/tsv/persist/test_fix_width_table.rb +134 -0
  87. data/test/scout/tsv/persist/test_tokyocabinet.rb +29 -1
  88. data/test/scout/tsv/test_attach.rb +227 -0
  89. data/test/scout/tsv/test_change_id.rb +98 -0
  90. data/test/scout/tsv/test_dumper.rb +1 -1
  91. data/test/scout/tsv/test_index.rb +127 -3
  92. data/test/scout/tsv/test_open.rb +167 -0
  93. data/test/scout/tsv/test_parser.rb +45 -3
  94. data/test/scout/tsv/test_persist.rb +9 -0
  95. data/test/scout/tsv/test_transformer.rb +108 -0
  96. data/test/scout/tsv/test_traverse.rb +195 -3
  97. data/test/scout/tsv/test_util.rb +24 -0
  98. data/test/scout/tsv/util/test_filter.rb +188 -0
  99. data/test/scout/tsv/util/test_process.rb +47 -0
  100. data/test/scout/tsv/util/test_reorder.rb +94 -0
  101. data/test/scout/tsv/util/test_select.rb +58 -0
  102. data/test/scout/tsv/util/test_unzip.rb +112 -0
  103. data/test/scout/work_queue/test_socket.rb +0 -1
  104. data/test/scout/work_queue/test_worker.rb +63 -6
  105. data/test/scout/workflow/step/test_load.rb +3 -3
  106. data/test/scout/workflow/step/test_status.rb +31 -0
  107. data/test/scout/workflow/task/test_inputs.rb +14 -14
  108. data/test/scout/workflow/test_step.rb +13 -13
  109. data/test/scout/workflow/test_task.rb +168 -32
  110. data/test/scout/workflow/test_usage.rb +33 -6
  111. data/test/test_helper.rb +3 -1
  112. metadata +29 -2
@@ -0,0 +1,81 @@
1
+ require 'matrix'
2
+
3
+ module TSV
4
+ def reorder(key_field = nil, fields = nil, merge: true, one2one: true, **kwargs)
5
+ res = self.annotate({})
6
+ res.type = kwargs[:type] if kwargs.include?(:type)
7
+ kwargs[:one2one] = one2one
8
+ key_field_name, field_names = traverse key_field, fields, **kwargs do |k,v|
9
+ if @type == :double && merge && res.include?(k)
10
+ current = res[k]
11
+ if merge == :concat
12
+ v.each_with_index do |new,i|
13
+ next if new.empty?
14
+ current[i].concat(new)
15
+ end
16
+ else
17
+ merged = []
18
+ v.each_with_index do |new,i|
19
+ next if new.empty?
20
+ merged[i] = current[i] + new
21
+ end
22
+ res[k] = merged
23
+ end
24
+ else
25
+ res[k] = v
26
+ end
27
+ end
28
+ res.key_field = key_field_name
29
+ res.fields = field_names
30
+ res
31
+ end
32
+
33
+ def slice(fields, **kwargs)
34
+ reorder :key, fields, **kwargs
35
+ end
36
+
37
+ def column(field, **kwargs)
38
+ new_type = case type
39
+ when :double, :flat
40
+ :flat
41
+ else
42
+ :single
43
+ end
44
+
45
+ kwargs[:type] = new_type
46
+ slice(field, **kwargs)
47
+ end
48
+
49
+ def transpose_list(key_field="Unkown ID")
50
+ new_fields = keys.dup
51
+ new = self.annotate({})
52
+ TSV.setup(new, :key_field => key_field, :fields => new_fields, :type => type, :filename => filename, :identifiers => identifiers)
53
+
54
+ m = Matrix.rows values
55
+ new_rows = m.transpose.to_a
56
+
57
+ fields.zip(new_rows) do |key,row|
58
+ new[key] = row
59
+ end
60
+
61
+ new
62
+ end
63
+
64
+ def transpose_double(key_field = "Unkown ID")
65
+ sep = "-!SEP--#{rand 10000}!-"
66
+ tmp = self.to_list{|v| v * sep}
67
+ new = tmp.transpose_list(key_field)
68
+ new.to_double{|v| v.split(sep)}
69
+ end
70
+
71
+ def transpose(key_field = "Unkown ID")
72
+ case type
73
+ when :single, :flat
74
+ self.to_list.transpose_list key_field
75
+ when :list
76
+ transpose_list key_field
77
+ when :double
78
+ transpose_double key_field
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,265 @@
1
+ module TSV
2
+ def self.select(key, values, method, fields: nil, field: nil, invert: false, type: nil, sep: nil, &block)
3
+ return ! select(key, values, method, field: field, invert: false, type: type, sep: sep, &block) if invert
4
+
5
+ return yield(key, values) if method.nil? && block_given
6
+
7
+ if Hash === method
8
+ if method.include?(:invert)
9
+ method = method.dup
10
+ invert = method.delete(:invert)
11
+ return select(key, values, method, fields: fields, field: field, invert: invert, type: type, sep: sep, &block)
12
+ end
13
+ field = method.keys.first
14
+ value = method[field]
15
+ return select(key, values, value, fields: fields, field: field, invert: invert, type: type, sep: sep, &block)
16
+ end
17
+
18
+ if field
19
+ field = fields.index(field) if fields && String === field
20
+ set = field == :key ? [key] : (type == :double ? values[field].split(sep) : values[field])
21
+ else
22
+ set = [key, (type == :double ? values.collect{|v| v.split(sep) } : values)]
23
+ end
24
+
25
+ if Array === set
26
+ set.flatten!
27
+ else
28
+ set = [set]
29
+ end
30
+
31
+ case method
32
+ when Array
33
+ (method & set).any?
34
+ when Regexp
35
+ set.select{|v| v =~ method }.any?
36
+ when Symbol
37
+ set.first.send(method)
38
+ when Numeric
39
+ set.size > method
40
+ when String
41
+ if block_given?
42
+ field = method
43
+ field = fields.index?(field) if fields && String === field
44
+ case
45
+ when block.arity == 1
46
+ if (method == key_field or method == :key)
47
+ yield(key)
48
+ else
49
+ yield(values[method])
50
+ end
51
+ when block.arity == 2
52
+ if (method == key_field or method == :key)
53
+ yield(key, key)
54
+ else
55
+ yield(key, values[method])
56
+ end
57
+ end
58
+ elsif m = method.match(/^([<>]=?)(.*)/)
59
+ set.select{|v| v.to_f.send($1, $2.to_f) }.any?
60
+ else
61
+ set.select{|v| v == method }.any?
62
+ end
63
+ when Proc
64
+ set.select{|v| method.call(v) }.any?
65
+ end
66
+ end
67
+
68
+ def select(method = nil, invert = false, &block)
69
+ new = TSV.setup({}, :key_field => key_field, :fields => fields, :type => type, :filename => filename, :identifiers => identifiers)
70
+
71
+ self.annotate(new)
72
+
73
+ case
74
+ when (method.nil? and block_given?)
75
+ through do |key, values|
76
+ new[key] = values if invert ^ (yield key, values)
77
+ end
78
+ when Array === method
79
+ method = Set.new method
80
+ with_unnamed do
81
+ case type
82
+ when :single
83
+ through do |key, value|
84
+ new[key] = value if invert ^ (method.include? key or method.include? value)
85
+ end
86
+ when :list, :flat
87
+ through do |key, values|
88
+ new[key] = values if invert ^ (method.include? key or (method & values).length > 0)
89
+ end
90
+ else
91
+ through do |key, values|
92
+ new[key] = values if invert ^ (method.include? key or (method & values.flatten).length > 0)
93
+ end
94
+ end
95
+ end
96
+ when Regexp === method
97
+ with_unnamed do
98
+ through do |key, values|
99
+ new[key] = values if invert ^ ([key,values].flatten.select{|v| v =~ method}.any?)
100
+ end
101
+ end
102
+ when ((String === method) || (Symbol === method))
103
+ if block_given?
104
+ case
105
+ when block.arity == 1
106
+ with_unnamed do
107
+ case
108
+ when (method == key_field or method == :key)
109
+ through do |key, values|
110
+ new[key] = values if invert ^ (yield(key))
111
+ end
112
+ when (type == :single or type == :flat)
113
+ through do |key, value|
114
+ new[key] = value if invert ^ (yield(value))
115
+ end
116
+ else
117
+ pos = identify_field method
118
+ raise "Field #{ method } not identified. Available: #{ fields * ", " }" if pos.nil?
119
+
120
+ through do |key, values|
121
+ new[key] = values if invert ^ (yield(values[pos]))
122
+ end
123
+ end
124
+ end
125
+ when block.arity == 2
126
+ with_unnamed do
127
+ case
128
+ when (method == key_field or method == :key)
129
+ through do |key, values|
130
+ new[key] = values if invert ^ (yield(key, key))
131
+ end
132
+ when (type == :single or type == :flat)
133
+ through do |key, value|
134
+ new[key] = value if invert ^ (yield(key, value))
135
+ end
136
+ else
137
+ pos = identify_field method
138
+ through do |key, values|
139
+ new[key] = values if invert ^ (yield(key, values[pos]))
140
+ end
141
+ end
142
+
143
+ end
144
+ end
145
+
146
+ else
147
+ with_unnamed do
148
+ through do |key, values|
149
+ new[key] = values if invert ^ ([key,values].flatten.select{|v| v == method}.any?)
150
+ end
151
+ end
152
+ end
153
+ when Hash === method
154
+ key = method.keys.first
155
+ method = method.values.first
156
+ case
157
+ when ((Array === method) and (key == :key or key_field == key))
158
+ with_unnamed do
159
+ keys.each do |key|
160
+ new[key] = self[key] if invert ^ (method.include? key)
161
+ end
162
+ end
163
+ when Array === method
164
+ with_unnamed do
165
+ method = Set.new method unless Set === method
166
+ case type
167
+ when :single
168
+ through :key, key do |key, value|
169
+ new[key] = self[key] if invert ^ (method.include? value)
170
+ end
171
+ when :list
172
+ through :key, key do |key, values|
173
+ new[key] = self[key] if invert ^ (method.include? values.first)
174
+ end
175
+ when :flat #untested
176
+ through :key, key do |key, values|
177
+ new[key] = self[key] if invert ^ ((method & values.flatten).any?)
178
+ end
179
+ else
180
+ through :key, key do |key, values|
181
+ new[key] = self[key] if invert ^ ((method & values.flatten).any?)
182
+ end
183
+ end
184
+ end
185
+
186
+ when Regexp === method
187
+ with_unnamed do
188
+ through :key, key do |key, values|
189
+ values = [values] if type == :single
190
+ new[key] = self[key] if invert ^ (values.flatten.select{|v| v =~ method}.any?)
191
+ end
192
+ end
193
+
194
+ when ((String === method) and (method =~ /name:(.*)/))
195
+ name = $1
196
+ old_unnamed = self.unnamed
197
+ self.unnamed = false
198
+ if name.strip =~ /^\/(.*)\/$/
199
+ regexp = Regexp.new $1
200
+ through :key, key do |key, values|
201
+ case type
202
+ when :single
203
+ values = values.annotate([values])
204
+ when :double
205
+ values = values[0]
206
+ end
207
+ new[key] = self[key] if invert ^ (values.select{|v| v.name =~ regexp}.any?)
208
+ end
209
+ else
210
+ through :key, key do |key, values|
211
+ case type
212
+ when :single
213
+ values = values.annotate([values])
214
+ when :double
215
+ values = values[0]
216
+ end
217
+ new[key] = self[key] if invert ^ (values.select{|v| v.name == name}.any?)
218
+ end
219
+ end
220
+ self.unnamed = old_unnamed
221
+
222
+ when String === method
223
+ if method =~ /^([<>]=?)(.*)/
224
+ with_unnamed do
225
+ through :key, key do |key, values|
226
+ value = Array === values ? values.flatten.first : values
227
+ new[key] = self[key] if value.to_f.send($1, $2.to_f)
228
+ end
229
+ end
230
+ else
231
+ with_unnamed do
232
+ through :key, key do |key, values|
233
+ values = [values] if type == :single
234
+ new[key] = self[key] if invert ^ (values.flatten.select{|v| v == method}.length > 0)
235
+ end
236
+ end
237
+ end
238
+ when Numeric === method
239
+ with_unnamed do
240
+ through :key, key do |key, values|
241
+ new[key] = self[key] if invert ^ (values.flatten.length >= method)
242
+ end
243
+ end
244
+ when Proc === method
245
+ with_unnamed do
246
+ through :key, key do |key, values|
247
+ values = [values] if type == :single
248
+ new[key] = self[key] if invert ^ (values.flatten.select{|v| method.call(v)}.length > 0)
249
+ end
250
+ end
251
+ end
252
+ end
253
+ new
254
+ end
255
+
256
+ def subset(keys)
257
+ new = self.annotate({})
258
+ self.with_unnamed do
259
+ keys.each do |k|
260
+ new[k] = self[k] if self.include?(k)
261
+ end
262
+ end
263
+ new
264
+ end
265
+ end
@@ -0,0 +1,86 @@
1
+ module TSV
2
+
3
+ def self.unzip(source, field, target: nil, sep: ":", delete: true, type: :list, merge: false, one2one: true, bar: nil)
4
+ source = TSV::Parser.new source if String === source
5
+
6
+ field_pos = source.identify_field(field)
7
+ new_fields = source.fields.dup
8
+ field_name = new_fields[field_pos]
9
+ new_fields.delete_at(field_pos) if delete
10
+ new_key_field = [source.key_field, field_name] * sep
11
+ type = :double if merge
12
+
13
+ stream = target == :stream
14
+
15
+ target = case target
16
+ when :stream
17
+ TSV::Dumper.new(source.options.merge(sep: "\t"))
18
+ when nil
19
+ TSV.setup({})
20
+ else
21
+ target
22
+ end
23
+
24
+ target.fields = new_fields
25
+ target.key_field = new_key_field
26
+ target.type = type
27
+
28
+ transformer = TSV::Transformer.new source, target, unnamed: true
29
+
30
+ bar = "Unzip #{new_key_field}" if TrueClass === bar
31
+
32
+ transformer.traverse unnamed: true, one2one: one2one, bar: bar do |k,v|
33
+ if source.type == :double
34
+ if one2one
35
+ res = NamedArray.zip_fields(v).collect do |_v|
36
+ field_value = _v[field_pos]
37
+
38
+ if delete
39
+ new_values = _v.dup
40
+ new_values.delete_at field_pos
41
+ else
42
+ new_values = _v
43
+ end
44
+
45
+ new_key = [k,field_value] * sep
46
+ new_values = new_values.collect{|e| [e] } if transformer.type == :double
47
+ [new_key, new_values]
48
+ end
49
+ else
50
+ all_values = v.collect{|e| e.dup }
51
+ all_values.delete_at field_pos if delete
52
+ res = NamedArray.zip_fields(v).collect do |_v|
53
+ field_value = _v[field_pos]
54
+
55
+ new_key = [k,field_value] * sep
56
+ new_values = all_values if transformer.type == :double
57
+ [new_key, new_values]
58
+ end
59
+ end
60
+
61
+ MultipleResult.setup(res)
62
+ else
63
+ field_value = v[field_pos]
64
+
65
+ if delete
66
+ new_values = v.dup
67
+ new_values.delete_at field_pos
68
+ else
69
+ new_values = v
70
+ end
71
+
72
+ new_key = [k,field_value] * sep
73
+
74
+ new_values = new_values.collect{|e| [e] } if transformer.type == :double
75
+
76
+ [new_key, new_values]
77
+ end
78
+ end
79
+
80
+ stream ? transformer : transformer.tsv(merge: merge)
81
+ end
82
+
83
+ def unzip(*args, **kwargs)
84
+ TSV.unzip(self, *args, **kwargs)
85
+ end
86
+ end
@@ -1,24 +1,131 @@
1
1
  #require_relative '../../../modules/rbbt-util/lib/rbbt/tsv/manipulate'
2
2
  #Log.warn "USING OLD RBBT CODE: #{__FILE__}"
3
+ require_relative 'traverse'
4
+ require_relative 'util/filter'
5
+ require_relative 'util/process'
6
+ require_relative 'util/select'
7
+ require_relative 'util/reorder'
8
+ require_relative 'util/unzip'
3
9
  module TSV
4
- #[:each, :collect, :map].each do |method|
5
- # define_method(method) do |*args,&block|
6
- # super(*args) do |k,v|
7
- # NamedArray.setup(v, @fields) unless @unnamed
8
- # block.call k, v
9
- # end
10
- # end
11
- #end
12
-
13
- #[:select, :reject].each do |method|
14
- # define_method(method) do |*args,&block|
15
- # res = super(*args) do |k,v|
16
- # NamedArray.setup(v, @fields) unless @unnamed
17
- # block.call k, v
18
- # end
19
- # self.annotate(res)
20
- # res
21
- # end
22
- #end
10
+ def self.identify_field(key_field, fields, name, strict: nil)
11
+ return :key if name == :key || (! strict && NamedArray.field_match(key_field, name))
12
+ name.collect!{|n| key_field == n ? :key : n } if Array === name
13
+ NamedArray.identify_name(fields, name, strict: strict)
14
+ end
23
15
 
16
+ def identify_field(name, strict: nil)
17
+ TSV.identify_field(@key_field, @fields, name, strict: strict)
18
+ end
19
+
20
+ def [](key, *rest)
21
+ v = super(key, *rest)
22
+ NamedArray.setup(v, @fields, key) unless @unnamed || ! (Array === v)
23
+ v
24
+ end
25
+
26
+ def options
27
+ extension_attr_hash
28
+ end
29
+
30
+ def zip_new(key, values, insitu: :lax)
31
+ values = values.collect{|v| Array === v ? v : [v] } unless Array === values.first
32
+ if current_values = self[key]
33
+ if insitu == :lax
34
+ self[key] = NamedArray.add_zipped(current_values, values)
35
+ elsif insitu
36
+ NamedArray.add_zipped(current_values, values)
37
+ else
38
+ self[key] = NamedArray.add_zipped(current_values.dup, values)
39
+ end
40
+ else
41
+ if insitu && insitu != :lax
42
+ self[key] = values.dup
43
+ else
44
+ self[key] = values
45
+ end
46
+ end
47
+ end
48
+
49
+ def each(*args, &block)
50
+ if block_given?
51
+ super(*args) do |k,v|
52
+ NamedArray.setup(v, @fields) unless @unnamed || ! (Array === v)
53
+ block.call(k, v)
54
+ end
55
+ else
56
+ super(*args)
57
+ end
58
+ end
59
+
60
+ def collect(*args, &block)
61
+ if block_given?
62
+ res = []
63
+ each do |k,v|
64
+ res << yield(k, v)
65
+ end
66
+ res
67
+ else
68
+ super(*args)
69
+ end
70
+ end
71
+
72
+ def with_unnamed(unnamed = true)
73
+ begin
74
+ old_unnamed = @unnamed
75
+ @unnamed = unnamed
76
+ yield
77
+ ensure
78
+ @unnamed = old_unnamed
79
+ end
80
+ end
81
+
82
+ def summary
83
+ key = nil
84
+ values = nil
85
+ self.each do |k, v|
86
+ key = k
87
+ values = v
88
+ break
89
+ end
90
+
91
+ filename = @filename
92
+ filename = "No filename" if filename.nil? || String === filename && filename.empty?
93
+ filename.find if Path === filename
94
+ filename = File.basename(filename) + " [" + File.basename(persistence_path) + "]" if respond_to?(:persistence_path) and persistence_path
95
+
96
+ with_unnamed do
97
+ <<-EOF
98
+ Filename = #{filename}
99
+ Key field = #{key_field || "*No key field*"}
100
+ Fields = #{fields ? Log.fingerprint(fields) : "*No field info*"}
101
+ Type = #{type}
102
+ Size = #{size}
103
+ namespace = #{Log.fingerprint namespace}
104
+ identifiers = #{Log.fingerprint identifiers}
105
+ Example:
106
+ - #{key} -- #{Log.fingerprint values }
107
+ EOF
108
+ end
109
+ end
110
+
111
+ def all_fields
112
+ return [] if @fields.nil?
113
+ [@key_field] + @fields
114
+ end
115
+
116
+ def options
117
+ self.extension_attr_hash
118
+ end
119
+
120
+ def fingerprint
121
+ "TSV:{"<< Log.fingerprint(self.all_fields|| []) << ";" << Log.fingerprint(self.keys) << "}"
122
+ end
123
+
124
+ def digest_str
125
+ fingerprint
126
+ end
127
+
128
+ def inspect
129
+ fingerprint
130
+ end
24
131
  end
data/lib/scout/tsv.rb CHANGED
@@ -2,26 +2,49 @@ require_relative 'meta_extension'
2
2
  require_relative 'tsv/util'
3
3
  require_relative 'tsv/parser'
4
4
  require_relative 'tsv/dumper'
5
+ require_relative 'tsv/transformer'
5
6
  require_relative 'tsv/persist'
6
7
  require_relative 'tsv/index'
7
8
  require_relative 'tsv/path'
8
9
  require_relative 'tsv/traverse'
10
+ require_relative 'tsv/open'
11
+ require_relative 'tsv/attach'
12
+ require_relative 'tsv/change_id'
9
13
 
10
14
  module TSV
11
15
  extend MetaExtension
12
- extension_attr :key_field, :fields, :type, :filename, :namespace, :unnamed
16
+ extension_attr :key_field, :fields, :type, :filename, :namespace, :unnamed, :identifiers
17
+
18
+ def self.str2options(str)
19
+ field_options,_sep, rest = str.partition("#")
20
+ key, fields_str = field_options.split("~")
21
+
22
+ fields = fields_str.nil? ? [] : fields_str.split(/,\s*/)
23
+
24
+ rest = ":type=" << rest if rest =~ /^:?\w+$/
25
+ rest_options = rest.nil? ? {} : IndiferentHash.string2hash(rest)
26
+
27
+ {:key_field => key, :fields => fields}.merge(rest_options)
28
+ end
29
+
30
+ def self.str_setup(option_str, obj)
31
+ options = TSV.str2options(option_str)
32
+ setup(obj, options)
33
+ end
13
34
 
14
35
  def self.open(file, options = {})
15
- persist, type = IndiferentHash.process_options options, :persist, :persist_type, :persist => false, :persist_type => "HDB"
16
- Persist.persist(file, type, options.merge(:persist => persist)) do |filename|
36
+ persist, type, grep, invert_grep = IndiferentHash.process_options options, :persist, :persist_type, :grep, :invert_grep, :persist => false, :persist_type => "HDB"
37
+ type = type.to_sym if type
38
+ file = StringIO.new file if String === file && ! (Path === file) && file.index("\n")
39
+ Persist.persist(file, type, options.merge(:persist => persist, :prefix => "Tsv", :other_options => options)) do |filename|
17
40
  data = filename ? ScoutCabinet.open(filename, true, type) : nil
18
41
  options[:data] = data if data
19
42
  options[:filename] = file
20
- Open.open(file) do |f|
43
+ Log.debug "TSV open #{Log.fingerprint file}"
44
+ Open.open(file, grep: grep, invert_grep: invert_grep) do |f|
21
45
  TSV.parse(f, **options)
22
46
  end
23
47
  end
24
48
  end
25
-
26
49
  end
27
50
 
@@ -3,7 +3,7 @@ require 'scout/semaphore'
3
3
  require 'scout/exceptions'
4
4
  class WorkQueue
5
5
  class Socket
6
- attr_accessor :sread, :swrite, :write_sem, :read_sem, :cleaned
6
+ attr_accessor :sread, :swrite, :write_sem, :read_sem, :cleaned, :exception
7
7
  def initialize(serializer = nil)
8
8
  @sread, @swrite = Open.pipe
9
9
 
@@ -112,6 +112,11 @@ class WorkQueue
112
112
  end
113
113
  end
114
114
 
115
+ def abort(exception)
116
+ @exception = exception
117
+ @swrite.close unless closed_write?
118
+ end
119
+
115
120
  alias write push
116
121
 
117
122
  alias read pop
@@ -27,8 +27,10 @@ class WorkQueue
27
27
  rescue Interrupt
28
28
  rescue Exception
29
29
  output.write WorkerException.new($!, Process.pid)
30
- exit -1
30
+ Process.exit! -1
31
+ ensure
31
32
  end
33
+ Process.exit! 0
32
34
  end
33
35
  end
34
36
 
@@ -36,7 +38,8 @@ class WorkQueue
36
38
  begin
37
39
  Log.debug "Aborting worker #{@pid}"
38
40
  Process.kill "INT", @pid
39
- rescue Errno::ECHILD
41
+ rescue Errno::ECHILD
42
+ rescue Errno::ESRCH
40
43
  end
41
44
  end
42
45