fat_table 0.2.11 → 0.3.4

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: 1e55116f769d702af90918ed1bff4e9d8589d02d746da47d599d3bc155bbd033
4
- data.tar.gz: f415408bfb6af7a2752b4f0f9d8d9b80407dd6062a1ba3ff85088886bd23c743
3
+ metadata.gz: b1acf502c906ac50471a86a10889b2897831c26a4a49102aa3ee18e784658122
4
+ data.tar.gz: a239367ae5b4a70a888fe1e8427f1989f0cf8369402f2e3e252b9b2d11058841
5
5
  SHA512:
6
- metadata.gz: e3344a48f676d18c6e68ff460af5b697b19b8ebba6343d2a604ba62fc65d228b2e6f5563bcbfe7cf852d31db1fe20e9cc7f7952f75c4e6c09a2eb29a8211c9cd
7
- data.tar.gz: 615a248fc73a49ca5caad56c12569aa3686aa3450393c4a1305de657fc5a6809a34b1a135a84298373fb49f5fb8461af375abe2d6880319b0a49e9e5ccbd1c2e
6
+ metadata.gz: 1edd15c8c3bf469a2b2278fd96246af6154ec8d7b1190f9f8398f23db1fc6bd816ecc92467296f8d811ac21045f797fbfb62c54fb2f6e95b83b33272a5bac1a4
7
+ data.tar.gz: 8c938a602ea1a7a4f58a85265d84d80c9c7eea9dcba250a36861456f8244ab14f0f108f70d57737c43316b528d2ca373ff7ab3d0ee87eb8ae9c77637207163cd
data/.gitignore CHANGED
@@ -13,6 +13,7 @@
13
13
  .rspec_status
14
14
  /README.pdf
15
15
  /README.tex
16
+ /README.md
16
17
  /README.synctex.gz
17
18
  /_minted*
18
19
  /auto/
@@ -24,3 +25,4 @@
24
25
  /GRTAGS
25
26
  /GTAGS
26
27
  /TAGS
28
+ /README.pyg
data/.rubocop.yml CHANGED
@@ -1,3 +1,18 @@
1
- inherit_from: ~/.rubocop.yml
1
+ inherit_gem:
2
+ rubocop-shopify: rubocop.yml
2
3
  require: rubocop-rspec
3
4
  require: rubocop-performance
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 2.7
8
+ Exclude:
9
+ - 'test/tmp/**/*'
10
+ - 'vendor/bundle/**/*'
11
+
12
+ Style/MethodCallWithArgsParentheses:
13
+ Exclude:
14
+ - '**/Gemfile'
15
+
16
+ Style/ClassAndModuleChildren:
17
+ Exclude:
18
+ - 'test/**/*'
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ language: ruby
2
2
  before_install:
3
3
  - sudo apt-get -qq update
4
4
  - sudo apt-get install -y texlive-latex-base texlive-latex-recommended
5
+ - gem install pg
5
6
  # before_script:
6
7
  # - createdb -U travis travis
7
8
  after_failure:
@@ -13,9 +14,9 @@ bundler_args: --without debug
13
14
  services:
14
15
  - postgresql
15
16
  rvm:
16
- - 2.3
17
17
  - 2.4
18
18
  - 2.5
19
19
  - 2.6
20
20
  - 2.7
21
- - ruby-head
21
+ - 3.0
22
+ - truffleruby
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'rubocop-shopify', require: false
4
+
3
5
  # Specify your gem's dependencies in fat_table.gemspec
4
6
  gemspec
data/README.org CHANGED
@@ -44,17 +44,6 @@ buffer as an org-table, ready for processing by other code blocks.
44
44
 
45
45
  * Installation
46
46
 
47
- ** Prerequisites
48
- The ~fat_table~ gem depends on several libraries being available for building,
49
- mostly those concerned with accessing databases. On an ubuntu system, the
50
- following packages should be installed before you install the ~fat_table~ gem:
51
-
52
- - ruby-dev
53
- - build-essential
54
- - libsqlite3-dev
55
- - libpq-dev
56
- - libmysqlclient-dev
57
-
58
47
  ** Installing the gem
59
48
 
60
49
  Add this line to your application's Gemfile:
@@ -492,7 +481,7 @@ This example illustrates several things:
492
481
  A second ruby data structure that can be used to initialize a ~FatTable~ table
493
482
  is an array of ruby Hashes. Each hash represents a row of the table, and the
494
483
  headers of the table are taken from the keys of the hashes. Accordingly, all the
495
- hashes should have the same keys.
484
+ hashes must have the same keys.
496
485
 
497
486
  This same method can in fact take an array of any objects that can be converted
498
487
  to a Hash with the ~#to_h~ method, so you can use an array of your own objects
@@ -526,9 +515,17 @@ or strings that can be parsed into one of the permissible column types.
526
515
 
527
516
  *** From SQL queries
528
517
 
529
- Another way to initialize a ~FatTable~ table is with the results of a SQL query.
530
- ~FatTable~ uses the ~sequel~ gem to query databases. You must first set the
531
- database parameters to be used for the queries.
518
+ Another way to initialize a ~FatTable~ table is with the results of a SQL
519
+ query. Before you can connect to a database, you need to make sure that the required
520
+ adapter for your database is installed. ~FatTable~ uses the ~sequel~ gem
521
+ under the hood, so any database that it supports can be used. For example, if
522
+ you are accessing a Postgres database, you must install the ~pg~ gem with
523
+
524
+ #+begin_src sh
525
+ $ gem install pg
526
+ #+end_src
527
+
528
+ You must first set the database parameters to be used for the queries.
532
529
 
533
530
  #+BEGIN_SRC ruby
534
531
  # This automatically requires sequel.
