fat_table 0.9.7 → 0.9.8

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.
@@ -106,7 +106,7 @@ module FatTable
106
106
  if types.keys.map(&:to_s).include?('omni')
107
107
  # All columns not otherwise included in types should have the type and
108
108
  # tolerance of omni.
109
- omni_val = (types['omni'] || types[:omni])
109
+ omni_val = types['omni'] || types[:omni]
110
110
  @omni_type, @omni_tol = Table.typ_tol(omni_val)
111
111
  # Remove omni from types.
112
112
  types.delete(:omni)
@@ -121,8 +121,7 @@ module FatTable
121
121
  tol = @omni_tol
122
122
  end
123
123
  @tolerant_cols << h.to_s.as_sym if tol
124
- @columns << Column.new(header: h.to_s.sub(/~\s*\z/, ''), type: typ,
125
- tolerant: tol)
124
+ @columns << Column.new(header: h.to_s.sub(/~\s*\z/, ''), type: typ, tolerant: tol)
126
125
  end
127
126
  @explicit_boundaries = []
128
127
  end
@@ -136,7 +135,7 @@ module FatTable
136
135
  # might have been set by a subclass instance.
137
136
  def empty_dup(result_cols = nil)
138
137
  result_cols ||= heads
139
- result_types = types.select { |k,_v| result_cols.include?(k) }
138
+ result_types = types.select { |k, _v| result_cols.include?(k) }
140
139
  result = self.class.new(result_cols, **result_types)
141
140
  tolerant_cols.each do |h|
142
141
  result.tolerant_cols << h
@@ -164,8 +163,8 @@ module FatTable
164
163
 
165
164
  # Construct a Table from a CSV string +str+, treated in the same manner as
166
165
  # the input from a CSV file in ::from_org_file.
167
- def self.from_csv_string(str, has_headers: true, **)
168
- from_csv_io(StringIO.new(str), has_headers:, **)
166
+ def self.from_csv_string(str, has_headers: true, **types)
167
+ from_csv_io(str, has_headers:, **types)
169
168
  rescue NoTable
170
169
  raise NoTable, "no table found in string '#{str[0..20]}...'"
171
170
  end
@@ -283,9 +282,9 @@ module FatTable
283
282
  # Construct table from an array of hashes or an array of any object that
284
283
  # can respond to #to_h. If an array element is a nil, mark it as a group
285
284
  # boundary in the Table.
286
- def from_array_of_hashes(hashes, hlines: false, **)
285
+ def from_array_of_hashes(hashes, hlines: false, **types)
287
286
  heads = hashes.first.keys
288
- result = new(*heads, **)
287
+ result = new(*heads, **types)
289
288
  hashes.each do |hsh|
290
289
  if hsh.nil?
291
290
  unless hlines
@@ -313,18 +312,18 @@ module FatTable
313
312
  # hlines are stripped from the table, otherwise (:hlines yes) they are
314
313
  # indicated with nil elements in the outer array as expected by this
315
314
  # method when hlines is set true.
316
- def from_array_of_arrays(rows, hlines: false, **)
315
+ def from_array_of_arrays(rows, hlines: false, **types)
317
316
  headers = []
318
317
  if !hlines
319
318
  # Take the first row as headers
320
319
  # Second row et seq as data
321
- headers = rows[0].map(&:to_s).map(&:as_sym)
320
+ headers = rows[0].map { |r| r.to_s.as_sym }
322
321
  first_data_row = 1
323
322
  elsif rows[1].nil?
324
323
  # Use first row 0 as headers
325
324
  # Row 1 is an hline
326
325
  # Row 2 et seq are data
327
- headers = rows[0].map(&:to_s).map(&:as_sym)
326
+ headers = rows[0].map { |r| r.to_s.as_sym }
328
327
  first_data_row = 2
329
328
  else
330
329
  # Synthesize headers
@@ -332,7 +331,7 @@ module FatTable
332
331
  headers = (1..rows[0].size).to_a.map { |k| "col_#{k}".as_sym }
333
332
  first_data_row = 0
334
333
  end
335
- result = new(*headers, **)
334
+ result = new(*headers, **types)
336
335
  rows[first_data_row..-1].each do |row|
337
336
  if row.nil?
338
337
  unless hlines
@@ -350,31 +349,40 @@ module FatTable
350
349
  result
351
350
  end
352
351
 
353
- def from_csv_io(io, has_headers: true, **)
354
- result = new(**)
352
+ def from_csv_io(io_or_str, has_headers: true, **types)
353
+ result = new(**types)
355
354
  if has_headers
356
- ::CSV.new(io, headers: has_headers, header_converters: :symbol, skip_blanks: true).each do |row|
357
- result << row.to_h
358
- end
355
+ csv_tab = CSV.new(io_or_str, headers: has_headers, header_converters: :symbol, skip_blanks: true)
359
356
  else
