rbbt-util 5.26.169 → 5.26.170

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9518793ebcf5bad66987d7d3c57627708a5821eb6b9680b3e26be2c7ef210360
4
- data.tar.gz: 8fabc19346ad08c78f898d1e377c652b38b71edfe51a81f831fc14f114cb78a4
3
+ metadata.gz: ec58135152ab8da64225ec6ee2c82630300f745e9a97da8bfbce6d1286792f28
4
+ data.tar.gz: 7ddc25495f7f37536aac591c645095acd176f36dcb68c7e2f24f53d8a8ad7354
5
5
  SHA512:
6
- metadata.gz: 7c5b12556e4c8b4b844982378c7478916b2f6cef846c9f0f864405c1753440688593b9c0ce767ae01c32c0f5708df6fe09f0e8eb147037d098f3d029220fe972
7
- data.tar.gz: 8be6d8482a4a1ce953f9fe9a73d66318a7dd0e2e7c03d665a1ccfaf43165239ea37c0823eace9448051d646cd2d493219aefbaf404633c5edbd2271d132cace7
6
+ metadata.gz: 11bd33815e5d784ef4c2fe8dca4580a6896a76aaa14fd7e67251ceb193e46472e25d292e5fec23116a39afe15c3951b83cd9696a3050b669c60ee7af6fd759bd
7
+ data.tar.gz: 87d3e4dfbf4286c8303b9bedd83462c5cb6f276802fd54068c9628a64bcff5d4a6cbde520de9495763f4cf008acc8465b1d4df1cc2955bdfe99c34cd42c9ae40
@@ -71,7 +71,7 @@ module Persist
71
71
  lock_filename = Persist.persistence_path(persistence_path + '.write', {:dir => TSV.lock_dir})
72
72
  #mutex.synchronize do
73
73
  Misc.lock(lock_filename, true) do
74
- write if closed? or not write?
74
+ write if closed? || ! write?
75
75
  res = begin
76
76
  yield
77
77
  rescue Exception
@@ -86,7 +86,7 @@ module Persist
86
86
  end
87
87
 
88
88
  def read_and_close
89
- read if closed? or not read?
89
+ read if closed? || ! read?
90
90
  res = begin
91
91
  yield
92
92
  ensure
@@ -106,5 +106,10 @@ module Persist
106
106
  def range(*args)
107
107
  super(*args) #- TSV::ENTRY_KEYS.to_a
108
108
  end
109
+
110
+ def include?(*args)
111
+ read if closed?
112
+ super(*args) #- TSV::ENTRY_KEYS.to_a
113
+ end
109
114
  end
110
115
  end
@@ -7,20 +7,23 @@ module Persist
7
7
 
8
8
  attr_accessor :tokyocabinet_class
9
9
 
10
- def self.open(path, write, serializer, tokyocabinet_class = TokyoCabinet::HDB)
11
- if String === tokyocabinet_class and tokyocabinet_class.include? ":big"
10
+ def self.open(path, write, tokyocabinet_class = TokyoCabinet::HDB)
11
+ if String === tokyocabinet_class && tokyocabinet_class.include?(":big")
12
12
  big = true
13
13
  tokyocabinet_class = tokyocabinet_class.split(":").first
14
14
  else
15
15
  big = false
16
16
  end
17
17
 
18
+ dir = File.dirname(File.expand_path(path))
19
+ Open.mkdir(dir) unless Open.exists?(dir)
20
+
18
21
  tokyocabinet_class = TokyoCabinet::HDB if tokyocabinet_class == "HDB" or tokyocabinet_class.nil?
19
22
  tokyocabinet_class = TokyoCabinet::BDB if tokyocabinet_class == "BDB"
20
23
 
21
24
  database = CONNECTIONS[path] ||= tokyocabinet_class.new
22
25
 
23
- if big and not Open.exists? path
26
+ if big and not Open.exists?(path)
24
27
  database.tune(nil,nil,nil,tokyocabinet_class::TLARGE | tokyocabinet_class::TDEFLATE)
25
28
  end
26
29
 
@@ -32,34 +35,40 @@ module Persist
32
35
  raise "Open error: #{database.errmsg(ecode)}. Trying to open file #{path}"
33
36
  end
34
37
 