@@ -771,17 +768,18 @@ symbol representing an existing column, which has the effect of renaming an
771
768
  existing column, or (2) a string representing a ruby expression for the value of
772
769
  a new column.
773
770
 
774
- Within the string expression, the names of existing or already-specified columns
775
- are available as local variables, as well as the instance variables '@row' and
776
- '@group'. So for our example table, the string expressions for new columns have
777
- access to local variables ~ref~, ~date~, ~code~, ~price~, ~g10~, ~qp10~,
771
+ Within the string expression, the names of existing or already-specified
772
+ columns are available as local variables. In addition the instance variables
773
+ '@row' and '@group' are available as the row number and group number of the
774
+ new value. So for our example table, the string expressions for new columns
775
+ have access to local variables ~ref~, ~date~, ~code~, ~price~, ~g10~, ~qp10~,
778
776
  ~shares~, ~lp~, ~qp~, ~iplp~, and ~ipqp~ as well as the instance variables
779
777
  ~@row~ and ~@group~. The local variables are set to the values of the cell in
780
- their respective columns for each row in the input table and the instance
781
- variables are set the number of the current row and group respectively.
778
+ their respective columns for each row in the input table, and the instance
779
+ variables are set the number of the current row and group number respectively.
782
780
 
783
- For example, if we want to rename the ~:date~ column and add a new column to
784
- compute the cost of shares, we could do the following:
781
+ For example, if we want to rename the ~traded_on~ column to ~:date~ and add a
782
+ new column to compute the cost of shares, we could do the following:
785
783
 
786
784
  #+HEADER: :colnames no :session readme :hlines yes :wrap EXAMPLE :exports both
787
785
  #+BEGIN_SRC ruby
@@ -1044,8 +1042,10 @@ the value is a symbol for one of several aggregating methods that
1044
1042
  to the :price column so that the output shows the average price in each group.
1045
1043
  The ~:shares~, ~:lp~, and ~:qp~ columns are summed, and the ~:any?~ aggregate is
1046
1044
  applied to one of the boolean fields, that is, it is ~true~ if any of the values
1047
- in that column are ~true~. The column names in the output of the aggregated
1048
- columns have the name of the aggregating method pre-pended to the column name.
1045
+ in that column are ~true~.
1046
+
1047
+ Note that the column names in the output of the aggregated columns have the
1048
+ name of the aggregating method pre-pended to the column name.
1049
1049
 
1050
1050
  Here is a list of all the aggregate methods available. If the description
1051
1051
  restricts the aggregate to particular column types, applying it to other types
@@ -1314,6 +1314,7 @@ table where the join expression is satisfied and augmented with nils otherwise.
1314
1314
  Finally, a cross join outputs every row of ~tab_a~ augmented with every row of
1315
1315
  ~tab_b~, in other words, the Cartesian product of the two tables. If ~tab_a~ has
1316
1316
  ~N~ rows and ~tab_b~ has ~M~ rows, the output table will have ~N * M~ rows.
1317
+ So be careful lest you consume all your computer's memory.
1317
1318
 
1318
1319
  #+HEADER: :colnames no :session readme :hlines yes :wrap EXAMPLE :exports both
1319
1320
  #+BEGIN_SRC ruby
@@ -1351,10 +1352,10 @@ Finally, a cross join outputs every row of ~tab_a~ augmented with every row of
1351
1352
 
1352
1353
  *** Set Operations
1353
1354
 
1354
- ~FatTable~ can perform several set operations on tables. In order for two tables
1355
- to be used this way, they must have the same number of columns with the same
1356
- types or an exception will be raised. We'll call two tables that qualify for
1357
- combining with set operations "set-compatible."
1355
+ ~FatTable~ can perform several set operations on pairs of tables. In order for
1356
+ two tables to be used this way, they must have the same number of columns with
1357
+ the same types or an exception will be raised. We'll call two tables that
1358
+ qualify for combining with set operations "set-compatible."
1358
1359
 
1359
1360
  We'll use the following two set-compatible tables in the examples. They each
1360
1361
  have some duplicates and some group boundaries so you can see the effect of the
@@ -1766,9 +1767,9 @@ but ruby data structures, and for them, things such as alignment are irrelevant.
1766
1767
  array of array,
1767
1768
 
1768
1769
  These are all implemented by classes that inherit from ~FatTable::Formatter~
1769
- class by defining about a dozen methods that get called at various places during
1770
- the construction of the output table. The idea is that more classes can be
1771
- defined by adding additional classes.
1770
+ class by defining about a dozen methods that get called at various places
1771
+ during the construction of the output table. The idea is that more output
1772
+ formats can be defined by adding additional classes.
1772
1773
 
1773
1774
  *** Table Locations
1774
1775
 
data/fat_table.gemspec CHANGED
@@ -64,22 +64,20 @@ Gem::Specification.new do |spec|
64
64
  spec.metadata['yard.run'] = 'yri' # use "yard" to build full HTML docs.
65
65
 
66
66
  spec.add_development_dependency 'bundler'
67
- spec.add_development_dependency 'byebug'
67
+ spec.add_development_dependency 'debug', '>= 1.0.0'
68
68
  spec.add_development_dependency 'pry'
69
- spec.add_development_dependency 'pry-byebug'
70
69
  spec.add_development_dependency 'pry-doc'
71
70
  spec.add_development_dependency 'rake', '~> 13.0'
72
71
  spec.add_development_dependency 'redcarpet'
72
+ spec.add_development_dependency 'pg'
73
73
  spec.add_development_dependency 'rspec', '~> 3.0'
74
74
  spec.add_development_dependency 'rubocop-rspec'
75
75
  spec.add_development_dependency 'rubocop-performance'