360
- nfields = io.readline.split(',').size
361
- io.seek(0, IO::SEEK_SET)
362
- heads = (1..nfields).map {|n| "col_#{n}"}
363
- ::CSV.new(io, headers: heads, skip_blanks: true).each do |row|
364
- result << row.to_h
365
- end
357
+ nfields =
358
+ case io_or_str
359
+ when StringIO, IO
360
+ io_or_str.readline.split(',').size
361
+ io_or_str.seek(0, IO::SEEK_SET)
362
+ when String
363
+ io_or_str.split("\n").first.split(',').size
364
+ else
365
+ raise LogicError, "from_csc_io input from #{io_or_str.class} must be String or IO"
366
+ end
367
+ heads = (1..nfields).map { |n| "col_#{n}" }
368
+ csv_tab = CSV.new(io_or_str, headers: heads, skip_blanks: true)
369
+ end
370
+ csv_tab.each do |row|
371
+ result << row.to_h
366
372
  end
367
373
  result.normalize_boundaries
368
374
  result
369
- rescue StandardError
370
- raise NoTable
375
+ rescue ::CSV::MalformedCSVError => ex
376
+ raise NoTable, "malformed CSV at line #{ex.line_number}"
377
+ rescue StandardError => ex
378
+ raise LogicError, ex
371
379
  end
372
380
 
373
381
  # Form rows of table by reading the first table found in the org file. The
374
382
  # header row must be marked with an hline (i.e, a row that looks like
375
383
  # '|---+--...--|') and groups of rows may be marked with hlines to
376
384
  # indicate group boundaries.
377
- def from_org_io(io, **)
385
+ def from_org_io(io, **types)
378
386
  table_re = /\A\s*\|/
379
387
  hrule_re = /\A\s*\|[-+]+/
380
388
  rows = []
@@ -417,7 +425,8 @@ module FatTable
417
425
  end
418
426
  end
419
427
  raise NoTable unless table_found
420
- from_array_of_arrays(rows, hlines: true, **)
428
+
429
+ from_array_of_arrays(rows, hlines: true, **types)
421
430
  end
422
431
  end
423
432
 
@@ -525,7 +534,7 @@ module FatTable
525
534
  # tolerant. We can't just look up the Column because it may not be build
526
535
  # yet, as when we do a row-by-row add.
527
536
  def tolerant_col?(h)
528
- tolerant_cols.include?(h.to_s.as_sym) || self.omni_tol
537
+ tolerant_cols.include?(h.to_s.as_sym) || omni_tol
529
538
  end
530
539
 
531
540
  # :category: Attributes
@@ -578,7 +587,7 @@ module FatTable
578
587
  # large table, that would require that we construct all the rows for a range
579
588
  # of any size.
580
589
  def rows_range(first = 0, last = nil) # :nodoc:
581
- raise UserError, 'first must be <= last' unless first <= last
590
+ raise UserError, 'first must be <= last' if first > last
582
591
 
583
592
  rows = []
584
593
  unless columns.empty?
@@ -604,12 +613,9 @@ module FatTable
604
613
  # :category: Attributes
605
614
 
606
615
  # Yield each row of the table as a Hash with the column symbols as keys.
607
- def each
608
- if block_given?
609
- rows.each do |row|
610
- yield row
611
- end
612
- self
616
+ def each(&block)
617
+ if block
618
+ rows.each(&block)
613
619
  else
614
620
  to_enum(:each)
615
621
  end
@@ -656,11 +662,7 @@ module FatTable
656
662
  # Return an array of an Array of row Hashes for the groups in this Table.
657
663
  def groups
658
664
  normalize_boundaries
659
- groups = []
660
- (0..boundaries.size - 1).each do |k|
661
- groups << group_rows(k)
662
- end
663
- groups
665
+ (0..boundaries.size - 1).map { |k| group_rows(k) }
664
666
  end
665
667
 
666
668
  # Return the number of groups in the table.
@@ -694,8 +696,12 @@ module FatTable
694
696
  range = group_row_range(k)
695
697
  tab_col = column(col)
696
698
  gitems = tab_col.items[range]
697
- cols << Column.new(header: col, items: gitems,
698
- type: tab_col.type, tolerant: tab_col.tolerant?)
699
+ cols << Column.new(
700
+ header: col,
701
+ items: gitems,
702
+ type: tab_col.type,
703
+ tolerant: tab_col.tolerant?,
704
+ )
699
705
  end
700
706
  cols
701
707
  end
@@ -721,12 +727,9 @@ module FatTable
721
727
  return self if empty?
722
728
 
723
729
  if row_num
