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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cddb3957ecbb2cce6a0957e00759aa8c54edc2b6ce1dae45509968cf22894c7a
4
- data.tar.gz: 880d4fdde6788b80ee1db1a94fdfeed15d98b8fe7a0d8c3c4c0b6611a5cfdf79
3
+ metadata.gz: 474551d14c160969e1361d2518458de199c6777865aedf1a34f5a4de00f22542
4
+ data.tar.gz: ae437f74a4422631c9f3fa3c4a1752b42eadbef4c0c3a2339829d3417a928441
5
5
  SHA512:
6
- metadata.gz: ddd8fce247c59e80ab719451fca226e0598459557cdd33cbcaf21fd8e12b6ae23b82e3cf3173d638414ad2654a6e3a40d6cc586a1d8804df9111a68474e87489
7
- data.tar.gz: 3ef80c4d7e05cc7daa9f8a4e9c38a47c7555693416ab521b2ef589b9abab6ba592e7484171b92df96e77333eae8f36bb85a19e4c9fb63cc2ae06cd3e7d4e2b72
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
@@ -16,4 +16,4 @@ jobs:
16
16
  runs-on: ubuntu-24.04
17
17
  steps:
18
18
  - uses: actions/checkout@v4
19
- - uses: yegor256/copyrights-action@0.0.8
19
+ - uses: yegor256/copyrights-action@0.0.12
@@ -20,4 +20,4 @@ jobs:
20
20
  runs-on: ubuntu-24.04
21
21
  steps:
22
22
  - uses: actions/checkout@v4
23
- - uses: articulate/actions-markdownlint@v1
23
+ - uses: DavidAnson/markdownlint-cli2-action@v20.0.0
@@ -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
@@ -1,10 +1,11 @@
1
- *.gem
2
- .DS_Store
3
1
  .bundle/
2
+ .DS_Store
4
3
  .idea/
5
4
  .yardoc/
5
+ *.gem
6
6
  coverage/
7
7
  doc/
8
8
  node_modules/
9
9
  rdoc/
10
10
  vendor/
11
+ .claude/
data/.rubocop.yml CHANGED
@@ -46,3 +46,4 @@ Security/MarshalLoad:
46
46
  Enabled: false
47
47
  Layout/MultilineAssignmentLayout:
48
48
  Enabled: true
49
+ require: []
data/Gemfile.lock CHANGED
@@ -26,11 +26,13 @@ GEM
26
26
  elapsed (0.0.1)
27
27
  loog (> 0)
28
28
  tago (> 0)
29
- json (2.11.3)
30
- language_server-protocol (3.17.0.4)
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.0)
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.3)
57
+ psych (5.2.6)
56
58
  date
57
59
  stringio
58
- qbash (0.4.0)
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.2.1)
66
- rdoc (6.13.1)
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.4)
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.0)
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 system total real
213
- insert 20000 facts 0.584619 0.003744 0.588363 ( 0.588372)
214
- export 20000 facts 0.019872 0.004992 0.024864 ( 0.024870)
215
- import 411135 bytes (20000 facts) 0.030978 0.004000 0.034978 ( 0.034983)
216
- insert 10 facts 0.043662 0.002056 0.045718 ( 0.045738)
217
- query 10 times w/txn 1.809973 0.034886 1.844859 ( 1.845456)
218
- query 10 times w/o txn 0.039074 0.004004 0.043078 ( 0.043081)
219
- modify 10 attrs w/txn 1.705921 0.015961 1.721882 ( 1.722316)
220
- delete 10 facts w/txn 1.021624 0.007014 1.028638 ( 1.028692)
221
- (and (eq what 'issue-was-closed') (exists... -> 200 2.110981 0.005000 2.115981 ( 2.116099)
222
- (and (eq what 'issue-was-closed') (exists... -> 200/txn 1.125909 0.000000 1.125909 ( 1.125962)
223
- (and (eq what 'issue-was-closed') (exists... -> zero 2.417743 0.000993 2.418736 ( 2.418869)
224
- (and (eq what 'issue-was-closed') (exists... -> zero/txn 1.282409 0.003006 1.285415 ( 1.285498)
225
- (gt time '2024-03-23T03:21:43Z') 0.092167 0.000000 0.092167 ( 0.092169)
226
- (gt cost 50) 0.107435 0.000000 0.107435 ( 0.107438)
227
- (eq title 'Object Thinking 5000') 0.002544 0.000000 0.002544 ( 0.002546)
228
- (and (eq foo 42.998) (or (gt bar 200) (absent zzz))) 0.022142 0.000000 0.022142 ( 0.022143)
229
- (eq id (agg (always) (max id))) 0.244818 0.000000 0.244818 ( 0.244835)
230
- (join "c<=cost,b<=bar" (eq id (agg (always) (max id)))) 0.672133 0.001998 0.674131 ( 0.674186)
231
- delete! 0.074661 0.000000 0.074661 ( 0.074663)
232
- Taped.append() x50000 0.037757 0.004997 0.042754 ( 0.042759)
233
- Taped.each() x125 1.283630 0.001995 1.285625 ( 1.285706)
234
- Taped.delete_if() x375 0.819901 0.000000 0.819901 ( 0.819968)
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-04-07 at 10:33,
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/14306969571
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",
@@ -20,6 +20,10 @@ class Factbase::CachedFact
20
20
  @cache = cache
21
21
  end
22
22
 
23
+ def to_s
24
+ @origin.to_s
25
+ end
26
+
23
27
  # When a method is missing, this method is called.
24
28
  others do |*args|
25
29
  @cache.clear if args[0].to_s.end_with?('=')
@@ -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 'Wront type of original' unless origin.respond_to?(:query)
25
+ raise 'Wrong type of original' unless origin.respond_to?(:query)
26
26
  @origin = origin
27
- raise 'Wront type of cache' unless cache.is_a?(Hash)
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
@@ -20,6 +20,10 @@ class Factbase::IndexedFact
20
20
  @idx = idx
21
21
  end
22
22
 
23
+ def to_s
24
+ @origin.to_s
25
+ end
26
+
23
27
  # When a method is missing, this method is called.
24
28
  others do |*args|
25
29
  @idx.clear if args[0].to_s.end_with?('=')
@@ -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 'Wront type of original' unless origin.respond_to?(:query)
25
+ raise 'Wrong type of original' unless origin.respond_to?(:query)
26
26
  @origin = origin
27
- raise 'Wront type of index' unless idx.is_a?(Hash)
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.10.1' unless const_defined?(:VERSION)
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
@@ -197,7 +197,7 @@ class TestQuery < Factbase::Test
197
197
  end
198
198
  end
199
199
 
200
- def test_finds_with_subsitution
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.10.1
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