76
76
  spec.add_development_dependency 'simplecov'
77
77
 
78
78
  spec.add_runtime_dependency 'activesupport', '>3.0'
79
- spec.add_runtime_dependency 'fat_core', '>= 4.1'
80
- spec.add_runtime_dependency 'mysql2'
81
- spec.add_runtime_dependency 'pg'
79
+ spec.add_runtime_dependency 'fat_core', '>= 4.9.0'
82
80
  spec.add_runtime_dependency 'rainbow'
83
81
  spec.add_runtime_dependency 'sequel'
84
- spec.add_runtime_dependency 'sqlite3'
82
+ spec.add_runtime_dependency 'gem-path'
85
83
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Column objects are a thin wrapper around an Array to allow columns to be
3
5
  # summed and have other aggregate operations performed on them, but compacting
@@ -81,7 +83,7 @@ module FatTable
81
83
  # col.type #=> 'Numeric'
82
84
  # col.header #=> :prices
83
85
  # col.sum #=> 18376.75
84
- def initialize(header:, items: [])
86
+ def initialize(header:, items: [], type: 'NilClass')
85
87
  @raw_header = header
86
88
  @header =
87
89
  if @raw_header.is_a?(Symbol)
@@ -89,7 +91,7 @@ module FatTable
89
91
  else
90
92
  @raw_header.to_s.as_sym
91
93
  end
92
- @type = 'NilClass'
94
+ @type = type
93
95
  msg = "unknown column type '#{type}"
94
96
  raise UserError, msg unless TYPES.include?(@type.to_s)
95
97
 
@@ -137,6 +139,19 @@ module FatTable
137
139
  size - 1
138
140
  end
139
141
 
142
+ # :category: Attributes
143
+
144
+ # Force the column to have String type and then convert all items to
145
+ # strings.
146
+ def force_to_string_type
147
+ # msg = "Can only force an empty column to String type"
148
+ # raise UserError, msg unless empty?
149
+ @type = 'String'
150
+ unless empty?
151
+ @items = items.map(&:to_s)
152
+ end
153
+ end
154
+
140
155
  ##########################################################################
141
156
  # Enumerable
142
157
  ##########################################################################
@@ -483,34 +498,55 @@ module FatTable
483
498
  end
484
499
  end
485
500
 
486
- IS0_DATE_RE = %r{\b(\d\d\d\d)[-/](\d\d?)[-/](\d\d?)\s*
487
- (T\d\d:\d\d:\d\d(\+\d\d:\d\d)?)?\b}x
488
- AMR_DATE_RE = %r{\b(\d\d?)[-/](\d\d?)[-/](\d\d\d\d)\s*
489
- (T\d\d:\d\d:\d\d(\+\d\d:\d\d)?)?\b}x
490
-
491
- # Convert the val to a DateTime if it is either a DateTime, a Date, or a
501
+ ISO_DATE_RE = %r{(?<yr>\d\d\d\d)[-\/]
502
+ (?<mo>\d\d?)[-\/]
503
+ (?<dy>\d\d?)\s*
504
+ (T?\s*\d\d:\d\d(:\d\d)?
505
+ ([-+](\d\d?)(:\d\d?))?)?}x
506
+
507
+ AMR_DATE_RE = %r{(?<dy>\d\d?)[-/](?<mo>\d\d?)[-/](?<yr>\d\d\d\d)\s*
508
+ (?<tm>T\d\d:\d\d:\d\d(\+\d\d:\d\d)?)?}x
509
+
510
+ # A Date like 'Tue, 01 Nov 2016' or 'Tue 01 Nov 2016' or '01 Nov 2016'.
511
+ # These are emitted by Postgresql, so it makes from_sql constructor
512
+ # possible without special formatting of the dates.
513
+ INV_DATE_RE = %r{((mon|tue|wed|thu|fri|sat|sun)[a-zA-z]*,?)?\s+ # looks like dow
514
+ (?<dy>\d\d?)\s+ # one or two-digit day
515
+ (?<mo_name>[jfmasondJFMASOND][A-Za-z]{2,})\s+ # looks like a month name
516
+ (?<yr>\d\d\d\d) # and a 4-digit year
517
+ }xi
518
+
519
+ # Convert the val to a DateTime if it is either a DateTime, a Date, a Time, or a
492
520
  # String that can be parsed as a DateTime, otherwise return nil. It only
493
- # recognizes strings that contain a something like '2016-01-14' or
494
- # '2/12/1985' within them, otherwise DateTime.parse would treat many bare
495
- # numbers as dates, such as '2841381', which it would recognize as a valid
496
- # date, but the user probably does not intend it to be so treated.
521
+ # recognizes strings that contain a something like '2016-01-14' or '2/12/1985'
522
+ # within them, otherwise DateTime.parse would treat many bare numbers as dates,
523
+ # such as '2841381', which it would recognize as a valid date, but the user
524
+ # probably does not intend it to be so treated.
497
525
  def convert_to_date_time(val)
498
526
  return val if val.is_a?(DateTime)
499
527
  return val if val.is_a?(Date)
528
+ return val.to_datetime if val.is_a?(Time)
500
529
  begin
501
- val = val.to_s.clean
502
- return nil if val.blank?
503
- if val.match?(IS0_DATE_RE)
504
- val = DateTime.parse(val)
505
- elsif val =~ AMR_DATE_RE
506
- val = DateTime.new($3.to_i, $1.to_i, $2.to_i)
530
+ str = val.to_s.clean
531
+ return nil if str.blank?
532
+
533
+ if str.match(ISO_DATE_RE)
534
+ date = DateTime.parse(val)
535
+ elsif str =~ AMR_DATE_RE
536
+ date = DateTime.new(Regexp.last_match[:yr].to_i,
537
+ Regexp.last_match[:mo].to_i,
538
+ Regexp.last_match[:dy].to_i)
539
+ elsif str =~ INV_DATE_RE
540
+ mo = Date.mo_name_to_num(last_match[:mo_name])
541
+ date = DateTime.new(Regexp.last_match[:yr].to_i, mo,
542
+ Regexp.last_match[:dy].to_i)
507
543
  else
