dentaku 3.2.0 → 3.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +7 -2
- data/lib/dentaku.rb +4 -0
- data/lib/dentaku/ast/arithmetic.rb +8 -0
- data/lib/dentaku/ast/comparators.rb +16 -6
- data/lib/dentaku/ast/function.rb +2 -1
- data/lib/dentaku/ast/functions/and.rb +2 -2
- data/lib/dentaku/ast/functions/or.rb +4 -4
- data/lib/dentaku/bulk_expression_solver.rb +6 -2
- data/lib/dentaku/calculator.rb +1 -1
- data/lib/dentaku/exceptions.rb +7 -4
- data/lib/dentaku/version.rb +1 -1
- data/spec/ast/comparator_spec.rb +26 -1
- data/spec/ast/function_spec.rb +6 -6
- data/spec/calculator_spec.rb +87 -2
- data/spec/dentaku_spec.rb +1 -1
- data/spec/external_function_spec.rb +3 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bc147a87584da15958dfa99d62dcbc680333b21d2f9a35758ab11b4d7327787b
|
4
|
+
data.tar.gz: a3138608c305adc7ff88168e5379bc5f7da7fa0712b60d9f5d4afb8c63bfa2c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24da7dff044e4909cc1a6f900fb91c1aa30064e940ddf57e1c68112b0d61331b66fa066173012daeb302f757d10ea7ccec1cc505c95d6a8f32c019b2d7d219ff
|
7
|
+
data.tar.gz: 5745ef2e7896a3e0570d236e0b04bdd627659b15da2234855f81adde950c18c3b04d73eaeb34ae836756bfeb37f54bff9886d8730912a32c9e2700161807ac10
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [v3.2.
|
3
|
+
## [v3.2.1] 2018-10-24
|
4
|
+
- make `evaluate` rescue more exceptions
|
5
|
+
|
6
|
+
## [v3.2.0] 2018-03-14
|
4
7
|
- add `COUNT` and `AVG` functions
|
5
8
|
- add unicode support 😎
|
6
9
|
- fix CASE parsing bug
|
@@ -8,7 +11,7 @@
|
|
8
11
|
- add variadic MUL function
|
9
12
|
- performance optimization
|
10
13
|
|
11
|
-
## [v3.1.0]
|
14
|
+
## [v3.1.0] 2018-01-10
|
12
15
|
- allow decimals with no leading zero
|
13
16
|
- nested hash and array support in bulk expression solver
|
14
17
|
- add a variadic SUM function
|
@@ -159,6 +162,8 @@
|
|
159
162
|
## [v0.1.0] 2012-01-20
|
160
163
|
- initial release
|
161
164
|
|
165
|
+
[HEAD]: https://github.com/rubysolo/dentaku/compare/v3.2.1...HEAD
|
166
|
+
[v3.2.1]: https://github.com/rubysolo/dentaku/compare/v3.2.0...v3.2.1
|
162
167
|
[v3.2.0]: https://github.com/rubysolo/dentaku/compare/v3.1.0...v3.2.0
|
163
168
|
[v3.1.0]: https://github.com/rubysolo/dentaku/compare/v3.0.0...v3.1.0
|
164
169
|
[v3.0.0]: https://github.com/rubysolo/dentaku/compare/v2.0.11...v3.0.0
|
data/lib/dentaku.rb
CHANGED
@@ -14,11 +14,21 @@ module Dentaku
|
|
14
14
|
def operator
|
15
15
|
raise NotImplementedError
|
16
16
|
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def value
|
21
|
+
yield
|
22
|
+
rescue ::ArgumentError => argument_error
|
23
|
+
raise Dentaku::ArgumentError, argument_error.message
|
24
|
+
rescue NoMethodError => no_method_error
|
25
|
+
raise Dentaku::Error, no_method_error.message
|
26
|
+
end
|
17
27
|
end
|
18
28
|
|
19
29
|
class LessThan < Comparator
|
20
30
|
def value(context = {})
|
21
|
-
left.value(context) < right.value(context)
|
31
|
+
super() { left.value(context) < right.value(context) }
|
22
32
|
end
|
23
33
|
|
24
34
|
def operator
|
@@ -28,7 +38,7 @@ module Dentaku
|
|
28
38
|
|
29
39
|
class LessThanOrEqual < Comparator
|
30
40
|
def value(context = {})
|
31
|
-
left.value(context) <= right.value(context)
|
41
|
+
super() { left.value(context) <= right.value(context) }
|
32
42
|
end
|
33
43
|
|
34
44
|
def operator
|
@@ -38,7 +48,7 @@ module Dentaku
|
|
38
48
|
|
39
49
|
class GreaterThan < Comparator
|
40
50
|
def value(context = {})
|
41
|
-
left.value(context) > right.value(context)
|
51
|
+
super() { left.value(context) > right.value(context) }
|
42
52
|
end
|
43
53
|
|
44
54
|
def operator
|
@@ -48,7 +58,7 @@ module Dentaku
|
|
48
58
|
|
49
59
|
class GreaterThanOrEqual < Comparator
|
50
60
|
def value(context = {})
|
51
|
-
left.value(context) >= right.value(context)
|
61
|
+
super() { left.value(context) >= right.value(context) }
|
52
62
|
end
|
53
63
|
|
54
64
|
def operator
|
@@ -58,7 +68,7 @@ module Dentaku
|
|
58
68
|
|
59
69
|
class NotEqual < Comparator
|
60
70
|
def value(context = {})
|
61
|
-
left.value(context) != right.value(context)
|
71
|
+
super() { left.value(context) != right.value(context) }
|
62
72
|
end
|
63
73
|
|
64
74
|
def operator
|
@@ -68,7 +78,7 @@ module Dentaku
|
|
68
78
|
|
69
79
|
class Equal < Comparator
|
70
80
|
def value(context = {})
|
71
|
-
left.value(context) == right.value(context)
|
81
|
+
super() { left.value(context) == right.value(context) }
|
72
82
|
end
|
73
83
|
|
74
84
|
def operator
|
data/lib/dentaku/ast/function.rb
CHANGED
@@ -41,7 +41,8 @@ module Dentaku
|
|
41
41
|
return number.include?('.') ? ::BigDecimal.new(number, DIG) : number.to_i if number
|
42
42
|
end
|
43
43
|
|
44
|
-
raise
|
44
|
+
raise Dentaku::ArgumentError.for(:incompatible_type, value: value, for: Numeric),
|
45
|
+
"'#{value || value.class}' is not coercible to numeric"
|
45
46
|
end
|
46
47
|
end
|
47
48
|
end
|
@@ -11,15 +11,15 @@ Dentaku::AST::Function.register(:or, :logical, lambda { |*args|
|
|
11
11
|
|
12
12
|
args.any? do |arg|
|
13
13
|
case arg
|
14
|
-
when TrueClass
|
14
|
+
when TrueClass
|
15
15
|
true
|
16
|
-
when FalseClass
|
16
|
+
when FalseClass, nil
|
17
17
|
false
|
18
18
|
else
|
19
19
|
raise Dentaku::ArgumentError.for(
|
20
20
|
:incompatible_type,
|
21
|
-
function_name: '
|
22
|
-
), '
|
21
|
+
function_name: 'OR()', expect: :logical, actual: arg.class
|
22
|
+
), 'OR() requires arguments to be logical expressions'
|
23
23
|
end
|
24
24
|
end
|
25
25
|
})
|
@@ -20,8 +20,9 @@ module Dentaku
|
|
20
20
|
results = load_results(&error_handler)
|
21
21
|
|
22
22
|
FlatHash.expand(
|
23
|
-
expression_hash.each_with_object({}) do |(k,
|
24
|
-
|
23
|
+
expression_hash.each_with_object({}) do |(k, v), r|
|
24
|
+
default = v.nil? ? v : :undefined
|
25
|
+
r[k] = results.fetch(k.to_s, default)
|
25
26
|
end
|
26
27
|
)
|
27
28
|
end
|
@@ -81,6 +82,9 @@ module Dentaku
|
|
81
82
|
r[var_name] = block.call(ex)
|
82
83
|
end
|
83
84
|
end
|
85
|
+
rescue TSort::Cyclic => ex
|
86
|
+
block.call(ex)
|
87
|
+
{}
|
84
88
|
end
|
85
89
|
|
86
90
|
def expressions
|
data/lib/dentaku/calculator.rb
CHANGED
@@ -46,7 +46,7 @@ module Dentaku
|
|
46
46
|
|
47
47
|
def evaluate(expression, data = {}, &block)
|
48
48
|
evaluate!(expression, data)
|
49
|
-
rescue
|
49
|
+
rescue Dentaku::Error, Dentaku::ArgumentError, Dentaku::ZeroDivisionError => ex
|
50
50
|
block.call(expression, ex) if block_given?
|
51
51
|
end
|
52
52
|
|
data/lib/dentaku/exceptions.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Dentaku
|
2
|
-
class
|
2
|
+
class Error < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class UnboundVariableError < Error
|
3
6
|
attr_accessor :recipient_variable
|
4
7
|
|
5
8
|
attr_reader :unbound_variables
|
@@ -9,7 +12,7 @@ module Dentaku
|
|
9
12
|
end
|
10
13
|
end
|
11
14
|
|
12
|
-
class NodeError <
|
15
|
+
class NodeError < Error
|
13
16
|
attr_reader :child, :expect, :actual
|
14
17
|
|
15
18
|
def initialize(expect, actual, child)
|
@@ -19,7 +22,7 @@ module Dentaku
|
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
22
|
-
class ParseError <
|
25
|
+
class ParseError < Error
|
23
26
|
attr_reader :reason, :meta
|
24
27
|
|
25
28
|
def initialize(reason, **meta)
|
@@ -45,7 +48,7 @@ module Dentaku
|
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
|
-
class TokenizerError <
|
51
|
+
class TokenizerError < Error
|
49
52
|
attr_reader :reason, :meta
|
50
53
|
|
51
54
|
def initialize(reason, **meta)
|
data/lib/dentaku/version.rb
CHANGED
data/spec/ast/comparator_spec.rb
CHANGED
@@ -8,7 +8,10 @@ describe Dentaku::AST::Comparator do
|
|
8
8
|
let(:two) { Dentaku::AST::Numeric.new Dentaku::Token.new(:numeric, 2) }
|
9
9
|
let(:x) { Dentaku::AST::Identifier.new Dentaku::Token.new(:identifier, 'x') }
|
10
10
|
let(:y) { Dentaku::AST::Identifier.new Dentaku::Token.new(:identifier, 'y') }
|
11
|
-
let(:
|
11
|
+
let(:nilly) do
|
12
|
+
Dentaku::AST::Identifier.new Dentaku::Token.new(:identifier, 'nilly')
|
13
|
+
end
|
14
|
+
let(:ctx) { { 'x' => 'hello', 'y' => 'world', 'nilly' => nil } }
|
12
15
|
|
13
16
|
it 'performs comparison with numeric operands' do
|
14
17
|
expect(less_than(one, two).value(ctx)).to be_truthy
|
@@ -18,6 +21,24 @@ describe Dentaku::AST::Comparator do
|
|
18
21
|
expect(equal(x, y).value(ctx)).to be_falsey
|
19
22
|
end
|
20
23
|
|
24
|
+
it 'raises a dentaku argument error when incorrect arguments are passed in' do
|
25
|
+
expect { less_than(one, nilly).value(ctx) }.to raise_error Dentaku::ArgumentError
|
26
|
+
expect { less_than_or_equal(one, nilly).value(ctx) }.to raise_error Dentaku::ArgumentError
|
27
|
+
expect { greater_than(one, nilly).value(ctx) }.to raise_error Dentaku::ArgumentError
|
28
|
+
expect { greater_than_or_equal(one, nilly).value(ctx) }.to raise_error Dentaku::ArgumentError
|
29
|
+
expect { not_equal(one, nilly).value(ctx) }.to_not raise_error
|
30
|
+
expect { equal(one, nilly).value(ctx) }.to_not raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'raises a dentaku error when nil is passed in as first argument' do
|
34
|
+
expect { less_than(nilly, one).value(ctx) }.to raise_error Dentaku::Error
|
35
|
+
expect { less_than_or_equal(nilly, one).value(ctx) }.to raise_error Dentaku::Error
|
36
|
+
expect { greater_than(nilly, one).value(ctx) }.to raise_error Dentaku::Error
|
37
|
+
expect { greater_than_or_equal(nilly, one).value(ctx) }.to raise_error Dentaku::Error
|
38
|
+
expect { not_equal(nilly, one).value(ctx) }.to_not raise_error
|
39
|
+
expect { equal(nilly, one).value(ctx) }.to_not raise_error
|
40
|
+
end
|
41
|
+
|
21
42
|
it 'returns correct operator symbols' do
|
22
43
|
expect(less_than(one, two).operator).to eq(:<)
|
23
44
|
expect(less_than_or_equal(one, two).operator).to eq(:<=)
|
@@ -29,6 +50,10 @@ describe Dentaku::AST::Comparator do
|
|
29
50
|
.to raise_error(NotImplementedError)
|
30
51
|
end
|
31
52
|
|
53
|
+
it 'relies on inheriting classes to expose value method' do
|
54
|
+
expect { described_class.new(one, two).value(ctx) }.to raise_error NoMethodError
|
55
|
+
end
|
56
|
+
|
32
57
|
private
|
33
58
|
|
34
59
|
def less_than(left, right)
|
data/spec/ast/function_spec.rb
CHANGED
@@ -54,11 +54,11 @@ describe Dentaku::AST::Function do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'raises an error if the value could not be cast to a Numeric' do
|
57
|
-
expect { described_class.numeric('flarble') }.to raise_error
|
58
|
-
expect { described_class.numeric('-') }.to raise_error
|
59
|
-
expect { described_class.numeric('') }.to raise_error
|
60
|
-
expect { described_class.numeric(nil) }.to raise_error
|
61
|
-
expect { described_class.numeric('7.') }.to raise_error
|
62
|
-
expect { described_class.numeric(true) }.to raise_error
|
57
|
+
expect { described_class.numeric('flarble') }.to raise_error Dentaku::ArgumentError
|
58
|
+
expect { described_class.numeric('-') }.to raise_error Dentaku::ArgumentError
|
59
|
+
expect { described_class.numeric('') }.to raise_error Dentaku::ArgumentError
|
60
|
+
expect { described_class.numeric(nil) }.to raise_error Dentaku::ArgumentError
|
61
|
+
expect { described_class.numeric('7.') }.to raise_error Dentaku::ArgumentError
|
62
|
+
expect { described_class.numeric(true) }.to raise_error Dentaku::ArgumentError
|
63
63
|
end
|
64
64
|
end
|
data/spec/calculator_spec.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'dentaku'
|
3
|
-
|
4
3
|
describe Dentaku::Calculator do
|
5
4
|
let(:calculator) { described_class.new }
|
6
5
|
let(:with_memory) { described_class.new.store(apples: 3) }
|
@@ -39,6 +38,70 @@ describe Dentaku::Calculator do
|
|
39
38
|
expect(calculator.evaluate('t + 1*24*60*60', t: Time.local(2017, 1, 1))).to eq(Time.local(2017, 1, 2))
|
40
39
|
expect(calculator.evaluate("2 | 3 * 9")).to eq (27)
|
41
40
|
expect(calculator.evaluate("2 & 3 * 9")).to eq (2)
|
41
|
+
expect(calculator.evaluate("5%")).to eq (0.05)
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'evaluate' do
|
45
|
+
it 'returns nil when formula has error' do
|
46
|
+
expect(calculator.evaluate('1 + + 1')).to be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'suppresses unbound variable errors' do
|
50
|
+
expect(calculator.evaluate('AND(a,b)')).to be_nil
|
51
|
+
expect(calculator.evaluate('IF(a, 1, 0)')).to be_nil
|
52
|
+
expect(calculator.evaluate('MAX(a,b)')).to be_nil
|
53
|
+
expect(calculator.evaluate('MIN(a,b)')).to be_nil
|
54
|
+
expect(calculator.evaluate('NOT(a)')).to be_nil
|
55
|
+
expect(calculator.evaluate('OR(a,b)')).to be_nil
|
56
|
+
expect(calculator.evaluate('ROUND(a)')).to be_nil
|
57
|
+
expect(calculator.evaluate('ROUNDDOWN(a)')).to be_nil
|
58
|
+
expect(calculator.evaluate('ROUNDUP(a)')).to be_nil
|
59
|
+
expect(calculator.evaluate('SUM(a,b)')).to be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'suppresses numeric coercion errors' do
|
63
|
+
expect(calculator.evaluate('MAX(a,b)', a: nil, b: nil)).to be_nil
|
64
|
+
expect(calculator.evaluate('MIN(a,b)', a: nil, b: nil)).to be_nil
|
65
|
+
expect(calculator.evaluate('ROUND(a)', a: nil)).to be_nil
|
66
|
+
expect(calculator.evaluate('ROUNDDOWN(a)', a: nil)).to be_nil
|
67
|
+
expect(calculator.evaluate('ROUNDUP(a)', a: nil)).to be_nil
|
68
|
+
expect(calculator.evaluate('SUM(a,b)', a: nil, b: nil)).to be_nil
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'treats explicit nil as logical false' do
|
72
|
+
expect(calculator.evaluate('AND(a,b)', a: nil, b: nil)).to be_falsy
|
73
|
+
expect(calculator.evaluate('IF(a,1,0)', a: nil, b: nil)).to eq(0)
|
74
|
+
expect(calculator.evaluate('NOT(a)', a: nil, b: nil)).to be_truthy
|
75
|
+
expect(calculator.evaluate('OR(a,b)', a: nil, b: nil)).to be_falsy
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe 'evaluate!' do
|
80
|
+
it 'raises exception when formula has error' do
|
81
|
+
expect { calculator.evaluate!('1 + + 1') }.to raise_error(Dentaku::ParseError)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'raises unbound variable errors' do
|
85
|
+
expect { calculator.evaluate!('AND(a,b)') }.to raise_error(Dentaku::UnboundVariableError)
|
86
|
+
expect { calculator.evaluate!('IF(a, 1, 0)') }.to raise_error(Dentaku::UnboundVariableError)
|
87
|
+
expect { calculator.evaluate!('MAX(a,b)') }.to raise_error(Dentaku::UnboundVariableError)
|
88
|
+
expect { calculator.evaluate!('MIN(a,b)') }.to raise_error(Dentaku::UnboundVariableError)
|
89
|
+
expect { calculator.evaluate!('NOT(a)') }.to raise_error(Dentaku::UnboundVariableError)
|
90
|
+
expect { calculator.evaluate!('OR(a,b)') }.to raise_error(Dentaku::UnboundVariableError)
|
91
|
+
expect { calculator.evaluate!('ROUND(a)') }.to raise_error(Dentaku::UnboundVariableError)
|
92
|
+
expect { calculator.evaluate!('ROUNDDOWN(a)') }.to raise_error(Dentaku::UnboundVariableError)
|
93
|
+
expect { calculator.evaluate!('ROUNDUP(a)') }.to raise_error(Dentaku::UnboundVariableError)
|
94
|
+
expect { calculator.evaluate!('SUM(a,b)') }.to raise_error(Dentaku::UnboundVariableError)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'raises numeric coersion errors' do
|
98
|
+
expect { calculator.evaluate!('MAX(a,b)', a: nil, b: nil) }.to raise_error(Dentaku::ArgumentError)
|
99
|
+
expect { calculator.evaluate!('MIN(a,b)', a: nil, b: nil) }.to raise_error(Dentaku::ArgumentError)
|
100
|
+
expect { calculator.evaluate!('ROUND(a)', a: nil) }.to raise_error(Dentaku::ArgumentError)
|
101
|
+
expect { calculator.evaluate!('ROUNDDOWN(a)', a: nil) }.to raise_error(Dentaku::ArgumentError)
|
102
|
+
expect { calculator.evaluate!('ROUNDUP(a)', a: nil) }.to raise_error(Dentaku::ArgumentError)
|
103
|
+
expect { calculator.evaluate!('SUM(a,b)', a: nil, b: nil) }.to raise_error(Dentaku::ArgumentError)
|
104
|
+
end
|
42
105
|
end
|
43
106
|
|
44
107
|
it 'supports unicode characters in identifiers' do
|
@@ -84,7 +147,7 @@ describe Dentaku::Calculator do
|
|
84
147
|
expect(calculator.evaluate!('a[x+1]', x: 1)).to eq 3
|
85
148
|
end
|
86
149
|
|
87
|
-
it '
|
150
|
+
it 'evaluates arrays' do
|
88
151
|
expect(calculator.evaluate([1, 2, 3])).to eq([1, 2, 3])
|
89
152
|
end
|
90
153
|
end
|
@@ -160,6 +223,15 @@ describe Dentaku::Calculator do
|
|
160
223
|
|
161
224
|
expect(result[:weight]).to eq 130.368
|
162
225
|
end
|
226
|
+
|
227
|
+
it 'raises an exception if there are cyclic dependencies' do
|
228
|
+
expect {
|
229
|
+
calculator.solve!(
|
230
|
+
make_money: "have_money",
|
231
|
+
have_money: "make_money"
|
232
|
+
)
|
233
|
+
}.to raise_error(TSort::Cyclic)
|
234
|
+
end
|
163
235
|
end
|
164
236
|
|
165
237
|
describe 'solve' do
|
@@ -198,6 +270,19 @@ describe Dentaku::Calculator do
|
|
198
270
|
d: 0,
|
199
271
|
)
|
200
272
|
end
|
273
|
+
|
274
|
+
it 'returns undefined if there are cyclic dependencies' do
|
275
|
+
expect {
|
276
|
+
result = calculator.solve(
|
277
|
+
make_money: "have_money",
|
278
|
+
have_money: "make_money"
|
279
|
+
)
|
280
|
+
expect(result).to eq(
|
281
|
+
make_money: :undefined,
|
282
|
+
have_money: :undefined
|
283
|
+
)
|
284
|
+
}.not_to raise_error
|
285
|
+
end
|
201
286
|
end
|
202
287
|
|
203
288
|
it 'evaluates a statement with no variables' do
|
data/spec/dentaku_spec.rb
CHANGED
@@ -69,7 +69,9 @@ describe Dentaku::Calculator do
|
|
69
69
|
expect(calculator1.evaluate("1 + my_function(2)")). to eq (1 + 2 * 2 + 1)
|
70
70
|
expect(calculator2.evaluate("1 + my_function(2)")). to eq (1 + 4 * 2 + 3)
|
71
71
|
|
72
|
-
expect {
|
72
|
+
expect {
|
73
|
+
Dentaku::Calculator.new.evaluate!("1 + my_function(2)")
|
74
|
+
}.to raise_error(Dentaku::ParseError)
|
73
75
|
end
|
74
76
|
|
75
77
|
it 'self.add_function adds to default/global function registry' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dentaku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Solomon White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: codecov
|
@@ -248,7 +248,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
248
248
|
version: '0'
|
249
249
|
requirements: []
|
250
250
|
rubyforge_project: dentaku
|
251
|
-
rubygems_version: 2.6
|
251
|
+
rubygems_version: 2.7.6
|
252
252
|
signing_key:
|
253
253
|
specification_version: 4
|
254
254
|
summary: A formula language parser and evaluator
|