35
-
36
38
  database.extend Persist::TCAdapter unless Persist::TCAdapter === database
37
39
  database.persistence_path ||= path
38
40
  database.tokyocabinet_class = tokyocabinet_class
39
41
 
40
42
  database.mutex = Mutex.new
43
+ database.read
44
+
45
+ CONNECTIONS[path] = database
46
+
41
47
  database
42
48
  end
43
49
 
44
50
  def close
45
51
  @closed = true
52
+ @writable = false
46
53
  super
47
54
  end
48
55
 
49
56
  def read(force = false)
50
- return if not write? and not closed and not force
57
+ return if ! write? && ! closed && ! force
51
58
  self.close
52
59
  if !self.open(@persistence_path, tokyocabinet_class::OREADER)
53
60
  ecode = self.ecode
54
61
  raise "Open error: #{self.errmsg(ecode)}. Trying to open file #{@persistence_path}"
55
62
  end
63
+
56
64
  @writable = false
57
65
  @closed = false
66
+
58
67
  self
59
68
  end
60
69
 
61
70
  def write(force = true)
62
- return if write? and not closed and not force
71
+ return if write? && ! closed && ! force
63
72
  self.close
64
73
 
65
74
  if !self.open(@persistence_path, tokyocabinet_class::OWRITER)
@@ -69,16 +78,18 @@ module Persist
69
78
 
70
79
  @writable = true
71
80
  @closed = false
81
+
72
82
  self
73
83
  end
84
+
74
85
  end
75
86
 
76
87
  def self.open_tokyocabinet(path, write, serializer = nil, tokyocabinet_class = TokyoCabinet::HDB)
77
88
  write = true unless File.exist? path
78
89
 
79
- FileUtils.mkdir_p File.dirname(path) unless File.exist?(File.dirname(path))
90
+ FileUtils.mkdir_p File.dirname(path) unless Open.exist?(File.dirname(path))
80
91
 
81
- database = Persist::TCAdapter.open(path, write, serializer, tokyocabinet_class)
92
+ database = Persist::TCAdapter.open(path, write, tokyocabinet_class)
82
93
 
83
94
  unless serializer == :clean
84
95
  TSV.setup database
@@ -0,0 +1,78 @@
1
+ require 'csv'
2
+
3
+ module TSV
4
+ def self.csv(obj, options = {})
5
+ options = Misc.add_defaults IndiferentHash.setup(options.dup), :headers => true, :type => :list
6
+ headers = options[:headers]
7
+
8
+ noheaders = ! headers
9
+
10
+ type = options.delete :type
11
+ merge = options.delete :merge
12
+ key_field = options.delete :key_field
13
+ fields = options.delete :fields
14
+
15
+ if key_field || fields
16
+ orig_type = type
17
+ type = :double
18
+ merge = true
19
+ end
20
+
21
+ options[:headers] = false
22
+
23
+ csv = case obj
24
+ when Path
25
+ CSV.read obj.find.open, options
26
+ when String
27
+ if Misc.is_filename?(obj)
28
+ CSV.read obj, options
29
+ else
30
+ CSV.new obj, options
31
+ end
32
+ else
33
+ CSV.new obj, options
34
+ end
35
+
36
+ tsv = if noheaders
37
+ TSV.setup({}, :key_field => nil, :fields => nil, :type => type)
38
+ else
39
+ key, *csv_fields = csv.shift
40
+ TSV.setup({}, :key_field => key, :fields => csv_fields, :type => type)
41
+ end
42
+
43
+ csv.each_with_index do |row,i|
44
+ if noheaders
45
+ key, values = ["row-#{i}", row]
46
+ else
47
+ key, *values = row
48
+ end
49
+
50
+ case type
51
+ when :double, :flat
52
+ tsv.zip_new(key, values)
53
+ when :single
54
+ tsv[key] = values.first
55
+ when :list
56
+ tsv[key] = values
57
+ end
58
+ end
59
+
60
+ if key_field || fields
61
+ tsv = tsv.reorder(key_field, fields, :zipped => true, :merge => true)
62
+ if tsv.type != orig_type
63
+ tsv = case orig_type
64
+ when :list
65
+ tsv.to_list
66
+ when :single
67
+ tsv.to_single
68
+ when :list
69
+ tsv.to_list
70
+ when :flat
71
+ tsv.to_flat
72
+ end
73
+ end
74
+ end
75
+
76
+ tsv
77
+ end
78
+ end
@@ -156,7 +156,6 @@ module TSV
156
156
  end