508
544
  return nil
509
545
  end
510
- val = val.to_date if val.seconds_since_midnight.zero?
511
- val
546
+ # val = val.to_date if
547
+ date.seconds_since_midnight.zero? ? date.to_date : date
512
548
  rescue ArgumentError
513
- return nil
549
+ nil
514
550
  end
515
551
  end
516
552
 
@@ -530,8 +566,8 @@ module FatTable
530
566
  BigDecimal(val.to_s.clean)
531
567
  when /\A[-+]?[\d]+\z/
532
568
  val.to_i
533
- when %r{\A([-+]?\d+)\s*[:/]\s*([-+]?\d+)\z}
534
- Rational($1, $2)
569
+ when %r{\A(?<nm>[-+]?\d+)\s*[:/]\s*(?<dn>[-+]?\d+)\z}
570
+ Rational(Regexp.last_match[:nm], Regexp.last_match[:dn])
535
571
  end
536
572
  end
537
573
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Set and access a database by module-level methods.
2
4
  module FatTable
3
5
  class << self
@@ -20,8 +22,9 @@ module FatTable
20
22
  #
21
23
  # +adapter+::
22
24
  # One of 'pg' (for Postgresql), 'mysql' or 'mysql2' (for Mysql), or
23
- # 'sqlite' (for SQLite3) to specify the +Sequel+ driver to use. You may
24
- # have to install the driver to make this work. By default use 'Pg'.
25
+ # 'sqlite' (for SQLite3) (or any other adapter supported by the +Sequel+
26
+ # gem) to specify the driver to use. You may have to install the
27
+ # appropriate driver to make this work.
25
28
  #
26
29
  # +database+::
27
30
  # The name of the database to access. There is no default for this.
@@ -55,8 +58,17 @@ module FatTable
55
58
  # Set the dsn for Sequel
56
59
  begin
57
60
  self.handle = Sequel.connect(args)
58
- rescue Sequel::Error => ex
59
- raise TransientError, "#{args}: #{ex}"
61
+ rescue Sequel::AdapterNotFound => ex
62
+ case ex.to_s
63
+ when /pg/
64
+ raise TransientError, 'You need to install the postgres adapter pg'
65
+ when /mysql/
66
+ raise TransientError, 'You need to install the mysql adapter'
67
+ when /sqlite/
68
+ raise TransientError, 'You need to install the sqlite adapter'
69
+ else
70
+ raise ex
71
+ end
60
72
  end
61
73
  handle
62
74
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Raised when the caller of the code made an error that the caller can
3
5
  # correct.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # The Evaluator class provides a class for evaluating Ruby expressions based
3
5
  # on variable settings provided at runtime. If the same Evaluator object is
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A subclass of Formatter for rendering the table as a Ruby Array of Arrays.
3
5
  # Each cell is formatted as a string in accordance with the formatting
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A subclass of Formatter for rendering the table as a Ruby Array of Hashes.
3
5
  # Each row of the Array is a Hash representing one row of the table with the
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A Formatter is for use in Table output routines, and provides methods for
3
5
  # adding group and table footers to the output and instructions for how the
@@ -73,7 +75,7 @@ module FatTable
73
75
  false_color: 'none',
74
76
  false_bgcolor: 'none',
75
77
  underline: false,
76
- blink: false
78
+ blink: false,
77
79
  }
78
80
 
79
81
  class_attribute :valid_colors
@@ -577,9 +579,9 @@ module FatTable
577
579
  # parse, we remove the matched construct from fmt. At the end, any
578
580
  # remaining characters in fmt should be invalid.
579
581
  fmt_hash = {}
