factbase 0.2.1 → 0.3.0
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/.github/workflows/actionlint.yml +1 -1
- data/.github/workflows/codecov.yml +2 -2
- data/.github/workflows/copyrights.yml +1 -1
- data/.github/workflows/markdown-lint.yml +1 -1
- data/.github/workflows/pdd.yml +1 -1
- data/.github/workflows/rake.yml +2 -2
- data/.github/workflows/xcop.yml +1 -1
- data/.github/workflows/yamllint.yml +1 -1
- data/.rubocop.yml +2 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +14 -13
- data/lib/factbase/fact.rb +3 -3
- data/lib/factbase/looged.rb +25 -20
- data/lib/factbase/term.rb +9 -8
- data/lib/factbase/terms/math.rb +13 -5
- data/lib/factbase.rb +1 -1
- data/test/factbase/terms/test_math.rb +20 -0
- data/test/factbase/test_inv.rb +12 -9
- data/test/factbase/test_rules.rb +4 -3
- data/test/test_factbase.rb +5 -4
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: da15ba272d70a23c1f7138efd317a27e19f37846c7305b005e75fb23d9222004
|
|
4
|
+
data.tar.gz: 37588b7eb0b03659b5e6373a4f42bda9e89cd652cc954bc6a7988faf705d35ad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba914de891e44ee3580e42be96710c3a2deecd75c2ba7fae07d78bb84920af2ffbf602b587e0aa81c1b138b9603f0c58903c21a933177e04e3fdcf1124d367b6
|
|
7
|
+
data.tar.gz: 3c681187d0df5285eb0922f7ae718c12009c26adb84c9a9ba7ad2676c095e5dcd68e01dce538a87c52f02e3475d62e4833349995c6d69cd444f3a9730fd4ba52
|
|
@@ -25,12 +25,12 @@ name: codecov
|
|
|
25
25
|
- master
|
|
26
26
|
jobs:
|
|
27
27
|
codecov:
|
|
28
|
-
runs-on: ubuntu-
|
|
28
|
+
runs-on: ubuntu-24.04
|
|
29
29
|
steps:
|
|
30
30
|
- uses: actions/checkout@v4
|
|
31
31
|
- uses: ruby/setup-ruby@v1
|
|
32
32
|
with:
|
|
33
|
-
ruby-version: 3.
|
|
33
|
+
ruby-version: 3.3
|
|
34
34
|
bundler-cache: true
|
|
35
35
|
- run: bundle install
|
|
36
36
|
- run: bundle exec rake
|
data/.github/workflows/pdd.yml
CHANGED
data/.github/workflows/rake.yml
CHANGED
data/.github/workflows/xcop.yml
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
|
@@ -27,9 +27,9 @@ gem 'minitest', '5.24.1', require: false
|
|
|
27
27
|
gem 'minitest-reporters', '1.7.1', require: false
|
|
28
28
|
gem 'rake', '13.2.1', require: false
|
|
29
29
|
gem 'rspec-rails', '6.1.3', require: false
|
|
30
|
-
gem 'rubocop', '1.65.
|
|
30
|
+
gem 'rubocop', '1.65.1', require: false
|
|
31
31
|
gem 'rubocop-performance', '1.21.1', require: false
|
|
32
|
-
gem 'rubocop-rspec', '3.0.
|
|
32
|
+
gem 'rubocop-rspec', '3.0.4', require: false
|
|
33
33
|
gem 'simplecov', '0.22.0', require: false
|
|
34
34
|
gem 'simplecov-cobertura', '2.1.0', require: false
|
|
35
35
|
gem 'yard', '0.9.36', require: false
|
data/Gemfile.lock
CHANGED
|
@@ -51,7 +51,7 @@ GEM
|
|
|
51
51
|
crass (1.0.6)
|
|
52
52
|
decoor (0.0.1)
|
|
53
53
|
diff-lcs (1.5.1)
|
|
54
|
-
docile (1.4.
|
|
54
|
+
docile (1.4.1)
|
|
55
55
|
drb (2.2.1)
|
|
56
56
|
erubi (1.13.0)
|
|
57
57
|
i18n (1.14.5)
|
|
@@ -65,7 +65,7 @@ GEM
|
|
|
65
65
|
loofah (2.22.0)
|
|
66
66
|
crass (~> 1.0.2)
|
|
67
67
|
nokogiri (>= 1.12.0)
|
|
68
|
-
loog (0.5.
|
|
68
|
+
loog (0.5.3)
|
|
69
69
|
minitest (5.24.1)
|
|
70
70
|
minitest-reporters (1.7.1)
|
|
71
71
|
ansi
|
|
@@ -73,13 +73,13 @@ GEM
|
|
|
73
73
|
minitest (>= 5.0)
|
|
74
74
|
ruby-progressbar
|
|
75
75
|
mutex_m (0.2.0)
|
|
76
|
-
nokogiri (1.16.
|
|
76
|
+
nokogiri (1.16.7-arm64-darwin)
|
|
77
77
|
racc (~> 1.4)
|
|
78
|
-
nokogiri (1.16.
|
|
78
|
+
nokogiri (1.16.7-x64-mingw-ucrt)
|
|
79
79
|
racc (~> 1.4)
|
|
80
|
-
nokogiri (1.16.
|
|
80
|
+
nokogiri (1.16.7-x86_64-darwin)
|
|
81
81
|
racc (~> 1.4)
|
|
82
|
-
nokogiri (1.16.
|
|
82
|
+
nokogiri (1.16.7-x86_64-linux)
|
|
83
83
|
racc (~> 1.4)
|
|
84
84
|
others (0.0.3)
|
|
85
85
|
parallel (1.25.1)
|
|
@@ -88,7 +88,7 @@ GEM
|
|
|
88
88
|
racc
|
|
89
89
|
psych (5.1.2)
|
|
90
90
|
stringio
|
|
91
|
-
racc (1.8.
|
|
91
|
+
racc (1.8.1)
|
|
92
92
|
rack (3.1.7)
|
|
93
93
|
rack-session (2.0.0)
|
|
94
94
|
rack (>= 3.0.0)
|
|
@@ -119,7 +119,7 @@ GEM
|
|
|
119
119
|
regexp_parser (2.9.2)
|
|
120
120
|
reline (0.5.9)
|
|
121
121
|
io-console (~> 0.5)
|
|
122
|
-
rexml (3.3.
|
|
122
|
+
rexml (3.3.4)
|
|
123
123
|
strscan
|
|
124
124
|
rspec-core (3.13.0)
|
|
125
125
|
rspec-support (~> 3.13.0)
|
|
@@ -138,7 +138,7 @@ GEM
|
|
|
138
138
|
rspec-mocks (~> 3.13)
|
|
139
139
|
rspec-support (~> 3.13)
|
|
140
140
|
rspec-support (3.13.1)
|
|
141
|
-
rubocop (1.65.
|
|
141
|
+
rubocop (1.65.1)
|
|
142
142
|
json (~> 2.3)
|
|
143
143
|
language_server-protocol (>= 3.17.0)
|
|
144
144
|
parallel (~> 1.10)
|
|
@@ -154,7 +154,7 @@ GEM
|
|
|
154
154
|
rubocop-performance (1.21.1)
|
|
155
155
|
rubocop (>= 1.48.1, < 2.0)
|
|
156
156
|
rubocop-ast (>= 1.31.1, < 2.0)
|
|
157
|
-
rubocop-rspec (3.0.
|
|
157
|
+
rubocop-rspec (3.0.4)
|
|
158
158
|
rubocop (~> 1.61)
|
|
159
159
|
ruby-progressbar (1.13.0)
|
|
160
160
|
simplecov (0.22.0)
|
|
@@ -176,12 +176,13 @@ GEM
|
|
|
176
176
|
webrick (1.8.1)
|
|
177
177
|
yaml (0.3.0)
|
|
178
178
|
yard (0.9.36)
|
|
179
|
-
zeitwerk (2.6.
|
|
179
|
+
zeitwerk (2.6.17)
|
|
180
180
|
|
|
181
181
|
PLATFORMS
|
|
182
182
|
arm64-darwin-22
|
|
183
183
|
x64-mingw-ucrt
|
|
184
184
|
x86_64-darwin-20
|
|
185
|
+
x86_64-darwin-21
|
|
185
186
|
x86_64-linux
|
|
186
187
|
|
|
187
188
|
DEPENDENCIES
|
|
@@ -190,9 +191,9 @@ DEPENDENCIES
|
|
|
190
191
|
minitest-reporters (= 1.7.1)
|
|
191
192
|
rake (= 13.2.1)
|
|
192
193
|
rspec-rails (= 6.1.3)
|
|
193
|
-
rubocop (= 1.65.
|
|
194
|
+
rubocop (= 1.65.1)
|
|
194
195
|
rubocop-performance (= 1.21.1)
|
|
195
|
-
rubocop-rspec (= 3.0.
|
|
196
|
+
rubocop-rspec (= 3.0.4)
|
|
196
197
|
simplecov (= 0.22.0)
|
|
197
198
|
simplecov-cobertura (= 2.1.0)
|
|
198
199
|
yard (= 0.9.36)
|
data/lib/factbase/fact.rb
CHANGED
|
@@ -71,9 +71,9 @@ class Factbase::Fact
|
|
|
71
71
|
raise "Invalid prop name '#{kk}'" unless kk.match?(/^[a-z_][_a-zA-Z0-9]*$/)
|
|
72
72
|
raise "Prohibited prop name '#{kk}'" if methods.include?(kk.to_sym)
|
|
73
73
|
v = args[1]
|
|
74
|
-
raise "
|
|
75
|
-
raise "
|
|
76
|
-
raise "
|
|
74
|
+
raise "The value of '#{kk}' can't be nil" if v.nil?
|
|
75
|
+
raise "The value of '#{kk}' can't be empty" if v == ''
|
|
76
|
+
raise "The type '#{v.class}' of '#{kk}' is not allowed" unless [String, Integer, Float, Time].include?(v.class)
|
|
77
77
|
v = v.utc if v.is_a?(Time)
|
|
78
78
|
@mutex.synchronize do
|
|
79
79
|
@map[kk] = [] if @map[kk].nil?
|
data/lib/factbase/looged.rb
CHANGED
|
@@ -59,13 +59,14 @@ class Factbase::Looged
|
|
|
59
59
|
start = Time.now
|
|
60
60
|
id = nil
|
|
61
61
|
rollback = false
|
|
62
|
-
r =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
r =
|
|
63
|
+
@fb.txn(this) do |fbt|
|
|
64
|
+
id = fbt.object_id
|
|
65
|
+
yield fbt
|
|
66
|
+
rescue Factbase::Rollback => e
|
|
67
|
+
rollback = true
|
|
68
|
+
raise e
|
|
69
|
+
end
|
|
69
70
|
if rollback
|
|
70
71
|
@loog.debug("Txn ##{id} rolled back in #{start.ago}")
|
|
71
72
|
else
|
|
@@ -120,9 +121,10 @@ class Factbase::Looged
|
|
|
120
121
|
def one(params = {})
|
|
121
122
|
q = Factbase::Syntax.new(@expr).to_term.to_s
|
|
122
123
|
r = nil
|
|
123
|
-
tail =
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
tail =
|
|
125
|
+
Factbase::Looged.elapsed do
|
|
126
|
+
r = @fb.query(@expr).one(params)
|
|
127
|
+
end
|
|
126
128
|
if r.nil?
|
|
127
129
|
@loog.debug("Nothing found by '#{q}' #{tail}")
|
|
128
130
|
else
|
|
@@ -135,9 +137,10 @@ class Factbase::Looged
|
|
|
135
137
|
q = Factbase::Syntax.new(@expr).to_term.to_s
|
|
136
138
|
if block_given?
|
|
137
139
|
r = nil
|
|
138
|
-
tail =
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
tail =
|
|
141
|
+
Factbase::Looged.elapsed do
|
|
142
|
+
r = @fb.query(@expr).each(params, &)
|
|
143
|
+
end
|
|
141
144
|
raise ".each of #{@query.class} returned #{r.class}" unless r.is_a?(Integer)
|
|
142
145
|
if r.zero?
|
|
143
146
|
@loog.debug("Nothing found by '#{q}' #{tail}")
|
|
@@ -147,11 +150,12 @@ class Factbase::Looged
|
|
|
147
150
|
r
|
|
148
151
|
else
|
|
149
152
|
array = []
|
|
150
|
-
tail =
|
|
151
|
-
|
|
152
|
-
|
|
153
|
+
tail =
|
|
154
|
+
Factbase::Looged.elapsed do
|
|
155
|
+
@fb.query(@expr).each(params) do |f|
|
|
156
|
+
array << f
|
|
157
|
+
end
|
|
153
158
|
end
|
|
154
|
-
end
|
|
155
159
|
if array.empty?
|
|
156
160
|
@loog.debug("Nothing found by '#{q}' #{tail}")
|
|
157
161
|
else
|
|
@@ -164,9 +168,10 @@ class Factbase::Looged
|
|
|
164
168
|
def delete!
|
|
165
169
|
r = nil
|
|
166
170
|
before = @fb.size
|
|
167
|
-
tail =
|
|
168
|
-
|
|
169
|
-
|
|
171
|
+
tail =
|
|
172
|
+
Factbase::Looged.elapsed do
|
|
173
|
+
r = @fb.query(@expr).delete!
|
|
174
|
+
end
|
|
170
175
|
raise ".delete! of #{@query.class} returned #{r.class}" unless r.is_a?(Integer)
|
|
171
176
|
if before.zero?
|
|
172
177
|
@loog.debug("There were no facts, nothing deleted by '#{@expr}' #{tail}")
|
data/lib/factbase/term.rb
CHANGED
|
@@ -122,15 +122,16 @@ class Factbase::Term
|
|
|
122
122
|
def to_s
|
|
123
123
|
items = []
|
|
124
124
|
items << @op
|
|
125
|
-
items +=
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
o.
|
|
130
|
-
|
|
131
|
-
|
|
125
|
+
items +=
|
|
126
|
+
@operands.map do |o|
|
|
127
|
+
if o.is_a?(String)
|
|
128
|
+
"'#{o.gsub("'", "\\\\'").gsub('"', '\\\\"')}'"
|
|
129
|
+
elsif o.is_a?(Time)
|
|
130
|
+
o.utc.iso8601
|
|
131
|
+
else
|
|
132
|
+
o.to_s
|
|
133
|
+
end
|
|
132
134
|
end
|
|
133
|
-
end
|
|
134
135
|
"(#{items.join(' ')})"
|
|
135
136
|
end
|
|
136
137
|
|
data/lib/factbase/terms/math.rb
CHANGED
|
@@ -63,6 +63,14 @@ module Factbase::Term::Math
|
|
|
63
63
|
cmp(:>, fact, maps)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def lte(fact, maps)
|
|
67
|
+
cmp(:<=, fact, maps)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def gte(fact, maps)
|
|
71
|
+
cmp(:>=, fact, maps)
|
|
72
|
+
end
|
|
73
|
+
|
|
66
74
|
def cmp(op, fact, maps)
|
|
67
75
|
assert_args(2)
|
|
68
76
|
lefts = the_values(0, fact, maps)
|
|
@@ -93,15 +101,15 @@ module Factbase::Term::Math
|
|
|
93
101
|
num = num.to_i
|
|
94
102
|
r =
|
|
95
103
|
case units
|
|
96
|
-
when 'seconds'
|
|
104
|
+
when 'seconds', 'second'
|
|
97
105
|
num
|
|
98
|
-
when 'minutes'
|
|
106
|
+
when 'minutes', 'minute'
|
|
99
107
|
num * 60
|
|
100
|
-
when 'hours'
|
|
108
|
+
when 'hours', 'hour'
|
|
101
109
|
num * 60 * 60
|
|
102
|
-
when 'days'
|
|
110
|
+
when 'days', 'day'
|
|
103
111
|
num * 60 * 60 * 24
|
|
104
|
-
when 'weeks'
|
|
112
|
+
when 'weeks', 'week'
|
|
105
113
|
num * 60 * 60 * 24 * 7
|
|
106
114
|
else
|
|
107
115
|
raise "Unknown time unit '#{units}' in '#{r}"
|
data/lib/factbase.rb
CHANGED
|
@@ -81,7 +81,7 @@ require 'yaml'
|
|
|
81
81
|
# License:: MIT
|
|
82
82
|
class Factbase
|
|
83
83
|
# Current version of the gem (changed by .rultor.yml on every release)
|
|
84
|
-
VERSION = '0.
|
|
84
|
+
VERSION = '0.3.0'
|
|
85
85
|
|
|
86
86
|
# An exception that may be thrown in a transaction, to roll it back.
|
|
87
87
|
class Rollback < StandardError; end
|
|
@@ -69,6 +69,20 @@ class TestMath < Minitest::Test
|
|
|
69
69
|
assert(!t.evaluate(fact('bar' => 100), []))
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
def test_gte
|
|
73
|
+
t = Factbase::Term.new(:gte, [:foo, 42])
|
|
74
|
+
assert(t.evaluate(fact('foo' => 100), []))
|
|
75
|
+
assert(t.evaluate(fact('foo' => 42), []))
|
|
76
|
+
assert(!t.evaluate(fact('foo' => 41), []))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_lte
|
|
80
|
+
t = Factbase::Term.new(:lte, [:foo, 42])
|
|
81
|
+
assert(t.evaluate(fact('foo' => 41), []))
|
|
82
|
+
assert(t.evaluate(fact('foo' => 42), []))
|
|
83
|
+
assert(!t.evaluate(fact('foo' => 100), []))
|
|
84
|
+
end
|
|
85
|
+
|
|
72
86
|
def test_gt
|
|
73
87
|
t = Factbase::Term.new(:gt, [:foo, 42])
|
|
74
88
|
assert(t.evaluate(fact('foo' => [100]), []))
|
|
@@ -115,4 +129,10 @@ class TestMath < Minitest::Test
|
|
|
115
129
|
assert_equal(Time.parse('2024-01-01T06:04'), t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), []))
|
|
116
130
|
assert(t.evaluate(fact, []).nil?)
|
|
117
131
|
end
|
|
132
|
+
|
|
133
|
+
def test_minus_time_singular
|
|
134
|
+
t = Factbase::Term.new(:minus, [:foo, '1 hour'])
|
|
135
|
+
assert_equal(Time.parse('2024-01-01T09:04'), t.evaluate(fact('foo' => Time.parse('2024-01-01T10:04')), []))
|
|
136
|
+
assert(t.evaluate(fact, []).nil?)
|
|
137
|
+
end
|
|
118
138
|
end
|
data/test/factbase/test_inv.rb
CHANGED
|
@@ -32,9 +32,10 @@ require_relative '../../lib/factbase/pre'
|
|
|
32
32
|
# License:: MIT
|
|
33
33
|
class TestInv < Minitest::Test
|
|
34
34
|
def test_simple_checking
|
|
35
|
-
fb =
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
fb =
|
|
36
|
+
Factbase::Inv.new(Factbase.new) do |p, v|
|
|
37
|
+
raise 'oops' if v.is_a?(String) && p == 'b'
|
|
38
|
+
end
|
|
38
39
|
f = fb.insert
|
|
39
40
|
f.a = 42
|
|
40
41
|
assert_raises do
|
|
@@ -46,12 +47,14 @@ class TestInv < Minitest::Test
|
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def test_pre_and_inv
|
|
49
|
-
fb =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
fb =
|
|
51
|
+
Factbase::Inv.new(Factbase.new) do |p, v|
|
|
52
|
+
raise 'oops' if v.is_a?(String) && p == 'b'
|
|
53
|
+
end
|
|
54
|
+
fb =
|
|
55
|
+
Factbase::Pre.new(fb) do |f|
|
|
56
|
+
f.id = 42
|
|
57
|
+
end
|
|
55
58
|
f = fb.insert
|
|
56
59
|
assert_equal(42, f.id)
|
|
57
60
|
end
|
data/test/factbase/test_rules.rb
CHANGED
|
@@ -96,9 +96,10 @@ class TestRules < Minitest::Test
|
|
|
96
96
|
|
|
97
97
|
def test_in_combination_with_pre
|
|
98
98
|
fb = Factbase::Rules.new(Factbase.new, '(when (exists a) (exists b))')
|
|
99
|
-
fb =
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
fb =
|
|
100
|
+
Factbase::Pre.new(fb) do |f|
|
|
101
|
+
f.hello = 42
|
|
102
|
+
end
|
|
102
103
|
ok = false
|
|
103
104
|
assert_raises do
|
|
104
105
|
fb.txn do |fbt|
|
data/test/test_factbase.rb
CHANGED
|
@@ -211,10 +211,11 @@ class TestFactbase < Minitest::Test
|
|
|
211
211
|
|
|
212
212
|
def test_txn_with_rollback
|
|
213
213
|
fb = Factbase.new
|
|
214
|
-
modified =
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
modified =
|
|
215
|
+
fb.txn do |fbt|
|
|
216
|
+
fbt.insert.bar = 33
|
|
217
|
+
raise Factbase::Rollback
|
|
218
|
+
end
|
|
218
219
|
assert(!modified)
|
|
219
220
|
assert_equal(0, fb.query('(always)').each.to_a.size)
|
|
220
221
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: factbase
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yegor Bugayenko
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-08-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: backtrace
|