157
157
  end
158
158
  end
159
-
160
159
  end
161
160
 
162
161
  #{{{ Methods
@@ -620,8 +619,8 @@ module TSV
620
619
  when type == :flat
621
620
  self[key] = new_values
622
621
  else
623
- if (String === values[field_pos] and String === new_values) or
624
- (Array === values[field_pos] and Array === new_values)
622
+ if ! values[field_pos].frozen? && ((String === values[field_pos] && String === new_values) ||
623
+ (Array === values[field_pos] && Array === new_values))
625
624
  values[field_pos].replace new_values
626
625
  else
627
626
  values[field_pos] = new_values
@@ -214,6 +214,7 @@ module TSV
214
214
  end
215
215
 
216
216
  def add_to_data_flat_merge_double(data, keys, values)
217
+ data.write
217
218
  keys.each do |key|
218
219
  if data.include? key
219
220
  data[key] = data[key].concat values
@@ -538,7 +539,7 @@ module TSV
538
539
  end
539
540
 
540
541
  def traverse(options = {})
541
- monitor, bar, grep, invert_grep, head = Misc.process_options options, :monitor, :bar, :grep, :invert_grep, :head
542
+ monitor, bar, grep, invert_grep, head, fixed_grep = Misc.process_options options, :monitor, :bar, :grep, :invert_grep, :head, :fixed_grep
542
543
  monitor = bar if bar and monitor.nil?
543
544
  raise "No block given in TSV::Parser#traverse" unless block_given?
544
545
 
@@ -551,10 +552,10 @@ module TSV
551
552
 
552
553
  if @tsv_grep
553
554
 
554
- stream = Open.grep(stream, @tsv_grep, invert_grep)
555
+ stream = Open.grep(stream, @tsv_grep, invert_grep, fixed_grep)
555
556
  stream.no_fail = true
556
557
  begin
557
- match = Open.grep(StringIO.new(line), @tsv_grep, invert_grep).read
558
+ match = Open.grep(StringIO.new(line), @tsv_grep, invert_grep, fixed_grep).read
558
559
  line = stream.gets if match.empty?
559
560
  rescue Exception
560
561
  Log.exception $!
@@ -14,7 +14,12 @@ module Log
14
14
 
15
15
  class ProgressBar
16
16
 
17
+ class << self
18
+ attr_accessor :default_file
19
+ end
20
+
17
21
  attr_accessor :max, :ticks, :frequency, :depth, :desc, :file, :bytes
22
+
18
23
  def initialize(max = nil, options = {})
19
24
  options = Misc.add_defaults options, :depth => 0, :num_reports => 100, :io => STDERR, :severity => Log.severity, :frequency => 2
20
25
  depth, num_reports, desc, io, severity, file, bytes, frequency = Misc.process_options options, :depth, :num_reports, :desc, :io, :severity, :file, :bytes, :frequency
@@ -37,6 +42,10 @@ module Log
37
42
  (@ticks * 100) / @max
38
43
  end
39
44
 
45
+ def file
46
+ @file || ProgressBar.default_file
47
+ end
48
+
40
49
  def init
41
50
  @start = @last_time = Time.now
42
51
  @last_count = 0
@@ -127,7 +127,7 @@ module Log
127
127
  def save
128
128
  info = {:start => @start, :last_time => @last_time, :last_count => @last_count, :last_percent => @last_percent, :desc => @desc, :ticks => @ticks, :max => @max, :mean => @mean}
129
129
  info.delete_if{|k,v| v.nil?}
130
- Open.write(@file, info.to_yaml)
130
+ Open.write(file, info.to_yaml)
131
131
  end
132
132
 
133
133
  def report(io = STDERR)
@@ -158,7 +158,7 @@ module Log
158
158
  @last_time = Time.now
159
159
  @last_count = ticks
160
160
  @last_percent = percent if max and max > 0
161
- save if @file
161
+ save if file
162
162
  end
163
163
 
164
164
  def done(io = STDERR)
@@ -175,7 +175,7 @@ module Log
175
175
  done_msg << " - " << thr_msg