724
- unless row_num < size
725
- raise ArgumentError, "can't mark boundary at row #{row_num}, last row is #{size - 1}"
726
- end
727
- unless row_num >= 0
728
- raise ArgumentError, "can't mark boundary at non-positive row #{row_num}"
729
- end
730
+ raise ArgumentError, "can't mark boundary at row #{row_num}, last row is #{size - 1}" if row_num >= size
731
+ raise ArgumentError, "can't mark boundary at non-positive row #{row_num}" if row_num < 0
732
+
730
733
  explicit_boundaries.push(row_num)
731
734
  elsif size > 0
732
735
  explicit_boundaries.push(size - 1)
@@ -797,7 +800,7 @@ module FatTable
797
800
  # Return the rows for group number +grp_num+.
798
801
  def group_rows(grp_num) # :nodoc:
799
802
  normalize_boundaries
800
- return [] unless grp_num < boundaries.size
803
+ return [] if grp_num >= boundaries.size
801
804
 
802
805
  first = first_row_num_in_group(grp_num)
803
806
  last = last_row_num_in_group(grp_num)
@@ -884,7 +887,7 @@ module FatTable
884
887
  # each row where the sort key changes.
885
888
  def order_with(expr)
886
889
  unless expr.is_a?(String)
887
- raise "must call FatTable::Table\#order_with with a single string expression"
890
+ raise "must call FatTable::Table#order_with with a single string expression"
888
891
  end
889
892
 
890
893
  rev = false
@@ -995,9 +998,11 @@ module FatTable
995
998
  after_hook = new_cols[:after_hook].to_s
996
999
  new_cols.delete(:after_hook)
997
1000
  end
998
- ev = Evaluator.new(ivars: ivars,
999
- before: before_hook,
1000
- after: after_hook)
1001
+ ev = Evaluator.new(
1002
+ ivars: ivars,
1003
+ before: before_hook,
1004
+ after: after_hook,
1005
+ )
1001
1006
  # Compute the new Table from this Table
1002
1007
  result_cols =
1003
1008
  if cols.include?(:omni)
@@ -1041,13 +1046,14 @@ module FatTable
1041
1046
 
1042
1047
  new_row[key] = vars[expr]
1043
1048
  when String
1044
- if expr.match?(/\A\s*:/)
1045
- # Leading colon signal a literal string
1046
- new_row[key] = expr.sub(/\A\s*:/, '')
1047
- else
1048
- # Otherwise, evaluate the string.
1049
- new_row[key] = ev.evaluate(expr, locals: vars)
1050
- end
1049
+ new_row[key] =
1050
+ if expr.match?(/\A\s*:/)
1051
+ # Leading colon signal a literal string
1052
+ expr.sub(/\A\s*:/, '')
1053
+ else
1054
+ # Otherwise, evaluate the string.
1055
+ ev.evaluate(expr, locals: vars)
1056
+ end
1051
1057
  when Numeric, DateTime, Date, TrueClass, FalseClass
1052
1058
  new_row[key] = expr
1053
1059
  else
@@ -1119,9 +1125,7 @@ module FatTable
1119
1125
  # eliminated from the result. Any groups present in either Table are
1120
1126
  # eliminated in the output Table.
1121
1127
  def union(other)
1122
- set_operation(other, :+,
1123
- distinct: true,
1124
- add_boundaries: true)
1128
+ set_operation(other, :+, distinct: true, add_boundaries: true)
1125
1129
  end
1126
1130
 
1127
1131
  # :category: Operators
@@ -1134,13 +1138,7 @@ module FatTable
1134
1138
  # boundaries of the constituent tables. Preserves and adjusts the group
1135
1139
  # boundaries of the constituent table.
1136
1140
  def union_all(other)
1137
- set_operation(
1138
- other,
1139
- :+,
1140
- distinct: false,
1141
- add_boundaries: true,
1142
- inherit_boundaries: true
1143
- )
1141
+ set_operation(other, :+, distinct: false, add_boundaries: true, inherit_boundaries: true)
1144
1142
  end
1145
1143
 
1146
1144
  # :category: Operators
@@ -1297,25 +1295,20 @@ module FatTable
1297
1295
  next unless matches
1298
1296
 
1299
1297
  self_row_matched = other_row_matches[k] = true
1300
- out_row = build_out_row(row_a: self_row, row_b: other_row,
1301
- common_heads: other_common_heads,
1302
- type: join_type)
1298
+ out_row = build_out_row(row_a: self_row, row_b: other_row, common_heads: other_common_heads, type: join_type)
1303
1299
  result << out_row
1304
1300
  end
1305
- next unless [:left, :full].include?(join_type)
1301
+ # next unless [:left, :full].include?(join_type)
1302
+ next unless join_type == :left || join_type == :full
1306
1303
  next if self_row_matched
1307
1304
 
1308
- result << build_out_row(row_a: self_row,
1309
- row_b: other_row_nils,
1310
- type: join_type)
1305
+ result << build_out_row(row_a: self_row, row_b: other_row_nils, type: join_type)
1311
1306
  end