580
- if fmt =~ /c\[(#{CLR_RE})(\.(#{CLR_RE}))?\]/
581
- fmt_hash[:color] = $1 unless $1.blank?
582
- fmt_hash[:bgcolor] = $3 unless $3.blank?
582
+ if fmt =~ /c\[(?<co>#{CLR_RE})(\.(?<bg>#{CLR_RE}))?\]/
583
+ fmt_hash[:color] = Regexp.last_match[:co] unless Regexp.last_match[:co].blank?
584
+ fmt_hash[:bgcolor] = Regexp.last_match[:bg] unless Regexp.last_match[:bg].blank?
583
585
  validate_color(fmt_hash[:color])
584
586
  validate_color(fmt_hash[:bgcolor])
585
587
  fmt = fmt.sub($&, '')
@@ -599,12 +601,12 @@ module FatTable
599
601
  fmt_hash[:case] = :title
600
602
  fmt = fmt.sub($&, '')
601
603
  end
602
- if fmt =~ /(~\s*)?B/
603
- fmt_hash[:bold] = !$1
604
+ if fmt =~ /(?<neg>~\s*)?B/
605
+ fmt_hash[:bold] = !Regexp.last_match[:neg]
604
606
  fmt = fmt.sub($&, '')
605
607
  end
606
- if fmt =~ /(~\s*)?I/
607
- fmt_hash[:italic] = !$1
608
+ if fmt =~ /(?<neg>~\s*)?I/
609
+ fmt_hash[:italic] = !Regexp.last_match[:neg]
608
610
  fmt = fmt.sub($&, '')
609
611
  end
610
612
  if fmt =~ /R/
@@ -619,12 +621,12 @@ module FatTable
619
621
  fmt_hash[:alignment] = :left
620
622
  fmt = fmt.sub($&, '')
621
623
  end
622
- if fmt =~ /(~\s*)?_/
623
- fmt_hash[:underline] = !$1
624
+ if fmt =~ /(?<neg>~\s*)?_/
625
+ fmt_hash[:underline] = !Regexp.last_match[:neg]
624
626
  fmt = fmt.sub($&, '')
625
627
  end
626
- if fmt =~ /(~\s*)?\*/
627
- fmt_hash[:blink] = !$1
628
+ if fmt =~ /(?<neg>~\s*)?\*/
629
+ fmt_hash[:blink] = !Regexp.last_match[:neg]
628
630
  fmt = fmt.sub($&, '')
629
631
  end
630
632
  [fmt_hash, fmt]
@@ -639,9 +641,9 @@ module FatTable
639
641
  # parse, we remove the matched construct from fmt. At the end, any
640
642
  # remaining characters in fmt should be invalid.
641
643
  fmt_hash = {}
642
- if fmt =~ /n\[\s*([^\]]*)\s*\]/
643
- fmt_hash[:nil_text] = $1.clean
644
- fmt = fmt.sub($&, '')
644
+ if fmt =~ /n\[\s*(?<bdy>[^\]]*)\s*\]/
645
+ fmt_hash[:nil_text] = Regexp.last_match[:bdy].clean
646
+ fmt = fmt.sub(Regexp.last_match[0], '')
645
647
  end
646
648
  [fmt_hash, fmt]
647
649
  end
@@ -655,22 +657,22 @@ module FatTable
655
657
  # parse, we remove the matched construct from fmt. At the end, any
656
658
  # remaining characters in fmt should be invalid.
657
659
  fmt_hash, fmt = parse_str_fmt(fmt)
658
- if fmt =~ /(\d+).(\d+)/
659
- fmt_hash[:pre_digits] = $1.to_i
660
- fmt_hash[:post_digits] = $2.to_i
661
- fmt = fmt.sub($&, '')
660
+ if fmt =~ /(?<pre>\d+).(?<post>\d+)/
661
+ fmt_hash[:pre_digits] = Regexp.last_match[:pre].to_i
662
+ fmt_hash[:post_digits] = Regexp.last_match[:post].to_i
663
+ fmt = fmt.sub(Regexp.last_match[0], '')
662
664
  end
663
- if fmt =~ /(~\s*)?,/
664
- fmt_hash[:commas] = !$1
665
- fmt = fmt.sub($&, '')
665
+ if fmt =~ /(?<neg>~\s*)?,/
666
+ fmt_hash[:commas] = !Regexp.last_match[:neg]
667
+ fmt = fmt.sub(Regexp.last_match[0], '')
666
668
  end
667
- if fmt =~ /(~\s*)?\$/
668
- fmt_hash[:currency] = !$1
669
- fmt = fmt.sub($&, '')
669
+ if fmt =~ /(?<neg>~\s*)?\$/
670
+ fmt_hash[:currency] = !Regexp.last_match[:neg]
671
+ fmt = fmt.sub(Regexp.last_match[0], '')
670
672
  end
671
- if fmt =~ /(~\s*)?H/
672
- fmt_hash[:hms] = !$1
673
- fmt = fmt.sub($&, '')
673
+ if fmt =~ /(?<neg>~\s*)?H/
674
+ fmt_hash[:hms] = !Regexp.last_match[:neg]
675
+ fmt = fmt.sub(Regexp.last_match[0], '')
674
676
  end
675
677
  unless fmt.blank? || !strict
676
678
  raise UserError, "unrecognized numeric formatting instructions '#{fmt}'"
@@ -688,13 +690,13 @@ module FatTable
688
690
  # parse, we remove the matched construct from fmt. At the end, any
689
691
  # remaining characters in fmt should be invalid.
690
692
  fmt_hash, fmt = parse_str_fmt(fmt)
691
- if fmt =~ /d\[([^\]]*)\]/
692
- fmt_hash[:date_fmt] = $1
693
- fmt = fmt.sub($&, '')
693
+ if fmt =~ /d\[(?<bdy>[^\]]*)\]/
694
+ fmt_hash[:date_fmt] = Regexp.last_match[:bdy]
695
+ fmt = fmt.sub(Regexp.last_match[0], '')
694
696
  end
695
- if fmt =~ /D\[([^\]]*)\]/
696
- fmt_hash[:date_fmt] = $1
697
- fmt = fmt.sub($&, '')
697
+ if fmt =~ /D\[(?<bdy>[^\]]*)\]/
698
+ fmt_hash[:date_fmt] = Regexp.last_match[:bdy]
699
+ fmt = fmt.sub(Regexp.last_match[0], '')
698
700
  end
699
701
  unless fmt.blank? || !strict
700
702
  msg = "unrecognized datetime formatting instructions '#{fmt}'"
@@ -712,37 +714,38 @@ module FatTable
712
714
  # parse, we remove the matched construct from fmt. At the end, any
713
715
  # remaining characters in fmt should be invalid.
714
716
  fmt_hash = {}
715
- if fmt =~ /b\[\s*([^\],]*),([^\]]*)\s*\]/
716
- fmt_hash[:true_text] = $1.clean
717
- fmt_hash[:false_text] = $2.clean
718
- fmt = fmt.sub($&, '')
717
+ if fmt =~ /b\[\s*(?<t>[^\],]*),(?<f>[^\]]*)\s*\]/
718
+ fmt_hash[:true_text] = Regexp.last_match[:t].clean
719
+ fmt_hash[:false_text] = Regexp.last_match[:f].clean
720
+ fmt = fmt.sub(Regexp.last_match[0], '')
719
721
  end