176
176
  done_msg << Log.color(:magenta, " · " << desc)
177
177
  print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth))
178
- Open.rm @file if @file and Open.exists? @file
178
+ Open.rm file if file and Open.exists? file
179
179
  end
180
180
 
181
181
  def error(io = STDERR)
@@ -192,7 +192,7 @@ module Log
192
192
  done_msg << " - " << thr_msg
193
193
  done_msg << Log.color(:magenta, " · " << desc)
194
194
  print(io, Log.up_lines(@depth) << done_msg << Log.down_lines(@depth))
195
- Open.rm @file if @file and Open.exists? @file
195
+ Open.rm file if file and Open.exists? file
196
196
  end
197
197
  end
198
198
  end
@@ -163,11 +163,10 @@ module Misc
163
163
 
164
164
  def self.fixutf8(string)
165
165
  return nil if string.nil?
166
- return string if (string.respond_to? :valid_encoding? and string.valid_encoding?) or
167
- (string.respond_to? :valid_encoding and string.valid_encoding)
166
+ return string if string.respond_to?(:encoding) && string.encoding == "UTF-8" && (string.respond_to?(:valid_encoding?) && string.valid_encoding?) ||
167
+ (string.respond_to?(:valid_encoding) && string.valid_encoding)
168
168
 
169
169
  if string.respond_to?(:encode)
170
- #string.encode("UTF-16BE", :invalid => :replace, :undef => :replace, :replace => "?").encode('UTF-8')
171
170
  string.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
172
171
  else
173
172
  require 'iconv'
@@ -138,11 +138,15 @@ module Open
138
138
 
139
139
  # Grep
140
140
 
141
- def self.grep(stream, grep, invert = false)
141
+ def self.grep(stream, grep, invert = false, fixed = nil)
142
142
  case
143
143
  when Array === grep
144
144
  TmpFile.with_file(grep * "\n", false) do |f|
145
- CMD.cmd("#{GREP_CMD} #{invert ? '-v' : ''} -", "-w" => true, "-F" => true, "-f" => f, :in => stream, :pipe => true, :post => proc{FileUtils.rm f})
145
+ if FalseClass === fixed
146
+ CMD.cmd("#{GREP_CMD} #{invert ? '-v' : ''} -", "-f" => f, :in => stream, :pipe => true, :post => proc{FileUtils.rm f})
147
+ else
148
+ CMD.cmd("#{GREP_CMD} #{invert ? '-v' : ''} -", "-w" => true, "-F" => true, "-f" => f, :in => stream, :pipe => true, :post => proc{FileUtils.rm f})
149
+ end
146
150
  end
147
151
  else