1312
- if [:right, :full].include?(join_type)
1307
+ if join_type == :right || join_type == :full
1313
1308
  other_rows.each_with_index do |other_row, k|
1314
1309
  next if other_row_matches[k]
1315
1310
 
1316
- result << build_out_row(row_a: self_row_nils,
1317
- row_b: other_row,
1318
- type: join_type)
1311
+ result << build_out_row(row_a: self_row_nils, row_b: other_row, type: join_type)
1319
1312
  end
1320
1313
  end
1321
1314
  result.normalize_boundaries
@@ -1430,15 +1423,13 @@ module FatTable
1430
1423
 
1431
1424
  if partial_result
1432
1425
  # Second of a pair
1433
- ensure_common_types!(self_h: a_head,
1434
- other_h: last_sym,
1435
- other: other)
1426
+ ensure_common_types!(self_h: a_head, other_h: last_sym, other: other)
1436
1427
  partial_result << "#{a_head}_a)"
1437
1428
  and_conds << partial_result
1438
1429
  partial_result = nil
1439
1430
  else
1440
1431
  # First of a pair of _a or _b
1441
- partial_result = +"(#{a_head}_a == "
1432
+ partial_result = "(#{a_head}_a == "
1442
1433
  end
1443
1434
  last_sym = a_head
1444
1435
  when /\A(?<sy>.*)_b\z/
@@ -1449,15 +1440,13 @@ module FatTable
1449
1440
 
1450
1441
  if partial_result
1451
1442
  # Second of a pair
1452
- ensure_common_types!(self_h: last_sym,
1453
- other_h: b_head,
1454
- other: other)
1443
+ ensure_common_types!(self_h: last_sym, other_h: b_head, other: other)
1455
1444
  partial_result << "#{b_head}_b)"
1456
1445
  and_conds << partial_result
1457
1446
  partial_result = nil
1458
1447
  else
1459
1448
  # First of a pair of _a or _b
1460
- partial_result = +"(#{b_head}_b == "
1449
+ partial_result = "(#{b_head}_b == "
1461
1450
  end
1462
1451
  b_common_heads << b_head
1463
1452
  last_sym = b_head
@@ -1554,8 +1543,7 @@ module FatTable
1554
1543
  agg_cols.each_pair do |h, agg_func|
1555
1544
  items = rows.map { |r| r[h] }
1556
1545
  new_h = "#{agg_func}_#{h}".as_sym
1557
- new_row[new_h] = Column.new(header: h,
1558
- items: items).send(agg_func)
1546
+ new_row[new_h] = Column.new(header: h, items: items).send(agg_func)
1559
1547
  end
1560
1548
  new_row
1561
1549
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module FatTable
4
4
  # The current version of FatTable
5
- VERSION = '0.9.7'
5
+ VERSION = '0.9.8'
6
6
  end
data/lib/fat_table.rb CHANGED
@@ -162,6 +162,7 @@ module FatTable
162
162
  def self.to_any(fmt, table, options = {})
163
163
  fmt = fmt.as_sym
164
164
  raise UserError, "unknown format '#{fmt}'" unless FORMATS.include?(fmt)
165
+
165
166
  method = "to_#{fmt}"
166
167
  if block_given?
167
168
  send(method, table, options, &Proc.new)
metadata CHANGED
@@ -1,44 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fat_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel E. Doherty
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-12-26 00:00:00.000000000 Z
10
+ date: 2024-12-31 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: fat_core
13
+ name: csv
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 4.9.0
18
+ version: '0'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 4.9.0
25
+ version: '0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: csv
27
+ name: fat_core
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: 4.9.0
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: '0'
39
+ version: 4.9.0
40
40
  - !ruby/object:Gem::Dependency
41
- name: rainbow
41
+ name: gem-path
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="
@@ -52,7 +52,7 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
- name: sequel
55
+ name: rainbow
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - ">="
@@ -66,7 +66,7 @@ dependencies:
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  - !ruby/object:Gem::Dependency
69
- name: gem-path
69
+ name: sequel
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - ">="
@@ -115,6 +115,7 @@ executables:
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
+ - ".envrc"
118
119
  - ".gitignore"
119
120
  - ".rspec"
120
121
  - ".rubocop.yml"
@@ -156,6 +157,7 @@ files:
156
157
  - lib/fat_table/formatters/org_formatter.rb
157
158
  - lib/fat_table/formatters/term_formatter.rb
158
159
  - lib/fat_table/formatters/text_formatter.rb
160
+ - lib/fat_table/formatters/xcolors.txt
159
161
  - lib/fat_table/patches.rb
160
162
  - lib/fat_table/table.rb
161
163
  - lib/fat_table/version.rb