rbbt-util 5.4.1 → 5.5.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.
- checksums.yaml +8 -8
- data/bin/rbbt_monitor.rb +8 -4
- data/lib/rbbt.rb +4 -11
- data/lib/rbbt/annotations.rb +4 -1
- data/lib/rbbt/association.rb +218 -157
- data/lib/rbbt/association/index.rb +92 -0
- data/lib/rbbt/association/item.rb +44 -0
- data/lib/rbbt/entity.rb +4 -0
- data/lib/rbbt/fix_width_table.rb +14 -9
- data/lib/rbbt/knowledge_base.rb +269 -0
- data/lib/rbbt/persist.rb +1 -1
- data/lib/rbbt/persist/tsv.rb +22 -2
- data/lib/rbbt/resource.rb +0 -1
- data/lib/rbbt/resource/path.rb +1 -1
- data/lib/rbbt/resource/util.rb +0 -1
- data/lib/rbbt/tsv.rb +15 -14
- data/lib/rbbt/tsv/accessor.rb +21 -16
- data/lib/rbbt/tsv/attach.rb +5 -5
- data/lib/rbbt/tsv/attach/util.rb +4 -2
- data/lib/rbbt/tsv/change_id.rb +67 -0
- data/lib/rbbt/tsv/index.rb +5 -3
- data/lib/rbbt/tsv/manipulate.rb +83 -37
- data/lib/rbbt/tsv/parser.rb +2 -1
- data/lib/rbbt/tsv/util.rb +2 -0
- data/lib/rbbt/util/cmd.rb +1 -2
- data/lib/rbbt/util/log.rb +42 -38
- data/lib/rbbt/util/misc.rb +134 -46
- data/lib/rbbt/util/open.rb +3 -17
- data/lib/rbbt/util/semaphore.rb +8 -2
- data/lib/rbbt/workflow.rb +31 -46
- data/lib/rbbt/workflow/accessor.rb +1 -1
- data/lib/rbbt/workflow/step.rb +5 -3
- data/share/rbbt_commands/workflow/server +1 -0
- data/share/rbbt_commands/workflow/task +12 -2
- data/test/rbbt/association/test_index.rb +36 -0
- data/test/rbbt/test_annotations.rb +5 -4
- data/test/rbbt/test_association.rb +40 -13
- data/test/rbbt/test_knowledge_base.rb +103 -0
- data/test/rbbt/test_workflow.rb +4 -2
- data/test/rbbt/tsv/test_change_id.rb +43 -0
- data/test/rbbt/tsv/test_index.rb +2 -1
- data/test/rbbt/tsv/test_manipulate.rb +51 -0
- data/test/rbbt/util/test_misc.rb +21 -1
- data/test/test_helper.rb +8 -4
- metadata +12 -86
data/lib/rbbt/persist.rb
CHANGED
@@ -43,7 +43,7 @@ module Persist
|
|
43
43
|
|
44
44
|
def self.persistence_path(file, persist_options = {}, options = {})
|
45
45
|
persistence_file = Misc.process_options persist_options, :file
|
46
|
-
return persistence_file
|
46
|
+
return persistence_file unless persistence_file.nil?
|
47
47
|
|
48
48
|
prefix = Misc.process_options persist_options, :prefix
|
49
49
|
|
data/lib/rbbt/persist/tsv.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'tokyocabinet'
|
3
|
+
rescue Exception
|
4
|
+
Log.warn "The tokyocabinet gem could not be loaded: persistence over TSV files will fail"
|
5
|
+
end
|
2
6
|
|
3
7
|
module Persist
|
4
8
|
TC_CONNECTIONS = {}
|
@@ -85,6 +89,20 @@ module Persist
|
|
85
89
|
out(key)
|
86
90
|
end
|
87
91
|
|
92
|
+
def write_and_read
|
93
|
+
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
94
|
+
Misc.lock(lock_filename) do
|
95
|
+
write if @closed or not write?
|
96
|
+
res = begin
|
97
|
+
yield
|
98
|
+
ensure
|
99
|
+
read
|
100
|
+
end
|
101
|
+
res
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
88
106
|
def write_and_close
|
89
107
|
lock_filename = Persist.persistence_path(persistence_path, {:dir => TSV.lock_dir})
|
90
108
|
Misc.lock(lock_filename) do
|
@@ -148,10 +166,12 @@ module Persist
|
|
148
166
|
filename ||= case
|
149
167
|
when Path === source
|
150
168
|
source
|
151
|
-
when source.respond_to?(:filename)
|
169
|
+
when (source.respond_to?(:filename) and source.filename)
|
152
170
|
source.filename
|
153
171
|
when source.respond_to?(:cmd)
|
154
172
|
"CMD-#{Misc.digest(source.cmd)}"
|
173
|
+
when TSV === source
|
174
|
+
"TSV[#{Misc.digest Misc.fingerprint(source)}]"
|
155
175
|
else
|
156
176
|
source.object_id.to_s
|
157
177
|
end
|
data/lib/rbbt/resource.rb
CHANGED
data/lib/rbbt/resource/path.rb
CHANGED
data/lib/rbbt/resource/util.rb
CHANGED
data/lib/rbbt/tsv.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
require '
|
1
|
+
require 'rbbt/persist'
|
2
|
+
require 'rbbt/persist/tsv'
|
2
3
|
|
4
|
+
require 'rbbt/util/log'
|
3
5
|
require 'rbbt/util/misc'
|
4
6
|
require 'rbbt/util/named_array'
|
5
|
-
require 'rbbt/util/log'
|
6
|
-
|
7
|
-
require 'rbbt/persist'
|
8
7
|
|
9
8
|
require 'rbbt/tsv/util'
|
10
9
|
require 'rbbt/tsv/serializers'
|
@@ -36,6 +35,8 @@ module TSV
|
|
36
35
|
hash.send("#{ entry }=", options[entry.to_sym]) if options.include? entry.to_sym
|
37
36
|
end
|
38
37
|
|
38
|
+
hash.unnamed = options[:unnamed]
|
39
|
+
|
39
40
|
hash
|
40
41
|
end
|
41
42
|
|
@@ -95,17 +96,19 @@ module TSV
|
|
95
96
|
stream.open do |f|
|
96
97
|
Parser.new f, options
|
97
98
|
end
|
98
|
-
when (String === stream and stream.length < 300 and Open.exists? stream)
|
99
|
+
when (String === stream and stream.length < 300 and Open.exists? stream or Open.remote? stream)
|
99
100
|
Open.open(stream) do |f|
|
100
101
|
Parser.new f, options
|
101
102
|
end
|
102
103
|
else
|
104
|
+
filename = stream.respond_to?(:filename) ? stream.filename : Misc.fingerprint(stream)
|
105
|
+
Log.debug("Parsing header of open stream: #{filename}")
|
103
106
|
Parser.new stream, options
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
107
110
|
def self.parse(stream, data, options = {})
|
108
|
-
monitor, grep, invert_grep = Misc.process_options options, :monitor, :grep, :invert_grep
|
111
|
+
monitor, grep, invert_grep, head = Misc.process_options options, :monitor, :grep, :invert_grep, :head
|
109
112
|
|
110
113
|
parser = Parser.new stream, options
|
111
114
|
|
@@ -117,19 +120,14 @@ module TSV
|
|
117
120
|
|
118
121
|
line = parser.rescue_first_line
|
119
122
|
|
120
|
-
if TokyoCabinet::HDB === data and parser.straight
|
123
|
+
if TokyoCabinet::HDB === data and parser.straight and
|
121
124
|
data.close
|
122
|
-
pos = stream.pos if stream.respond_to? :pos
|
123
125
|
begin
|
126
|
+
CMD.cmd('tchmgr', :log => false)
|
127
|
+
FileUtils.mkdir_p File.dirname(data.persistence_path)
|
124
128
|
CMD.cmd("tchmgr importtsv '#{data.persistence_path}'", :in => stream, :log => false, :dont_close_in => true)
|
125
129
|
rescue
|
126
130
|
Log.debug("tchmgr importtsv failed for: #{data.persistence_path}")
|
127
|
-
Log.debug($!.message)
|
128
|
-
if stream.respond_to? :seek
|
129
|
-
stream.seek pos
|
130
|
-
else
|
131
|
-
#raise "tchmgr import failed and cannot restore stream"
|
132
|
-
end
|
133
131
|
end
|
134
132
|
data.write
|
135
133
|
end
|
@@ -170,6 +168,7 @@ module TSV
|
|
170
168
|
progress_monitor = nil
|
171
169
|
end
|
172
170
|
|
171
|
+
line_num = 1
|
173
172
|
while not line.nil?
|
174
173
|
begin
|
175
174
|
progress_monitor.tick(stream.pos) if progress_monitor
|
@@ -183,6 +182,8 @@ module TSV
|
|
183
182
|
values = parser.cast_values values if parser.cast?
|
184
183
|
parser.add_to_data data, key, values
|
185
184
|
line = stream.gets
|
185
|
+
line_num += 1
|
186
|
+
raise Parser::END_PARSING if head and line_num > head.to_i
|
186
187
|
rescue Parser::SKIP_LINE
|
187
188
|
begin
|
188
189
|
line = stream.gets
|
data/lib/rbbt/tsv/accessor.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
#require 'rbbt/util/chain_methods'
|
2
1
|
require 'yaml'
|
3
2
|
module TSV
|
4
3
|
#extend ChainMethods
|
@@ -35,7 +34,6 @@ module TSV
|
|
35
34
|
return entity if entity.nil?
|
36
35
|
return entity unless defined? Entity
|
37
36
|
entity = entity if options.delete :dup_array
|
38
|
-
entity_templates
|
39
37
|
if (template = entity_templates[field])
|
40
38
|
entity = template.annotate(entity.frozen? ? entity.dup : entity)
|
41
39
|
entity.extend AnnotatedArray if Array === entity
|
@@ -263,7 +261,7 @@ module TSV
|
|
263
261
|
end
|
264
262
|
when :list, :flat
|
265
263
|
through :key, field do |key, fields|
|
266
|
-
elems << [key, fields]
|
264
|
+
elems << [key, fields.first]
|
267
265
|
end
|
268
266
|
when :double
|
269
267
|
through :key, field do |key, fields|
|
@@ -481,19 +479,22 @@ end
|
|
481
479
|
|
482
480
|
|
483
481
|
def all_fields
|
482
|
+
return nil if key_field.nil? or fields.nil?
|
484
483
|
[key_field] + fields
|
485
484
|
end
|
486
485
|
|
487
486
|
def values_to_s(values)
|
488
|
-
case
|
489
|
-
when
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
487
|
+
case values
|
488
|
+
when nil
|
489
|
+
if fields.nil? or fields.empty?
|
490
|
+
"\n"
|
491
|
+
else
|
492
|
+
"\t" << ([""] * fields.length) * "\t" << "\n"
|
493
|
+
end
|
494
|
+
when Array
|
496
495
|
"\t" << values.collect{|v| Array === v ? v * "|" : v} * "\t" << "\n"
|
496
|
+
else
|
497
|
+
"\t" << values.to_s << "\n"
|
497
498
|
end
|
498
499
|
end
|
499
500
|
|
@@ -541,14 +542,18 @@ end
|
|
541
542
|
end
|
542
543
|
|
543
544
|
def summary
|
544
|
-
|
545
|
-
|
546
|
-
|
545
|
+
with_unnamed do
|
546
|
+
<<-EOF
|
547
|
+
Key field = #{key_field || "*No key field*"}
|
548
|
+
Fields = #{fields ? Misc.fingerprint(fields) : "*No field info*"}
|
547
549
|
Type = #{type}
|
550
|
+
Size = #{size}
|
551
|
+
namespace = #{namespace}
|
548
552
|
Example:
|
549
|
-
- #{key = keys.first}: #{self[key]
|
553
|
+
- #{key = keys.first}: #{Misc.fingerprint self[key] }
|
550
554
|
|
551
|
-
|
555
|
+
EOF
|
556
|
+
end
|
552
557
|
end
|
553
558
|
|
554
559
|
def to_hash
|
data/lib/rbbt/tsv/attach.rb
CHANGED
@@ -144,9 +144,9 @@ module TSV
|
|
144
144
|
in_namespace = options[:in_namespace]
|
145
145
|
|
146
146
|
unless TSV === other
|
147
|
-
|
147
|
+
other_identifier_file = other.identifier_files.first if other.respond_to? :identifier_files
|
148
148
|
other = TSV.open(other, :persist => options[:persist_input] == true)
|
149
|
-
other.identifiers =
|
149
|
+
other.identifiers = other_identifier_file
|
150
150
|
end
|
151
151
|
|
152
152
|
fields = other.fields - [key_field].concat(self.fields) if fields.nil? or fields == :all
|
@@ -157,10 +157,10 @@ module TSV
|
|
157
157
|
end
|
158
158
|
|
159
159
|
other_filename = other.respond_to?(:filename) ? other.filename : other.inspect
|
160
|
-
Log.low("Attaching fields:#{fields
|
160
|
+
Log.low("Attaching fields:#{Misc.fingerprint fields } from #{other_filename}.")
|
161
161
|
|
162
162
|
case
|
163
|
-
when key_field == other.key_field
|
163
|
+
when key_field == other.key_field
|
164
164
|
Log.debug "Attachment with same key: #{other.key_field}"
|
165
165
|
attach_same_key other, fields
|
166
166
|
when (not in_namespace and self.fields.include?(other.key_field))
|
@@ -175,7 +175,7 @@ module TSV
|
|
175
175
|
Log.debug "Attachment with index: #{other.key_field}"
|
176
176
|
attach_index other, index, fields
|
177
177
|
end
|
178
|
-
Log.debug("Attachment of fields:#{fields
|
178
|
+
Log.debug("Attachment of fields:#{Misc.fingerprint fields } from #{other.filename.inspect} finished.")
|
179
179
|
|
180
180
|
self
|
181
181
|
end
|
data/lib/rbbt/tsv/attach/util.rb
CHANGED
@@ -36,7 +36,7 @@ module TSV
|
|
36
36
|
if type == :double
|
37
37
|
self[key] = current.concat [[]] * fields.length
|
38
38
|
else
|
39
|
-
self[key] = current.concat [
|
39
|
+
self[key] = current.concat [nil] * fields.length
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
@@ -46,6 +46,8 @@ module TSV
|
|
46
46
|
self.type = :list if self.type == :single
|
47
47
|
|
48
48
|
self.fields = self.fields.concat fields
|
49
|
+
|
50
|
+
self
|
49
51
|
end
|
50
52
|
|
51
53
|
def attach_source_key(other, source, options = {})
|
@@ -169,7 +171,7 @@ module TSV
|
|
169
171
|
if type == :double
|
170
172
|
all_new_values = [[[]] * field_positions.length]
|
171
173
|
else
|
172
|
-
all_new_values = [[
|
174
|
+
all_new_values = [[nil] * field_positions.length]
|
173
175
|
end
|
174
176
|
end
|
175
177
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rbbt/tsv'
|
2
|
+
|
3
|
+
module TSV
|
4
|
+
def self.change_key(tsv, format, options = {})
|
5
|
+
options = Misc.add_defaults options, :persist => false, :identifiers => tsv.identifiers
|
6
|
+
|
7
|
+
identifiers, persist_input = Misc.process_options options, :identifiers, :persist_input
|
8
|
+
|
9
|
+
if not tsv.fields.include? format
|
10
|
+
tsv = tsv.annotate(Hash[*tsv.keys.zip(tsv.values.collect{|l| l.dup}).flatten(1)])
|
11
|
+
|
12
|
+
orig_type = tsv.type
|
13
|
+
tsv = tsv.to_double if orig_type != :double
|
14
|
+
|
15
|
+
tsv = tsv.attach identifiers, :fields => [format], :persist_input => true
|
16
|
+
tsv = tsv.reorder(format, tsv.fields - [format])
|
17
|
+
|
18
|
+
tsv = tsv.to_flat if orig_type == :flat
|
19
|
+
|
20
|
+
tsv
|
21
|
+
else
|
22
|
+
tsv.reorder(format)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def change_key(*args)
|
27
|
+
TSV.change_key(self, *args)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.swap_id(tsv, field, format, options = {})
|
31
|
+
options = Misc.add_defaults options, :persist => false, :identifiers => tsv.identifiers
|
32
|
+
|
33
|
+
identifiers, persist_input = Misc.process_options options, :identifiers, :persist
|
34
|
+
|
35
|
+
index = identifiers.index :target => format, :fields => [field], :persist => persist_input
|
36
|
+
|
37
|
+
orig_type = tsv.type
|
38
|
+
tsv = tsv.to_double if orig_type != :double
|
39
|
+
|
40
|
+
pos = tsv.fields.index field
|
41
|
+
tsv.with_unnamed do
|
42
|
+
if tsv.type == :list or tsv.type == :single
|
43
|
+
tsv.through do |k,v|
|
44
|
+
v[pos] = index[v[pos]]
|
45
|
+
tsv[k] = v
|
46
|
+
end
|
47
|
+
else
|
48
|
+
tsv.through do |k,v|
|
49
|
+
v[pos] = index.values_at(*v[pos])
|
50
|
+
tsv[k] = v
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
tsv.fields = tsv.fields.collect{|f| f == field ? format : f}
|
55
|
+
end
|
56
|
+
|
57
|
+
tsv = tsv.to_flat if orig_type == :flat
|
58
|
+
|
59
|
+
tsv
|
60
|
+
end
|
61
|
+
|
62
|
+
def swap_id(*args)
|
63
|
+
TSV.swap_id(self, *args)
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
end
|
data/lib/rbbt/tsv/index.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
require 'rbbt/util/misc'
|
2
1
|
require 'rbbt/fix_width_table'
|
2
|
+
require 'rbbt/util/misc'
|
3
|
+
|
4
|
+
require 'rbbt/persist'
|
5
|
+
require 'rbbt/persist/tsv'
|
6
|
+
|
3
7
|
require 'rbbt/tsv/manipulate'
|
4
8
|
require 'rbbt/tsv/filter'
|
5
|
-
require 'rbbt/persist/tsv'
|
6
|
-
require 'rbbt/persist'
|
7
9
|
|
8
10
|
module TSV
|
9
11
|
|
data/lib/rbbt/tsv/manipulate.rb
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
require 'progress-bar'
|
2
|
-
require 'rbbt/persist'
|
3
|
-
require 'rbbt/tsv/util'
|
4
|
-
require 'set'
|
5
2
|
|
6
3
|
module TSV
|
7
4
|
|
@@ -59,6 +56,7 @@ module TSV
|
|
59
56
|
[key] : values[field] }.flatten
|
60
57
|
]
|
61
58
|
end
|
59
|
+
|
62
60
|
def initialize(key_field, fields, new_key_field, new_fields, type, uniq)
|
63
61
|
@new_key_field = TSV.identify_field(key_field, fields, new_key_field)
|
64
62
|
|
@@ -235,28 +233,55 @@ module TSV
|
|
235
233
|
persist_options[:prefix] = "Reorder"
|
236
234
|
|
237
235
|
Persist.persist_tsv self, self.filename, {:key_field => new_key_field, :fields => new_fields}, persist_options do |data|
|
236
|
+
if data.respond_to? :persistence_path
|
237
|
+
real_data = data
|
238
|
+
data = {}
|
239
|
+
end
|
238
240
|
|
239
241
|
with_unnamed do
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
242
|
+
if zipped or (type != :double and type != :flat)
|
243
|
+
new_key_field_name, new_field_names = through new_key_field, new_fields, uniq, zipped do |key, value|
|
244
|
+
data[key] = value.clone if Array === value
|
245
|
+
end
|
246
|
+
else
|
247
|
+
case type
|
248
|
+
when :double
|
249
|
+
new_key_field_name, new_field_names = through new_key_field, new_fields, uniq, zipped do |key, value|
|
250
|
+
if data[key].nil?
|
251
|
+
#data[key] = value.collect{|v| v.dup}
|
252
|
+
data[key] = value.collect{|v| v.dup}
|
253
|
+
else
|
254
|
+
current = data[key]
|
255
|
+
value.each_with_index do |v, i|
|
256
|
+
current[i].concat v
|
257
|
+
end
|
258
|
+
data[key] = current if data.respond_to? :tokyocabinet_class
|
259
|
+
end
|
260
|
+
end
|
261
|
+
when :flat
|
262
|
+
new_key_field_name, new_field_names = through new_key_field, new_fields, uniq, zipped do |key, value|
|
263
|
+
data[key] ||= []
|
246
264
|
data[key].concat value
|
247
265
|
end
|
248
|
-
else
|
249
|
-
data[key] = value.dup
|
250
266
|
end
|
251
267
|
end
|
252
268
|
|
269
|
+
if real_data and real_data.respond_to? :persistence_path
|
270
|
+
real_data.serializer = type if real_data.respond_to? :serializer
|
271
|
+
real_data.merge!(data)
|
272
|
+
data = real_data
|
273
|
+
end
|
274
|
+
|
253
275
|
data.extend TSV unless TSV === data
|
254
276
|
data.key_field = new_key_field_name
|
255
277
|
data.fields = new_field_names
|
256
278
|
data.filename = filename
|
257
279
|
data.namespace = namespace
|
258
280
|
data.entity_options = entity_options
|
259
|
-
data.entity_templates =
|
281
|
+
data.entity_templates = {}
|
282
|
+
data.fields.each do |field|
|
283
|
+
data.entity_templates[field] = entity_templates[field] if entity_templates.include? field
|
284
|
+
end
|
260
285
|
data.type = zipped ? :list : type
|
261
286
|
end
|
262
287
|
end
|
@@ -289,7 +314,7 @@ module TSV
|
|
289
314
|
elems.sort_by{|k,v| v}.collect{|k,v| k}
|
290
315
|
end
|
291
316
|
|
292
|
-
def select(method = nil, &block)
|
317
|
+
def select(method = nil, invert = false, &block)
|
293
318
|
new = TSV.setup({}, :key_field => key_field, :fields => fields, :type => type, :filename => filename, :identifiers => identifiers)
|
294
319
|
|
295
320
|
new.key_field = key_field
|
@@ -303,7 +328,7 @@ module TSV
|
|
303
328
|
case
|
304
329
|
when (method.nil? and block_given?)
|
305
330
|
through do |key, values|
|
306
|
-
new[key] = values if yield key, values
|
331
|
+
new[key] = values if invert ^ (yield key, values)
|
307
332
|
end
|
308
333
|
when Array === method
|
309
334
|
method = Set.new method
|
@@ -311,22 +336,22 @@ module TSV
|
|
311
336
|
case type
|
312
337
|
when :single
|
313
338
|
through do |key, value|
|
314
|
-
new[key] = value if method.include? key or method.include? value
|
339
|
+
new[key] = value if invert ^ (method.include? key or method.include? value)
|
315
340
|
end
|
316
341
|
when :list, :flat
|
317
342
|
through do |key, values|
|
318
|
-
new[key] = values if method.include? key or (method & values).any?
|
343
|
+
new[key] = values if invert ^ (method.include? key or (method & values).any?)
|
319
344
|
end
|
320
345
|
else
|
321
346
|
through do |key, values|
|
322
|
-
new[key] = values if method.include? key or (method & values.flatten).any?
|
347
|
+
new[key] = values if invert ^ (method.include? key or (method & values.flatten).any?)
|
323
348
|
end
|
324
349
|
end
|
325
350
|
end
|
326
351
|
when Regexp === method
|
327
352
|
with_unnamed do
|
328
353
|
through do |key, values|
|
329
|
-
new[key] = values if [key,values].flatten.select{|v| v =~ method}.any?
|
354
|
+
new[key] = values if invert ^ ([key,values].flatten.select{|v| v =~ method}.any?)
|
330
355
|
end
|
331
356
|
end
|
332
357
|
when String === method
|
@@ -337,18 +362,18 @@ module TSV
|
|
337
362
|
case
|
338
363
|
when (method == key_field or method == :key)
|
339
364
|
through do |key, values|
|
340
|
-
new[key] = values if yield(key)
|
365
|
+
new[key] = values if invert ^ (yield(key))
|
341
366
|
end
|
342
367
|
when (type == :single or type == :flat)
|
343
368
|
through do |key, value|
|
344
|
-
new[key] = value if yield(value)
|
369
|
+
new[key] = value if invert ^ (yield(value))
|
345
370
|
end
|
346
371
|
else
|
347
372
|
pos = identify_field method
|
348
373
|
raise "Field #{ method } not identified. Available: #{ fields * ", " }" if pos.nil?
|
349
374
|
|
350
375
|
through do |key, values|
|
351
|
-
new[key] = values if yield(values[pos])
|
376
|
+
new[key] = values if invert ^ (yield(values[pos]))
|
352
377
|
end
|
353
378
|
end
|
354
379
|
end
|
@@ -357,28 +382,26 @@ module TSV
|
|
357
382
|
case
|
358
383
|
when (method == key_field or method == :key)
|
359
384
|
through do |key, values|
|
360
|
-
new[key] = values if yield(key, key)
|
385
|
+
new[key] = values if invert ^ (yield(key, key))
|
361
386
|
end
|
362
387
|
when (type == :single or type == :flat)
|
363
388
|
through do |key, value|
|
364
|
-
new[key] = value if yield(key, value)
|
389
|
+
new[key] = value if invert ^ (yield(key, value))
|
365
390
|
end
|
366
391
|
else
|
367
392
|
pos = identify_field method
|
368
393
|
through do |key, values|
|
369
|
-
new[key] = values if yield(key, values[pos])
|
394
|
+
new[key] = values if invert ^ (yield(key, values[pos]))
|
370
395
|
end
|
371
396
|
end
|
372
397
|
|
373
398
|
end
|
374
|
-
|
375
399
|
end
|
376
400
|
|
377
|
-
|
378
401
|
else
|
379
402
|
with_unnamed do
|
380
403
|
through do |key, values|
|
381
|
-
new[key] = values if [key,values].flatten.select{|v| v == method}.any?
|
404
|
+
new[key] = values if invert ^ ([key,values].flatten.select{|v| v == method}.any?)
|
382
405
|
end
|
383
406
|
end
|
384
407
|
end
|
@@ -389,7 +412,7 @@ module TSV
|
|
389
412
|
when (Array === method and (key == :key or key_field == key))
|
390
413
|
with_unnamed do
|
391
414
|
method.each{|key|
|
392
|
-
new[key] = self[key] if self.include? key
|
415
|
+
new[key] = self[key] if invert ^ (self.include? key)
|
393
416
|
}
|
394
417
|
end
|
395
418
|
when Array === method
|
@@ -398,45 +421,68 @@ module TSV
|
|
398
421
|
case type
|
399
422
|
when :single
|
400
423
|
through :key, key do |key, value|
|
401
|
-
new[key] = self[key] if method.include? value
|
424
|
+
new[key] = self[key] if invert ^ (method.include? value)
|
402
425
|
end
|
403
426
|
when :list
|
404
427
|
through :key, key do |key, values|
|
405
|
-
new[key] = self[key] if method.include? values.first
|
428
|
+
new[key] = self[key] if invert ^ (method.include? values.first)
|
406
429
|
end
|
407
430
|
when :flat #untested
|
408
431
|
through :key, key do |key, values|
|
409
|
-
new[key] = self[key] if (method & values.flatten).any?
|
432
|
+
new[key] = self[key] if invert ^ ((method & values.flatten).any?)
|
410
433
|
end
|
411
434
|
else
|
412
435
|
through :key, key do |key, values|
|
413
|
-
new[key] = self[key] if (method & values.flatten).any?
|
436
|
+
new[key] = self[key] if invert ^ ((method & values.flatten).any?)
|
414
437
|
end
|
415
438
|
end
|
416
439
|
end
|
440
|
+
|
417
441
|
when Regexp === method
|
418
442
|
with_unnamed do
|
419
443
|
through :key, key do |key, values|
|
420
444
|
values = [values] if type == :single
|
421
|
-
new[key] = self[key] if values.flatten.select{|v| v =~ method}.any?
|
445
|
+
new[key] = self[key] if invert ^ (values.flatten.select{|v| v =~ method}.any?)
|
422
446
|
end
|
423
447
|
end
|
448
|
+
|
449
|
+
when (String === method and method =~ /name:(.*)/)
|
450
|
+
name = $1
|
451
|
+
if name.strip =~ /^\/(.*)\/$/
|
452
|
+
regexp = Regexp.new $1
|
453
|
+
through :key, key do |key, values|
|
454
|
+
values = [values] if type == :single
|
455
|
+
new[key] = self[key] if invert ^ (values.flatten.select{|v| v.name =~ regexp}.any?)
|
456
|
+
end
|
457
|
+
else
|
458
|
+
through :key, key do |key, values|
|
459
|
+
values = [values] if type == :single
|
460
|
+
new[key] = self[key] if invert ^ (values.flatten.select{|v| v.name == name}.any?)
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
424
464
|
when String === method
|
425
465
|
with_unnamed do
|
426
466
|
through :key, key do |key, values|
|
427
467
|
values = [values] if type == :single
|
428
|
-
new[key] = self[key] if values.flatten.select{|v| v == method}.any?
|
468
|
+
new[key] = self[key] if invert ^ (values.flatten.select{|v| v == method}.any?)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
when Fixnum === method
|
473
|
+
with_unnamed do
|
474
|
+
through :key, key do |key, values|
|
475
|
+
new[key] = self[key] if invert ^ (values.flatten.length >= method)
|
429
476
|
end
|
430
477
|
end
|
431
478
|
when Proc === method
|
432
479
|
with_unnamed do
|
433
480
|
through :key, key do |key, values|
|
434
481
|
values = [values] if type == :single
|
435
|
-
new[key] = self[key] if values.flatten.select{|v| method.call(v)}.any?
|
482
|
+
new[key] = self[key] if invert ^ (values.flatten.select{|v| method.call(v)}.any?)
|
436
483
|
end
|
437
484
|
end
|
438
485
|
end
|
439
|
-
|
440
486
|
end
|
441
487
|
|
442
488
|
new
|
@@ -538,7 +584,7 @@ module TSV
|
|
538
584
|
values = [new_values]
|
539
585
|
when values.nil?
|
540
586
|
values = [nil] * fields.length + [new_values]
|
541
|
-
when
|
587
|
+
when Array === values
|
542
588
|
values += [new_values]
|
543
589
|
else
|
544
590
|
values << new_values
|