fat_table 0.9.7 → 0.9.9
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 +4 -4
- data/.envrc +1 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +9 -0
- data/Gemfile +2 -0
- data/Rakefile +5 -1
- data/fat_table.gemspec +6 -6
- data/lib/ext/array.rb +2 -2
- data/lib/fat_table/column.rb +11 -8
- data/lib/fat_table/convert.rb +22 -11
- data/lib/fat_table/evaluator.rb +4 -1
- data/lib/fat_table/footer.rb +9 -6
- data/lib/fat_table/formatters/aoa_formatter.rb +1 -1
- data/lib/fat_table/formatters/aoh_formatter.rb +1 -1
- data/lib/fat_table/formatters/formatter.rb +81 -74
- data/lib/fat_table/formatters/latex_formatter.rb +13 -63
- data/lib/fat_table/formatters/term_formatter.rb +23 -23
- data/lib/fat_table/formatters/xcolors.txt +337 -0
- data/lib/fat_table/patches.rb +6 -9
- data/lib/fat_table/table.rb +80 -92
- data/lib/fat_table/version.rb +1 -1
- data/lib/fat_table.rb +1 -0
- metadata +14 -12
data/lib/fat_table/table.rb
CHANGED
@@ -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 =
|
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.
|
138
|
+
result_types = types.slice(*result_cols)
|
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(
|
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
|
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
|
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(
|
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
|
-
|
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 =
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
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
|
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
|
-
|
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) ||
|
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'
|
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
|
609
|
-
rows.each
|
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
|
-
|
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(
|
698
|
-
|
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
|
-
|
725
|
-
|
726
|
-
|
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 []
|
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
|
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(
|
999
|
-
|
1000
|
-
|
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
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
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
|
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 =
|
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 =
|
1449
|
+
partial_result = "(#{b_head}_b == "
|
1461
1450
|
end
|
1462
1451
|
b_common_heads << b_head
|
1463
1452
|
last_sym = b_head
|
@@ -1532,7 +1521,7 @@ module FatTable
|
|
1532
1521
|
groups = sorted_tab.rows.group_by do |r|
|
1533
1522
|
group_cols.map { |k| r[k] }
|
1534
1523
|
end
|
1535
|
-
grp_types = types.
|
1524
|
+
grp_types = types.slice(*group_cols)
|
1536
1525
|
result = Table.new(*group_cols, **grp_types)
|
1537
1526
|
groups.each_pair do |_vals, grp_rows|
|
1538
1527
|
result << row_from_group(grp_rows, group_cols, agg_cols)
|
@@ -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
|
data/lib/fat_table/version.rb
CHANGED
data/lib/fat_table.rb
CHANGED
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.
|
4
|
+
version: 0.9.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel E. Doherty
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 2025-03-19 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
|
-
name:
|
13
|
+
name: csv
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - ">="
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version:
|
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:
|
25
|
+
version: '0'
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
|
-
name:
|
27
|
+
name: fat_core
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
29
29
|
requirements:
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
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:
|
39
|
+
version: 4.9.0
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
|
-
name:
|
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:
|
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:
|
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
|
@@ -179,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
181
|
- !ruby/object:Gem::Version
|
180
182
|
version: '0'
|
181
183
|
requirements: []
|
182
|
-
rubygems_version: 3.6.
|
184
|
+
rubygems_version: 3.6.3
|
183
185
|
specification_version: 4
|
184
186
|
summary: Provides tools for working with tables as a data type.
|
185
187
|
test_files: []
|