factbase 0.10.1 → 0.11.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/benchmark.yml +2 -1
- data/.github/workflows/copyrights.yml +1 -1
- data/.github/workflows/markdown-lint.yml +1 -1
- data/.github/workflows/typos.yml +19 -0
- data/.gitignore +3 -2
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +12 -9
- data/README.md +25 -25
- data/REUSE.toml +8 -7
- data/lib/factbase/cached/cached_fact.rb +4 -0
- data/lib/factbase/cached/cached_factbase.rb +2 -2
- data/lib/factbase/fact_as_yaml.rb +38 -0
- data/lib/factbase/indexed/indexed_fact.rb +4 -0
- data/lib/factbase/indexed/indexed_factbase.rb +2 -2
- data/lib/factbase.rb +1 -1
- data/test/factbase/cached/test_cached_factbase.rb +9 -0
- data/test/factbase/test_fact_as_yaml.rb +62 -0
- data/test/factbase/test_query.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 474551d14c160969e1361d2518458de199c6777865aedf1a34f5a4de00f22542
|
4
|
+
data.tar.gz: ae437f74a4422631c9f3fa3c4a1752b42eadbef4c0c3a2339829d3417a928441
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc63686b69eb970b104a748be486d3e254f8ac919b9e171e801c77e6a02645c3e8daac33ea5807d3f37fe1d1e7f9d7744326f44155ad36d18cf1f498ade75cff
|
7
|
+
data.tar.gz: 7c5d8f8aa98f68fa5a96d6f387cfe892fd43026ad2c51c418b0dccda72f3cdebac2ca24e9c1b9a3d205576c96888bb7ca03adab925c6533abc18de5e51769424
|
@@ -28,7 +28,7 @@ jobs:
|
|
28
28
|
set -x
|
29
29
|
sum=$(
|
30
30
|
echo '```text'
|
31
|
-
cat stdout.txt
|
31
|
+
cat stdout.txt | cut -c -71
|
32
32
|
echo '```'
|
33
33
|
echo
|
34
34
|
echo "The results were calculated in [this GHA job][benchmark-gha]"
|
@@ -43,6 +43,7 @@ jobs:
|
|
43
43
|
rm stdout.txt
|
44
44
|
- uses: peter-evans/create-pull-request@v7
|
45
45
|
with:
|
46
|
+
sign-commits: true
|
46
47
|
branch: benchmark-results
|
47
48
|
commit-message: 'new benchmarking results'
|
48
49
|
delete-branch: true
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
2
|
+
# SPDX-License-Identifier: MIT
|
3
|
+
---
|
4
|
+
# yamllint disable rule:line-length
|
5
|
+
name: typos
|
6
|
+
'on':
|
7
|
+
push:
|
8
|
+
branches:
|
9
|
+
- master
|
10
|
+
pull_request:
|
11
|
+
branches:
|
12
|
+
- master
|
13
|
+
jobs:
|
14
|
+
typos:
|
15
|
+
timeout-minutes: 15
|
16
|
+
runs-on: ubuntu-24.04
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v4
|
19
|
+
- uses: crate-ci/typos@v1.33.1
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -26,11 +26,13 @@ GEM
|
|
26
26
|
elapsed (0.0.1)
|
27
27
|
loog (> 0)
|
28
28
|
tago (> 0)
|
29
|
-
|
30
|
-
|
29
|
+
erb (5.0.1)
|
30
|
+
json (2.12.2)
|
31
|
+
language_server-protocol (3.17.0.5)
|
31
32
|
lint_roller (1.1.0)
|
32
33
|
logger (1.7.0)
|
33
|
-
loog (0.6.
|
34
|
+
loog (0.6.1)
|
35
|
+
logger (~> 1.0)
|
34
36
|
minitest (5.25.5)
|
35
37
|
minitest-reporters (1.7.1)
|
36
38
|
ansi
|
@@ -52,22 +54,23 @@ GEM
|
|
52
54
|
ast (~> 2.4.1)
|
53
55
|
racc
|
54
56
|
prism (1.4.0)
|
55
|
-
psych (5.2.
|
57
|
+
psych (5.2.6)
|
56
58
|
date
|
57
59
|
stringio
|
58
|
-
qbash (0.4.
|
60
|
+
qbash (0.4.5)
|
59
61
|
backtrace (> 0)
|
60
62
|
elapsed (> 0)
|
61
63
|
loog (> 0)
|
62
64
|
tago (> 0)
|
63
65
|
racc (1.8.1)
|
64
66
|
rainbow (3.1.1)
|
65
|
-
rake (13.
|
66
|
-
rdoc (6.
|
67
|
+
rake (13.3.0)
|
68
|
+
rdoc (6.14.0)
|
69
|
+
erb
|
67
70
|
psych (>= 4.0.0)
|
68
71
|
regexp_parser (2.10.0)
|
69
72
|
rexml (3.4.1)
|
70
|
-
rubocop (1.75.
|
73
|
+
rubocop (1.75.8)
|
71
74
|
json (~> 2.3)
|
72
75
|
language_server-protocol (~> 3.17.0.2)
|
73
76
|
lint_roller (~> 1.1.0)
|
@@ -81,7 +84,7 @@ GEM
|
|
81
84
|
rubocop-ast (1.44.1)
|
82
85
|
parser (>= 3.3.7.2)
|
83
86
|
prism (~> 1.4)
|
84
|
-
rubocop-minitest (0.38.
|
87
|
+
rubocop-minitest (0.38.1)
|
85
88
|
lint_roller (~> 1.1)
|
86
89
|
rubocop (>= 1.75.0, < 2.0)
|
87
90
|
rubocop-ast (>= 1.38.0, < 2.0)
|
data/README.md
CHANGED
@@ -209,34 +209,34 @@ This is the result of the benchmark:
|
|
209
209
|
|
210
210
|
<!-- benchmark_begin -->
|
211
211
|
```text
|
212
|
-
user
|
213
|
-
insert 20000 facts 0.
|
214
|
-
export 20000 facts 0.
|
215
|
-
import
|
216
|
-
insert 10 facts 0.
|
217
|
-
query 10 times w/txn 1.
|
218
|
-
query 10 times w/o txn 0.
|
219
|
-
modify 10 attrs w/txn 1.
|
220
|
-
delete 10 facts w/txn 1.
|
221
|
-
(and (eq what 'issue-was-closed') (exists... -> 200 2.
|
222
|
-
(and (eq what 'issue-was-closed') (exists... -> 200/txn 1.
|
223
|
-
(and (eq what 'issue-was-closed') (exists... -> zero 2.
|
224
|
-
(and (eq what 'issue-was-closed') (exists... -> zero/txn 1.
|
225
|
-
(gt time '2024-03-23T03:21:43Z') 0.
|
226
|
-
(gt cost 50) 0.
|
227
|
-
(eq title 'Object Thinking 5000') 0.
|
228
|
-
(and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.
|
229
|
-
(eq id (agg (always) (max id))) 0.
|
230
|
-
(join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.
|
231
|
-
delete! 0.
|
232
|
-
Taped.append() x50000 0.
|
233
|
-
Taped.each() x125 1.
|
234
|
-
Taped.delete_if() x375 0.
|
212
|
+
user
|
213
|
+
insert 20000 facts 0.606861
|
214
|
+
export 20000 facts 0.029288
|
215
|
+
import 410768 bytes (20000 facts) 0.029856
|
216
|
+
insert 10 facts 0.042954
|
217
|
+
query 10 times w/txn 1.951537
|
218
|
+
query 10 times w/o txn 0.038436
|
219
|
+
modify 10 attrs w/txn 1.815854
|
220
|
+
delete 10 facts w/txn 1.023006
|
221
|
+
(and (eq what 'issue-was-closed') (exists... -> 200 2.130857
|
222
|
+
(and (eq what 'issue-was-closed') (exists... -> 200/txn 1.146039
|
223
|
+
(and (eq what 'issue-was-closed') (exists... -> zero 2.424541
|
224
|
+
(and (eq what 'issue-was-closed') (exists... -> zero/txn 1.297135
|
225
|
+
(gt time '2024-03-23T03:21:43Z') 0.109071
|
226
|
+
(gt cost 50) 0.092356
|
227
|
+
(eq title 'Object Thinking 5000') 0.002707
|
228
|
+
(and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.024449
|
229
|
+
(eq id (agg (always) (max id))) 0.257526
|
230
|
+
(join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.650843
|
231
|
+
delete! 0.075867
|
232
|
+
Taped.append() x50000 0.038991
|
233
|
+
Taped.each() x125 1.321896
|
234
|
+
Taped.delete_if() x375 0.830375
|
235
235
|
```
|
236
236
|
|
237
237
|
The results were calculated in [this GHA job][benchmark-gha]
|
238
|
-
on 2025-
|
238
|
+
on 2025-06-03 at 09:54,
|
239
239
|
on Linux with 4 CPUs.
|
240
240
|
<!-- benchmark_end -->
|
241
241
|
|
242
|
-
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/
|
242
|
+
[benchmark-gha]: https://github.com/yegor256/factbase/actions/runs/15414210508
|
data/REUSE.toml
CHANGED
@@ -4,9 +4,17 @@
|
|
4
4
|
version = 1
|
5
5
|
[[annotations]]
|
6
6
|
path = [
|
7
|
+
".DS_Store",
|
8
|
+
".gitattributes",
|
9
|
+
".gitignore",
|
10
|
+
".pdd",
|
7
11
|
"**.json",
|
8
12
|
"**.md",
|
13
|
+
"**.png",
|
9
14
|
"**.txt",
|
15
|
+
"**/.DS_Store",
|
16
|
+
"**/.gitignore",
|
17
|
+
"**/.pdd",
|
10
18
|
"**/*.csv",
|
11
19
|
"**/*.jpg",
|
12
20
|
"**/*.json",
|
@@ -16,15 +24,8 @@ path = [
|
|
16
24
|
"**/*.svg",
|
17
25
|
"**/*.txt",
|
18
26
|
"**/*.vm",
|
19
|
-
"**/.DS_Store",
|
20
|
-
"**/.gitignore",
|
21
|
-
"**/.pdd",
|
22
27
|
"**/CNAME",
|
23
28
|
"**/Gemfile.lock",
|
24
|
-
".DS_Store",
|
25
|
-
".gitattributes",
|
26
|
-
".gitignore",
|
27
|
-
".pdd",
|
28
29
|
"Gemfile.lock",
|
29
30
|
"README.md",
|
30
31
|
"renovate.json",
|
@@ -22,9 +22,9 @@ class Factbase::CachedFactbase
|
|
22
22
|
# @param [Factbase] origin Original factbase to decorate
|
23
23
|
# @param [Hash] cache Cache to use
|
24
24
|
def initialize(origin, cache = {})
|
25
|
-
raise '
|
25
|
+
raise 'Wrong type of original' unless origin.respond_to?(:query)
|
26
26
|
@origin = origin
|
27
|
-
raise '
|
27
|
+
raise 'Wrong type of cache' unless cache.is_a?(Hash)
|
28
28
|
@cache = cache
|
29
29
|
end
|
30
30
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require 'yaml'
|
7
|
+
require_relative '../factbase'
|
8
|
+
|
9
|
+
# Single fact to YAML converter.
|
10
|
+
#
|
11
|
+
# This class helps converting a single fact to YAML format, for example:
|
12
|
+
#
|
13
|
+
# require 'factbase/fact_as_yaml'
|
14
|
+
# fb = Factbase.new
|
15
|
+
# f = fb.query('(eq foo 42)').to_a.first
|
16
|
+
# puts Factbase::FactAsYaml.new(f).to_s
|
17
|
+
#
|
18
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
19
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
20
|
+
# License:: MIT
|
21
|
+
class Factbase::FactAsYaml
|
22
|
+
# Constructor.
|
23
|
+
def initialize(fact)
|
24
|
+
@fact = fact
|
25
|
+
end
|
26
|
+
|
27
|
+
# Convert the fact to YAML.
|
28
|
+
# @return [String] The fact in YAML format
|
29
|
+
def to_s
|
30
|
+
props = @fact.all_properties
|
31
|
+
hash = {}
|
32
|
+
props.each do |p|
|
33
|
+
v = @fact[p]
|
34
|
+
hash[p] = v.is_a?(Array) ? v : [v]
|
35
|
+
end
|
36
|
+
hash.sort.to_h.to_yaml
|
37
|
+
end
|
38
|
+
end
|
@@ -22,9 +22,9 @@ class Factbase::IndexedFactbase
|
|
22
22
|
# @param [Factbase] origin Original factbase to decorate
|
23
23
|
# @param [Hash] idx Index to use
|
24
24
|
def initialize(origin, idx = {})
|
25
|
-
raise '
|
25
|
+
raise 'Wrong type of original' unless origin.respond_to?(:query)
|
26
26
|
@origin = origin
|
27
|
-
raise '
|
27
|
+
raise 'Wrong type of index' unless idx.is_a?(Hash)
|
28
28
|
@idx = idx
|
29
29
|
end
|
30
30
|
|
data/lib/factbase.rb
CHANGED
@@ -82,7 +82,7 @@ require 'yaml'
|
|
82
82
|
# License:: MIT
|
83
83
|
class Factbase
|
84
84
|
# Current version of the gem (changed by .rultor.yml on every release)
|
85
|
-
VERSION = '0.
|
85
|
+
VERSION = '0.11.0' unless const_defined?(:VERSION)
|
86
86
|
|
87
87
|
# An exception that may be thrown in a transaction, to roll it back.
|
88
88
|
class Rollback < StandardError; end
|
@@ -32,4 +32,13 @@ class TestCachedFactbase < Factbase::Test
|
|
32
32
|
refute_empty(origin.query('(exists bar)').each.to_a)
|
33
33
|
refute_empty(fb.query('(exists bar)').each.to_a)
|
34
34
|
end
|
35
|
+
|
36
|
+
def test_prints_fact_correctly
|
37
|
+
fb = Factbase::CachedFactbase.new(Factbase.new)
|
38
|
+
f1 = fb.insert
|
39
|
+
f1.foo = 42
|
40
|
+
assert_equal('[ foo: [42] ]', f1.to_s)
|
41
|
+
f2 = fb.query('(always)').each.to_a.first
|
42
|
+
assert_equal('[ foo: [42] ] + {}', f2.to_s)
|
43
|
+
end
|
35
44
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Yegor Bugayenko
|
4
|
+
# SPDX-License-Identifier: MIT
|
5
|
+
|
6
|
+
require 'yaml'
|
7
|
+
require_relative '../../lib/factbase'
|
8
|
+
require_relative '../../lib/factbase/fact_as_yaml'
|
9
|
+
require_relative '../test__helper'
|
10
|
+
|
11
|
+
# Test.
|
12
|
+
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
13
|
+
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
14
|
+
# License:: MIT
|
15
|
+
class TestFactAsYaml < Factbase::Test
|
16
|
+
def test_simple_rendering
|
17
|
+
fb = Factbase.new
|
18
|
+
f = fb.insert
|
19
|
+
f._id = 1
|
20
|
+
f.foo = 42
|
21
|
+
f.bar = 'hello'
|
22
|
+
yaml_str = Factbase::FactAsYaml.new(f).to_s
|
23
|
+
yaml = YAML.load(yaml_str)
|
24
|
+
assert_equal(1, yaml['_id'][0])
|
25
|
+
assert_equal('hello', yaml['bar'][0])
|
26
|
+
assert_equal(42, yaml['foo'][0])
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_multiple_values
|
30
|
+
fb = Factbase.new
|
31
|
+
f = fb.insert
|
32
|
+
f.foo = 42
|
33
|
+
f.foo = 256
|
34
|
+
f.foo = 512
|
35
|
+
yaml_str = Factbase::FactAsYaml.new(f).to_s
|
36
|
+
yaml = YAML.load(yaml_str)
|
37
|
+
assert_equal([42, 256, 512], yaml['foo'])
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_sorted_keys
|
41
|
+
fb = Factbase.new
|
42
|
+
f = fb.insert
|
43
|
+
f.c = 3
|
44
|
+
f.a = 1
|
45
|
+
f.b = 2
|
46
|
+
yaml_str = Factbase::FactAsYaml.new(f).to_s
|
47
|
+
assert_operator(yaml_str.index('a:'), :<, yaml_str.index('b:'))
|
48
|
+
assert_operator(yaml_str.index('b:'), :<, yaml_str.index('c:'))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_usage_example_from_issue
|
52
|
+
fb = Factbase.new
|
53
|
+
f = fb.insert
|
54
|
+
f._id = 1
|
55
|
+
f.name = 'test'
|
56
|
+
f = fb.query('(eq _id 1)').each.to_a.first
|
57
|
+
yaml_str = Factbase::FactAsYaml.new(f).to_s
|
58
|
+
assert(yaml_str)
|
59
|
+
assert_includes(yaml_str, '_id')
|
60
|
+
assert_includes(yaml_str, 'name')
|
61
|
+
end
|
62
|
+
end
|
data/test/factbase/test_query.rb
CHANGED
@@ -197,7 +197,7 @@ class TestQuery < Factbase::Test
|
|
197
197
|
end
|
198
198
|
end
|
199
199
|
|
200
|
-
def
|
200
|
+
def test_finds_with_substitution
|
201
201
|
maps = [{ 'foo' => [42] }, { 'bar' => [7] }, { 'foo' => [666] }]
|
202
202
|
with_factbases(maps) do |badge, fb|
|
203
203
|
assert_equal(0, fb.query('(eq 2 (agg (eq foo $foo) (count)))').each.to_a.size, "with #{badge}")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
@@ -157,6 +157,7 @@ files:
|
|
157
157
|
- ".github/workflows/pdd.yml"
|
158
158
|
- ".github/workflows/rake.yml"
|
159
159
|
- ".github/workflows/reuse.yml"
|
160
|
+
- ".github/workflows/typos.yml"
|
160
161
|
- ".github/workflows/xcop.yml"
|
161
162
|
- ".github/workflows/yamllint.yml"
|
162
163
|
- ".gitignore"
|
@@ -200,6 +201,7 @@ files:
|
|
200
201
|
- lib/factbase/cached/cached_term.rb
|
201
202
|
- lib/factbase/churn.rb
|
202
203
|
- lib/factbase/fact.rb
|
204
|
+
- lib/factbase/fact_as_yaml.rb
|
203
205
|
- lib/factbase/flatten.rb
|
204
206
|
- lib/factbase/indexed/indexed_fact.rb
|
205
207
|
- lib/factbase/indexed/indexed_factbase.rb
|
@@ -255,6 +257,7 @@ files:
|
|
255
257
|
- test/factbase/test_accum.rb
|
256
258
|
- test/factbase/test_churn.rb
|
257
259
|
- test/factbase/test_fact.rb
|
260
|
+
- test/factbase/test_fact_as_yaml.rb
|
258
261
|
- test/factbase/test_flatten.rb
|
259
262
|
- test/factbase/test_inv.rb
|
260
263
|
- test/factbase/test_logged.rb
|