rbbt-util 5.26.169 → 5.26.170

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 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