148
152
  CMD.cmd("#{GREP_CMD} #{invert ? '-v ' : ''} '#{grep}' -", :in => stream, :pipe => true, :post => proc{begin stream.force_close; rescue Exception; end if stream.respond_to?(:force_close)})
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbbt-util'
4
+ require 'rbbt/util/simpleopt'
5
+
6
+ options = SOPT.setup <<EOF
7
+ Read a TSV file and dump it
8
+
9
+ $ rbbt tsv keys [options] <filename.tsv|->
10
+
11
+ Use - to read from STDIN
12
+
13
+ -k--key_field* Key field
14
+ -h--help Print this help
15
+ -tch--tokyocabinet File is a tokyocabinet hash database
16
+ -tcb--tokyocabinet_bd File is a tokyocabinet B database
17
+
18
+ EOF
19
+ rbbt_usage and exit 0 if options[:help]
20
+
21
+ file = ARGV.shift
22
+
23
+ file = STDIN if file == '-'
24
+
25
+ case
26
+ when options[:tokyocabinet]
27
+ tsv = Persist.open_tokyocabinet(file, false)
28
+ tsv.keys.each do |k|
29
+ puts k
30
+ end
31
+ exit
32
+ when options[:tokyocabinet_bd]
33
+ tsv = Persist.open_tokyocabinet(file, false, nil, TokyoCabinet::BDB)
34
+ tsv.keys.each do |k|
35
+ puts k
36
+ end
37
+ exit
38
+ end
39
+
40
+ parser = TSV::Parser.new TSV.get_stream(file), options.merge(:fields => [])
41
+
42
+ options[:merge] = false if options[:merge] == "false"
43
+
44
+ Thread.new do
45
+ line = parser.first_line
46
+ bar = Log::ProgressBar.new
47
+ while line
48
+ bar.tick
49
+
50
+ line = Misc.fixutf8(line)
51
+ line = parser.process line
52
+ raise SKIP_LINE if line.empty?
53
+ parts = parser.chop_line line
54
+ key, values = parser.get_values parts
55
+ values = parser.cast_values values if parser.cast?
56
+
57
+ puts key
58
+ end
59
+ end
@@ -0,0 +1,49 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../..', 'test_helper.rb')
2
+ require 'rbbt/tsv/csv'
3
+
4
+ class TestCSV < Test::Unit::TestCase
5
+ def test_csv
6
+ text =<<-EOF
7
+ Key,FieldA,FieldB
8
+ k1,a,b
9
+ k2,aa,bb
10
+ EOF
11
+
12
+ tsv = TSV.csv(text)
13
+ assert_equal 'bb', tsv['k2']['FieldB']
14
+ end
15
+
16
+ def test_csv_key_field
17
+ text =<<-EOF
18
+ Key,FieldA,FieldB
19
+ k1,a,b
20
+ k2,aa,bb
21
+ EOF
22
+
23
+ tsv = TSV.csv(text, :key_field => 'FieldA', :type => :list)
24
+ assert_equal 'bb', tsv['aa']['FieldB']
25
+ end
26
+
27
+ def test_csv_double
28
+ text =<<-EOF
29
+ Key,FieldA,FieldB
30
+ k1,a,b
31
+ k2,aa,bb
32
+ EOF
33
+
34
+ tsv = TSV.csv(text, :key_field => 'FieldA', :type => :double)
35
+ assert_equal ['bb'], tsv['aa']['FieldB']
36
+ end
37
+
38
+ def test_csv_noheader
39
+ text =<<-EOF
40
+ k1,a,b
41
+ k2,aa,bb
42
+ EOF
43
+
44
+ tsv = TSV.csv(text, :headers => false)
45
+ assert_equal %w(k2 aa bb), tsv['row-1']
46
+ end
47
+
48
+ end
49
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbbt-util
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.26.169
4
+ version: 5.26.170
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miguel Vazquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-09 00:00:00.000000000 Z
11
+ date: 2020-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -241,6 +241,7 @@ files:
241
241
  - lib/rbbt/tsv/attach.rb
242
242
  - lib/rbbt/tsv/attach/util.rb
243
243
  - lib/rbbt/tsv/change_id.rb
244
+ - lib/rbbt/tsv/csv.rb
244
245
  - lib/rbbt/tsv/dumper.rb
245
246
  - lib/rbbt/tsv/excel.rb
246
247
  - lib/rbbt/tsv/field_index.rb
@@ -394,6 +395,7 @@ files:
394
395
  - share/rbbt_commands/tsv/head
395
396
  - share/rbbt_commands/tsv/info
396
397
  - share/rbbt_commands/tsv/json
398
+ - share/rbbt_commands/tsv/keys
397
399
  - share/rbbt_commands/tsv/query
398
400
  - share/rbbt_commands/tsv/read
399
401
  - share/rbbt_commands/tsv/read_excel
@@ -466,6 +468,7 @@ files:
466
468
  - test/rbbt/tsv/test_accessor.rb
467
469
  - test/rbbt/tsv/test_attach.rb
468
470
  - test/rbbt/tsv/test_change_id.rb
471
+ - test/rbbt/tsv/test_csv.rb
469
472
  - test/rbbt/tsv/test_excel.rb
470
473
  - test/rbbt/tsv/test_field_index.rb
471
474
  - test/rbbt/tsv/test_filter.rb
@@ -583,6 +586,7 @@ test_files:
583
586
  - test/rbbt/tsv/test_attach.rb
584
587
  - test/rbbt/tsv/test_filter.rb
585
588
  - test/rbbt/tsv/test_parser.rb
589
+ - test/rbbt/tsv/test_csv.rb
586
590
  - test/rbbt/tsv/test_accessor.rb
587
591
  - test/rbbt/tsv/test_matrix.rb
588
592
  - test/rbbt/tsv/test_field_index.rb