factbase 0.19.13 → 0.19.15
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/Gemfile.lock +11 -11
- data/README.md +15 -15
- data/lib/factbase/inv.rb +14 -6
- data/lib/factbase/logged.rb +11 -7
- data/lib/factbase/rules.rb +4 -2
- data/lib/factbase/terms/arithmetic.rb +1 -1
- data/lib/factbase/terms/env.rb +7 -2
- data/lib/factbase/terms/to_float.rb +9 -1
- data/lib/factbase/terms/to_integer.rb +9 -1
- data/lib/factbase/version.rb +1 -1
- data/lib/factbase.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0f6fa1160712c0f180b90cc7e3d15f9228c0266f5e8bdb227506aa2c9289cbf8
|
|
4
|
+
data.tar.gz: da6b63c4a95759dbc1ea4eb62cd204d4a0ec71dcc31b3bfc853fc197bb7ce183
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 32bab5bb943f397e259d2efd5c8f7ca90ee12da9e8595b416025f06b6ad72890221f20e72cd4e7b787d02102c6faf82b3e2b3bbc8bcd59b7e014fcab80782ee1
|
|
7
|
+
data.tar.gz: 25fa777f6fe8aeaf1bf55f92fc326512cc2228b3ec8b7d284d496abcde65c161bf3ad0006fbce73bc284c7d52b72cba49a2e613bb489f0fe25bf14a4a7f9a1cf
|
data/Gemfile.lock
CHANGED
|
@@ -21,7 +21,7 @@ GEM
|
|
|
21
21
|
backtrace (0.4.1)
|
|
22
22
|
benchmark (0.5.0)
|
|
23
23
|
builder (3.3.0)
|
|
24
|
-
concurrent-ruby (1.3.
|
|
24
|
+
concurrent-ruby (1.3.7)
|
|
25
25
|
date (3.5.1)
|
|
26
26
|
decoor (0.1.0)
|
|
27
27
|
docile (1.4.1)
|
|
@@ -31,8 +31,8 @@ GEM
|
|
|
31
31
|
tago (~> 0.1)
|
|
32
32
|
ellipsized (0.3.0)
|
|
33
33
|
erb (6.0.4)
|
|
34
|
-
json (2.
|
|
35
|
-
language_server-protocol (3.17.0.
|
|
34
|
+
json (2.20.0)
|
|
35
|
+
language_server-protocol (3.17.0.6)
|
|
36
36
|
lint_roller (1.1.0)
|
|
37
37
|
logger (1.7.0)
|
|
38
38
|
loog (0.8.0)
|
|
@@ -46,13 +46,13 @@ GEM
|
|
|
46
46
|
builder
|
|
47
47
|
minitest (>= 5.0, < 7)
|
|
48
48
|
ruby-progressbar
|
|
49
|
-
nokogiri (1.19.
|
|
49
|
+
nokogiri (1.19.4-arm64-darwin)
|
|
50
50
|
racc (~> 1.4)
|
|
51
|
-
nokogiri (1.19.
|
|
51
|
+
nokogiri (1.19.4-x64-mingw-ucrt)
|
|
52
52
|
racc (~> 1.4)
|
|
53
|
-
nokogiri (1.19.
|
|
53
|
+
nokogiri (1.19.4-x86_64-darwin)
|
|
54
54
|
racc (~> 1.4)
|
|
55
|
-
nokogiri (1.19.
|
|
55
|
+
nokogiri (1.19.4-x86_64-linux-gnu)
|
|
56
56
|
racc (~> 1.4)
|
|
57
57
|
os (1.1.4)
|
|
58
58
|
others (0.1.1)
|
|
@@ -78,7 +78,7 @@ GEM
|
|
|
78
78
|
tsort
|
|
79
79
|
regexp_parser (2.12.0)
|
|
80
80
|
rexml (3.4.4)
|
|
81
|
-
rubocop (1.
|
|
81
|
+
rubocop (1.88.1)
|
|
82
82
|
json (~> 2.3)
|
|
83
83
|
language_server-protocol (~> 3.17.0.2)
|
|
84
84
|
lint_roller (~> 1.1.0)
|
|
@@ -89,10 +89,10 @@ GEM
|
|
|
89
89
|
rubocop-ast (>= 1.49.0, < 2.0)
|
|
90
90
|
ruby-progressbar (~> 1.7)
|
|
91
91
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
92
|
-
rubocop-ast (1.
|
|
92
|
+
rubocop-ast (1.50.0)
|
|
93
93
|
parser (>= 3.3.7.2)
|
|
94
94
|
prism (~> 1.7)
|
|
95
|
-
rubocop-elegant (0.
|
|
95
|
+
rubocop-elegant (0.7.0)
|
|
96
96
|
lint_roller (~> 1.1)
|
|
97
97
|
rubocop (~> 1.75)
|
|
98
98
|
rubocop-minitest (0.39.1)
|
|
@@ -111,7 +111,7 @@ GEM
|
|
|
111
111
|
docile (~> 1.1)
|
|
112
112
|
simplecov-html (~> 0.11)
|
|
113
113
|
simplecov_json_formatter (~> 0.1)
|
|
114
|
-
simplecov-cobertura (3.
|
|
114
|
+
simplecov-cobertura (3.2.0)
|
|
115
115
|
rexml
|
|
116
116
|
simplecov (~> 0.19)
|
|
117
117
|
simplecov-html (0.13.2)
|
data/README.md
CHANGED
|
@@ -357,24 +357,24 @@ This is the result of the benchmark:
|
|
|
357
357
|
<!-- benchmark_begin -->
|
|
358
358
|
```text
|
|
359
359
|
user
|
|
360
|
-
void scan 0.
|
|
361
|
-
20k facts: export:
|
|
362
|
-
20k facts: import:
|
|
363
|
-
50k facts: read 0.
|
|
364
|
-
50k facts: read in txn 0.
|
|
365
|
-
50k facts: insert 0.
|
|
366
|
-
50k facts: insert in txn 0.
|
|
367
|
-
50k facts: modify 1.
|
|
368
|
-
50k facts: modify in txn
|
|
369
|
-
12k facts: large query: match 3k
|
|
370
|
-
12k facts: large query: match 3k in txn
|
|
371
|
-
12k facts: large query: match zero
|
|
372
|
-
12k facts: large query: match zero in txn
|
|
360
|
+
void scan 0.001099
|
|
361
|
+
20k facts: export: 2970KB 0.836539
|
|
362
|
+
20k facts: import: 2970KB 1.034012
|
|
363
|
+
50k facts: read 0.000256
|
|
364
|
+
50k facts: read in txn 0.002758
|
|
365
|
+
50k facts: insert 0.000100
|
|
366
|
+
50k facts: insert in txn 0.000257
|
|
367
|
+
50k facts: modify 1.484502
|
|
368
|
+
50k facts: modify in txn 2.812194
|
|
369
|
+
12k facts: large query: match 3k 14.318373
|
|
370
|
+
12k facts: large query: match 3k in txn 19.628950
|
|
371
|
+
12k facts: large query: match zero 15.134839
|
|
372
|
+
12k facts: large query: match zero in txn 20.974642
|
|
373
373
|
```
|
|
374
374
|
|
|
375
375
|
The results were calculated in [this GHA job][benchmark-gha]
|
|
376
|
-
on 2026-06-
|
|
376
|
+
on 2026-06-19 at 04:35,
|
|
377
377
|
on Linux with 4 CPUs.
|
|
378
378
|
<!-- benchmark_end -->
|
|
379
379
|
|
|
380
|
-
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/
|
|
380
|
+
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/27805571606
|
data/lib/factbase/inv.rb
CHANGED
|
@@ -7,17 +7,25 @@ require 'decoor'
|
|
|
7
7
|
require 'others'
|
|
8
8
|
require_relative '../factbase'
|
|
9
9
|
|
|
10
|
+
# @todo #644:30min Add a test that validates YARD docstring examples
|
|
11
|
+
# match the actual API signatures. The docstring in this class was
|
|
12
|
+
# recently fixed because the block signature was documented as
|
|
13
|
+
# |f, fbt| but the actual implementation passes |property, value|.
|
|
14
|
+
# A general test that parses docstrings and checks their examples
|
|
15
|
+
# against the real method signatures would prevent this class of
|
|
16
|
+
# bugs from recurring across the codebase.
|
|
17
|
+
#
|
|
10
18
|
# A decorator of a Factbase, that checks invariants on every set.
|
|
11
19
|
#
|
|
12
|
-
# For example, you can use this decorator if you want to
|
|
13
|
-
#
|
|
20
|
+
# For example, you can use this decorator if you want to make sure that
|
|
21
|
+
# no property +b+ is set to a +String+ value:
|
|
14
22
|
#
|
|
15
|
-
# fb = Factbase::Inv.new(Factbase.new) do |
|
|
16
|
-
#
|
|
23
|
+
# fb = Factbase::Inv.new(Factbase.new) do |p, v|
|
|
24
|
+
# raise "b cannot be a string" if p == 'b' && v.is_a?(String)
|
|
17
25
|
# end
|
|
18
26
|
#
|
|
19
|
-
# The
|
|
20
|
-
#
|
|
27
|
+
# The first block argument is the property name (a +String+), the second
|
|
28
|
+
# is the value being assigned.
|
|
21
29
|
#
|
|
22
30
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
23
31
|
# Copyright:: Copyright (c) 2024-2026 Yegor Bugayenko
|
data/lib/factbase/logged.rb
CHANGED
|
@@ -131,10 +131,11 @@ class Factbase::Logged
|
|
|
131
131
|
@maps = maps
|
|
132
132
|
@tube = tube
|
|
133
133
|
@fb = fb
|
|
134
|
+
@termtext = term.is_a?(Factbase::Term) ? term.to_s : term
|
|
134
135
|
end
|
|
135
136
|
|
|
136
137
|
def to_s
|
|
137
|
-
@
|
|
138
|
+
@termtext
|
|
138
139
|
end
|
|
139
140
|
|
|
140
141
|
def each(fb = @fb, params = {}, &)
|
|
@@ -147,10 +148,14 @@ class Factbase::Logged
|
|
|
147
148
|
r = qry.each(fb, params, &)
|
|
148
149
|
end
|
|
149
150
|
unless r.is_a?(Integer)
|
|
150
|
-
raise(StandardError, ".query(#{@
|
|
151
|
+
raise(StandardError, ".query(#{@termtext.inspect}).each() of #{qry.class} returned #{r.class}")
|
|
151
152
|
end
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
if params.is_a?(Hash) && !params.empty?
|
|
154
|
+
q = "#{@termtext} with {#{params.map do |k, v|
|
|
155
|
+
"#{k}=#{v}"
|
|
156
|
+
end.join(', ')}}"
|
|
157
|
+
end
|
|
158
|
+
q ||= @termtext
|
|
154
159
|
if r.zero?
|
|
155
160
|
@tube.say(mono, "Zero/#{@fb.size} facts found by #{q} #{tail}")
|
|
156
161
|
else
|
|
@@ -161,16 +166,15 @@ class Factbase::Logged
|
|
|
161
166
|
|
|
162
167
|
def one(fb = @fb, params = {})
|
|
163
168
|
mono = Process.clock_gettime(Factbase::Logged::MONO)
|
|
164
|
-
q = Factbase::Syntax.new(@term).to_term.to_s
|
|
165
169
|
r = nil
|
|
166
170
|
tail =
|
|
167
171
|
Factbase::Logged.elapsed do
|
|
168
172
|
r = @fb.query(@term, @maps).one(fb, params)
|
|
169
173
|
end
|
|
170
174
|
if r.nil?
|
|
171
|
-
@tube.say(mono, "Nothing found by '#{
|
|
175
|
+
@tube.say(mono, "Nothing found by '#{@termtext}' #{tail}")
|
|
172
176
|
else
|
|
173
|
-
@tube.say(mono, "Found #{r} (#{r.class}) by '#{
|
|
177
|
+
@tube.say(mono, "Found #{r} (#{r.class}) by '#{@termtext}' #{tail}")
|
|
174
178
|
end
|
|
175
179
|
r
|
|
176
180
|
end
|
data/lib/factbase/rules.rb
CHANGED
|
@@ -122,8 +122,10 @@ class Factbase::Rules
|
|
|
122
122
|
|
|
123
123
|
def it(fact, fb)
|
|
124
124
|
return if Factbase::Syntax.new(@expr).to_term.evaluate(fact, [], fb)
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
raise(
|
|
126
|
+
ArgumentError,
|
|
127
|
+
"The fact doesn't match the #{(@expr.length > 32 ? "#{@expr[0..31]}..." : @expr).inspect} rule: #{fact}"
|
|
128
|
+
)
|
|
127
129
|
end
|
|
128
130
|
end
|
|
129
131
|
|
|
@@ -47,7 +47,7 @@ class Factbase::Arithmetic < Factbase::TermBase
|
|
|
47
47
|
when 'weeks', 'week'
|
|
48
48
|
num * 60 * 60 * 24 * 7
|
|
49
49
|
else
|
|
50
|
-
raise(ArgumentError, "Unknown time unit '#{units}' in '#{r}")
|
|
50
|
+
raise(ArgumentError, "Unknown time unit '#{units}' in '#{r}'")
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
v.__send__(@op, r)
|
data/lib/factbase/terms/env.rb
CHANGED
|
@@ -22,7 +22,12 @@ class Factbase::Env < Factbase::TermBase
|
|
|
22
22
|
# @return [String] The value of the environment variable or the default
|
|
23
23
|
def evaluate(fact, maps, fb)
|
|
24
24
|
assert_args(2)
|
|
25
|
-
n = _values(0, fact, maps, fb)
|
|
26
|
-
|
|
25
|
+
n = _values(0, fact, maps, fb)
|
|
26
|
+
return if n.nil?
|
|
27
|
+
ENV.fetch(n[0].upcase) do
|
|
28
|
+
d = _values(1, fact, maps, fb)
|
|
29
|
+
return if d.nil?
|
|
30
|
+
d[0]
|
|
31
|
+
end
|
|
27
32
|
end
|
|
28
33
|
end
|
|
@@ -23,6 +23,14 @@ class Factbase::ToFloat < Factbase::TermBase
|
|
|
23
23
|
assert_args(1)
|
|
24
24
|
vv = _values(0, fact, maps, fb)
|
|
25
25
|
return if vv.nil?
|
|
26
|
-
|
|
26
|
+
to_float(vv[0])
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def to_float(value)
|
|
32
|
+
Float(value.to_s)
|
|
33
|
+
rescue ArgumentError, TypeError => e
|
|
34
|
+
raise(RuntimeError, "Cannot convert '#{value}' to Float in (to_float ...): #{e.message}")
|
|
27
35
|
end
|
|
28
36
|
end
|
|
@@ -23,6 +23,14 @@ class Factbase::ToInteger < Factbase::TermBase
|
|
|
23
23
|
assert_args(1)
|
|
24
24
|
vv = _values(0, fact, maps, fb)
|
|
25
25
|
return if vv.nil?
|
|
26
|
-
|
|
26
|
+
to_integer(vv[0])
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def to_integer(value)
|
|
32
|
+
Integer(value)
|
|
33
|
+
rescue ArgumentError, TypeError => e
|
|
34
|
+
raise(RuntimeError, "Cannot convert '#{value}' to Integer in (to_integer ...): #{e.message}")
|
|
27
35
|
end
|
|
28
36
|
end
|
data/lib/factbase/version.rb
CHANGED
data/lib/factbase.rb
CHANGED
|
@@ -17,7 +17,7 @@ require 'yaml'
|
|
|
17
17
|
# f = fb.insert # new fact created
|
|
18
18
|
# f.name = 'Jeff Lebowski'
|
|
19
19
|
# f.age = 42
|
|
20
|
-
# found =
|
|
20
|
+
# found = fb.query('(gt 20 age)').each.to_a[0]
|
|
21
21
|
# assert(found.age == 42)
|
|
22
22
|
#
|
|
23
23
|
# Every fact is a key-value hash map. Every value is a non-empty set of values.
|