720
722
  # Since true_text, false_text and nil_text may want to have internal
721
723
  # spaces, defer removing extraneous spaces until after they are parsed.
722
724
  if fmt =~ /c\[(#{CLR_RE})(\.(#{CLR_RE}))?,
723
725
  \s*(#{CLR_RE})(\.(#{CLR_RE}))?\]/x
724
- fmt_hash[:true_color] = $1 unless $1.blank?
725
- fmt_hash[:true_bgcolor] = $3 unless $3.blank?
726
- fmt_hash[:false_color] = $4 unless $4.blank?
727
- fmt_hash[:false_bgcolor] = $6 unless $6.blank?
728
- fmt = fmt.sub($&, '')
726
+ tco, _, tbg, fco, _, fbg = Regexp.last_match.captures
727
+ fmt_hash[:true_color] = tco unless tco.blank?
728
+ fmt_hash[:true_bgcolor] = tbg unless tbg.blank?
729
+ fmt_hash[:false_color] = fco unless fco.blank?
730
+ fmt_hash[:false_bgcolor] = fbg unless fbg.blank?
731
+ fmt = fmt.sub(Regexp.last_match[0], '')
729
732
  end
730
733
  str_fmt_hash, fmt = parse_str_fmt(fmt)
731
734
  fmt_hash = fmt_hash.merge(str_fmt_hash)
732
735
  if fmt =~ /Y/
733
736
  fmt_hash[:true_text] = 'Y'
734
737
  fmt_hash[:false_text] = 'N'
735
- fmt = fmt.sub($&, '')
738
+ fmt = fmt.sub(Regexp.last_match[0], '')
736
739
  end
737
740
  if fmt =~ /T/
738
741
  fmt_hash[:true_text] = 'T'
739
742
  fmt_hash[:false_text] = 'F'
740
- fmt = fmt.sub($&, '')
743
+ fmt = fmt.sub(Regexp.last_match[0], '')
741
744
  end
742
745
  if fmt =~ /X/
743
746
  fmt_hash[:true_text] = 'X'
744
747
  fmt_hash[:false_text] = ''
745
- fmt = fmt.sub($&, '')
748
+ fmt = fmt.sub(Regexp.last_match[0], '')
746
749
  end
747
750
  unless fmt.blank? || !strict
748
751
  raise UserError, "unrecognized boolean formatting instructions '#{fmt}'"
@@ -1072,7 +1075,10 @@ module FatTable
1072
1075
  :body
1073
1076
  end
1074
1077
  table.headers.each do |h|
1075
- grp_col[h] ||= Column.new(header: h)
1078
+ # We set the column type here in case the column type was forced
1079
+ # to String.
1080
+ # grp_col[h] ||= Column.new(header: h)
1081
+ grp_col[h] ||= Column.new(header: h, type: table.type(h))
1076
1082
  grp_col[h] << row[h]
1077
1083
  istruct = format_at[location][h]
1078
1084
  new_row[h] = [row[h], format_cell(row[h], istruct,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Output the table in the same way as org-mode for emacs does. This is almost
3
5
  # identical to TextFormatter except that dates do get formatted as inactive
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rainbow'
2
4
 
3
5
  module FatTable
@@ -26,10 +28,10 @@ module FatTable
26
28
  super
27
29
  @options[:unicode] = options.fetch(:unicode, true)
28
30
  @options[:framecolor] = options.fetch(:framecolor, 'none.none')
29
- return unless @options[:framecolor] =~ /([-_a-zA-Z]*)(\.([-_a-zA-Z]*))/
31
+ return unless @options[:framecolor] =~ /(?<co>[-_a-zA-Z]*)(\.(?<bg>[-_a-zA-Z]*))/
30
32
 
31
- @options[:frame_fg] = $1.downcase unless $1.blank?
32
- @options[:frame_bg] = $3.downcase unless $3.blank?
33
+ @options[:frame_fg] = Regexp.last_match[:co].downcase unless Regexp.last_match[:co].blank?
34
+ @options[:frame_bg] = Regexp.last_match[:bg].downcase unless Regexp.last_match[:bg].blank?
33
35
  end
34
36
 
35
37
  # Valid colors for ANSI terminal using the rainbow gem's X11ColorNames.
@@ -101,18 +103,18 @@ module FatTable
101
103
  # Unicode line-drawing characters. We use double lines before and after the
102
104
  # table and single lines for the sides and hlines between groups and
103
105
  # footers.
104
- UPPER_LEFT = "\u2552".freeze
105
- UPPER_RIGHT = "\u2555".freeze
106
- DOUBLE_RULE = "\u2550".freeze
107
- UPPER_TEE = "\u2564".freeze
108
- VERTICAL_RULE = "\u2502".freeze
109
- LEFT_TEE = "\u251C".freeze
110
- HORIZONTAL_RULE = "\u2500".freeze
111
- SINGLE_CROSS = "\u253C".freeze
112
- RIGHT_TEE = "\u2524".freeze
113
- LOWER_LEFT = "\u2558".freeze
114
- LOWER_RIGHT = "\u255B".freeze
115
- LOWER_TEE = "\u2567".freeze
106
+ UPPER_LEFT = "\u2552"
107
+ UPPER_RIGHT = "\u2555"
108
+ DOUBLE_RULE = "\u2550"
109
+ UPPER_TEE = "\u2564"
110
+ VERTICAL_RULE = "\u2502"
111
+ LEFT_TEE = "\u251C"
112
+ HORIZONTAL_RULE = "\u2500"
113
+ SINGLE_CROSS = "\u253C"
114
+ RIGHT_TEE = "\u2524"
115
+ LOWER_LEFT = "\u2558"
116
+ LOWER_RIGHT = "\u255B"
117
+ LOWER_TEE = "\u2567"
116
118
  # :startdoc:
117
119
 
118
120
  def upper_left
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Output the table as plain text. This is almost identical to OrgFormatter
3
5
  # except that dates do not get formatted as inactive timestamps and the
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fat_table/formatters/formatter'
2
4
  require 'fat_table/formatters/aoa_formatter'
3
5
  require 'fat_table/formatters/aoh_formatter'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  unless { a: 1 }.respond_to?(:fetch_values)
2
4
  # Add fetch_values if this version of ruby does not define it.
3
5
  class Hash
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A container for a two-dimensional table. All cells in the table must be a
3
5
  # String, a DateTime (or Date), a Numeric (Bignum, Integer, or BigDecimal), or
@@ -156,7 +158,8 @@ module FatTable
156
158
  raise UserError, msg if FatTable.db.nil?
157
159
 
158
160
  result = Table.new
159
- FatTable.db[query].each do |h|
161
+ rows = FatTable.db[query]
162
+ rows.each do |h|
160
163
  result << h
161
164
  end
162
165
  result
@@ -295,6 +298,8 @@ module FatTable
295
298
  # :category: Attributes
296
299
 
297
300
  # Return the table's Column with the given +key+ as its header.
301
+ # @param key [Symbol] symbol for header of column to return
302
+ # @return [FatTable::Column]
298
303
  def column(key)
299
304
  columns.detect { |c| c.header == key.as_sym }
300
305
  end
@@ -309,6 +314,15 @@ module FatTable
309
314
 
310
315
  # :category: Attributes
311
316
 
317
+ # Set the column type for Column with the given +key+ as a String type,
318
+ # but only if empty. Otherwise, we would have to worry about converting
319
+ # existing items in the column to String. Perhaps that's a TODO.
320
+ def set_column_to_string_type(key)
321
+ column(key).force_to_string_type
322
+ end
323
+
324
+ # :category: Attributes
325
+
312
326
  # Return the array of items of the column with the given header symbol
313
327
  # +key+, or if +key+ is an Integer, return that row at that index. So a
314
328
  # table's rows can be accessed by number, and its columns can be accessed by
@@ -880,10 +894,7 @@ module FatTable
880
894
  # Apply the set operation given by ~oper~ between this table and the other
881
895
  # table given in the first argument. If distinct is true, eliminate
882
896
  # duplicates from the result.
883
- def set_operation(other, oper = :+,
884
- distinct: true,
885
- add_boundaries: true,
886
- inherit_boundaries: false)
897
+ def set_operation(other, oper = :+, distinct: true, add_boundaries: true, inherit_boundaries: false)
887
898
  unless columns.size == other.columns.size
888
899
  msg = "can't apply set ops to tables with a different number of columns"
889
900
  raise UserError, msg
@@ -981,6 +992,11 @@ module FatTable
981
992
  #
982
993
  # Any groups present in either Table are eliminated in the output Table. See
983
994
  # the README for examples.
995
+ # @param other [FatTable::Table] table to join with self
996
+ # @param exps [Array<String>, Array<Symbol>] table to join with self
997
+ # @param join_type [Array<String>, Array<Symbol>] type of join :inner, :left, :right, :full, :cross
998
+ # @return [FatTable::Table] result of joining self to other
999
+ #
984
1000
  def join(other, *exps, join_type: :inner)
985
1001
  unless other.is_a?(Table)
986
1002
  raise UserError, 'need other table as first argument to join'
@@ -1083,10 +1099,10 @@ module FatTable
1083
1099
  # Translate any remaining row_b heads to append '_b' if they have the
1084
1100
  # same name as a row_a key.
1085
1101
  a_heads = row_a.keys
1086
- row_b = row_b.to_a.each.map { |k, v|
1102
+ row_b = row_b.to_a.each.map do |k, v|
1087
1103
  [a_heads.include?(k) ? "#{k}_b".to_sym : k, v]
1088
- }.to_h
1089
- row_a.merge(row_b)
1104
+ end
1105
+ row_a.merge(row_b.to_h)
1090
1106
  end
1091
1107
 
1092
1108
  # Return a hash for the local variables of a join expression in which all
@@ -1125,7 +1141,7 @@ module FatTable
1125
1141
  [nat_exp, common_heads]
1126
1142
  end
1127
1143
  else
1128
- # We have expressions to evaluate
1144
+ # We have join expressions to evaluate
1129
1145
  and_conds = []
1130
1146
  partial_result = nil
1131
1147
  last_sym = nil
@@ -1133,8 +1149,8 @@ module FatTable
1133
1149
  case exp
1134
1150
  when Symbol
1135
1151
  case exp.to_s.clean
1136
- when /\A(.*)_a\z/
1137
- a_head = $1.to_sym
1152
+ when /\A(?<sy>.*)_a\z/
1153
+ a_head = Regexp.last_match[:sy].to_sym
1138
1154
  unless a_heads.include?(a_head)
1139
1155
  raise UserError, "no column '#{a_head}' in table"
1140
1156
  end
@@ -1149,11 +1165,11 @@ module FatTable
1149
1165
  partial_result = nil
1150
1166
  else
1151
1167
  # First of a pair of _a or _b
1152
- partial_result = "(#{a_head}_a == "
1168
+ partial_result = String.new("(#{a_head}_a == ")
1153
1169
  end
1154
1170
  last_sym = a_head
1155
- when /\A(.*)_b\z/
1156
- b_head = $1.to_sym
1171
+ when /\A(?<sy>.*)_b\z/
1172
+ b_head = Regexp.last_match[:sy].to_sym
1157
1173
  unless b_heads.include?(b_head)
1158
1174
  raise UserError, "no column '#{b_head}' in second table"
1159
1175
  end
@@ -1168,7 +1184,7 @@ module FatTable
1168
1184
  partial_result = nil
1169
1185
  else
1170
1186
  # First of a pair of _a or _b
1171
- partial_result = "(#{b_head}_b == "
1187
+ partial_result = String.new("(#{b_head}_b == ")
1172
1188
  end
1173
1189
  b_common_heads << b_head
1174
1190
  last_sym = b_head
@@ -1275,6 +1291,15 @@ module FatTable
1275
1291
 
1276
1292
  # :category: Constructors
1277
1293
 
1294
+ # Add a group boundary mark at the given row, or at the end of the table
1295
+ # by default.
1296
+ def add_boundary(at_row = nil)
1297
+ row = at_row || (size - 1)
1298
+ @boundaries << row
1299
+ end
1300
+
1301
+ # :category: Constructors
1302
+
1278
1303
  # Add a +row+ represented by a Hash having the headers as keys. If +mark:+
1279
1304
  # is set true, mark this row as a boundary. All tables should be built
1280
1305
  # ultimately using this method as a primitive.
@@ -1284,7 +1309,7 @@ module FatTable
1284
1309
  columns << Column.new(header: k) unless column?(k)
1285
1310
  column(key) << v
1286
1311
  end
1287
- @boundaries << (size - 1) if mark
1312
+ add_boundary if mark
1288
1313
  self
1289
1314
  end
1290
1315
 
@@ -1353,9 +1378,9 @@ module FatTable
1353
1378
 
1354
1379
  method = "to_#{fmt}"
1355
1380
  if block_given?
1356
- send method, options, &Proc.new
1381
+ send(method, options, &Proc.new)
1357
1382
  else
1358
- send method, options
1383
+ send(method, options)
1359
1384
  end
1360
1385
  end
1361
1386
 
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # The current version of FatTable
3
- VERSION = '0.2.11'.freeze
5
+ VERSION = '0.3.4'
4
6
  end
data/lib/fat_table.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This module provides objects for treating tables as a data type on which you
2
4
  # can (1) perform operations, such as select, where, join, and others and (2)
3
5
  # output the tables in several formats, including text, ANSI terminal, LaTeX,
@@ -24,6 +26,15 @@ module FatTable
24
26
  require 'fat_table/db_handle'
25
27
  require 'fat_table/errors'
26
28
 
29
+ # Add paths for common db gems to the load paths
30
+ %w[pg mysql2 sqlite].each do |gem_name|
31
+ path = Dir.glob("#{ENV['GEM_HOME']}/gems/#{gem_name}*").sort.last
32
+ if path
33
+ path = File.join(path, 'lib')
34
+ $LOAD_PATH << path unless $LOAD_PATH.include?(path)
35
+ end
36
+ end
37
+
27
38
  # Valid output formats as symbols.
28
39
  FORMATS = %i[psv aoa aoh latex org term text].freeze
29
40
 
@@ -149,9 +160,9 @@ module FatTable
149
160
  raise UserError, "unknown format '#{fmt}'" unless FORMATS.include?(fmt)
150
161
  method = "to_#{fmt}"
151
162
  if block_given?
152
- send method, table, options, &Proc.new
163
+ send(method, table, options, &Proc.new)
153
164
  else
154
- send method, table, options
165
+ send(method, table, options)
155
166
  end
156
167
  end
157
168
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fat_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.11
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel E. Doherty
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-29 00:00:00.000000000 Z
11
+ date: 2022-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: byebug
28
+ name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 1.0.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 1.0.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: pry-byebug
56
+ name: pry-doc
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,35 +67,35 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: pry-doc
70
+ name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '13.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '13.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rake
84
+ name: redcarpet
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '13.0'
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '13.0'
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: redcarpet
98
+ name: pg
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -184,42 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - ">="
186
186
  - !ruby/object:Gem::Version
187
- version: '4.1'
188
- type: :runtime
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: '4.1'
195
- - !ruby/object:Gem::Dependency
196
- name: mysql2
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :runtime
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: '0'
209
- - !ruby/object:Gem::Dependency
210
- name: pg
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - ">="
214
- - !ruby/object:Gem::Version
215
- version: '0'
187
+ version: 4.9.0
216
188
  type: :runtime
217
189
  prerelease: false
218
190
  version_requirements: !ruby/object:Gem::Requirement
219
191
  requirements:
220
192
  - - ">="
221
193
  - !ruby/object:Gem::Version
222
- version: '0'
194
+ version: 4.9.0
223
195
  - !ruby/object:Gem::Dependency
224
196
  name: rainbow
225
197
  requirement: !ruby/object:Gem::Requirement
@@ -249,7 +221,7 @@ dependencies:
249
221
  - !ruby/object:Gem::Version
250
222
  version: '0'
251
223
  - !ruby/object:Gem::Dependency
252
- name: sqlite3
224
+ name: gem-path
253
225
  requirement: !ruby/object:Gem::Requirement
254
226
  requirements:
255
227
  - - ">="
@@ -334,7 +306,7 @@ licenses: []
334
306
  metadata:
335
307
  allowed_push_host: https://rubygems.org
336
308
  yard.run: yri
337
- post_install_message:
309
+ post_install_message:
338
310
  rdoc_options: []
339
311
  require_paths:
340
312
  - lib
@@ -349,8 +321,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
349
321
  - !ruby/object:Gem::Version
350
322
  version: '0'
351
323
  requirements: []
352
- rubygems_version: 3.1.2
353
- signing_key:
324
+ rubygems_version: 3.3.3
325
+ signing_key:
354
326
  specification_version: 4
355
327
  summary: Provides tools for working with tables as a data type.
356
328
  test_files: []