judges 0.1.0 → 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/Gemfile +2 -2
- data/Gemfile.lock +16 -7
- data/features/test.feature +17 -1
- data/features/update.feature +2 -2
- data/fixtures/try/try.rb +1 -1
- data/judges.gemspec +2 -2
- data/lib/judges/commands/test.rb +16 -5
- data/lib/judges/commands/update.rb +4 -3
- data/lib/judges/judge.rb +0 -2
- data/lib/judges.rb +1 -1
- data/test/test_judge.rb +0 -23
- metadata +4 -8
- data/lib/judges/fb/if_absent.rb +0 -74
- data/lib/judges/fb/once.rb +0 -54
- data/test/fb/test_if_absent.rb +0 -103
- data/test/fb/test_once.rb +0 -88
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: be8151f228edd7b8c45f0fcf1f566e8585fae93ce87bcb7f56ca6f452a1b67ca
|
|
4
|
+
data.tar.gz: 99e20604a1f8a78a0c5dbf4080522aab725a7e82df5cb87d3b456962636aad10
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2df81af8fd18810e54c05fc3631a2e38037d45e49a7f87cd4e9e8592155b155b81671ad5641e3923886e86752fa3be8c5f7926f2ce539d48ccfac714269f44d4
|
|
7
|
+
data.tar.gz: 6fd2568f060510bc0b0600cc9d186d622025a7f886085bf5993bc3388f246c283c2c08c785199d609fd7a4729eb949a27a829d199785d43334addbdcd7f51248
|
data/Gemfile
CHANGED
|
@@ -28,9 +28,9 @@ gem 'minitest', '5.23.1', require: false
|
|
|
28
28
|
gem 'net-ping', '2.0.8', require: false
|
|
29
29
|
gem 'rake', '13.2.1', require: false
|
|
30
30
|
gem 'rspec-rails', '6.1.2', require: false
|
|
31
|
-
gem 'rubocop', '1.64.
|
|
31
|
+
gem 'rubocop', '1.64.1', require: false
|
|
32
32
|
gem 'rubocop-performance', '1.21.0', require: false
|
|
33
|
-
gem 'rubocop-rspec', '2.
|
|
33
|
+
gem 'rubocop-rspec', '2.30.0', require: false
|
|
34
34
|
gem 'simplecov', '0.22.0', require: false
|
|
35
35
|
gem 'simplecov-cobertura', '2.1.0', require: false
|
|
36
36
|
gem 'webmock', '3.23.1', require: false
|
data/Gemfile.lock
CHANGED
|
@@ -4,7 +4,7 @@ PATH
|
|
|
4
4
|
judges (0.0.0)
|
|
5
5
|
backtrace (~> 0.3)
|
|
6
6
|
concurrent-ruby (= 1.2.3)
|
|
7
|
-
factbase (~> 0.0
|
|
7
|
+
factbase (~> 0.0)
|
|
8
8
|
gli (~> 2.21)
|
|
9
9
|
iri (~> 0.8)
|
|
10
10
|
loog (~> 0.2)
|
|
@@ -84,12 +84,18 @@ GEM
|
|
|
84
84
|
erubi (1.12.0)
|
|
85
85
|
ethon (0.16.0)
|
|
86
86
|
ffi (>= 1.15.0)
|
|
87
|
-
factbase (0.0.
|
|
87
|
+
factbase (0.0.41)
|
|
88
88
|
json (~> 2.7)
|
|
89
89
|
loog (~> 0.2)
|
|
90
90
|
nokogiri (~> 1.10)
|
|
91
91
|
yaml (~> 0.3)
|
|
92
|
-
ffi (1.
|
|
92
|
+
ffi (1.17.0-aarch64-linux-gnu)
|
|
93
|
+
ffi (1.17.0-arm-linux-gnu)
|
|
94
|
+
ffi (1.17.0-arm64-darwin)
|
|
95
|
+
ffi (1.17.0-x64-mingw-ucrt)
|
|
96
|
+
ffi (1.17.0-x86-linux-gnu)
|
|
97
|
+
ffi (1.17.0-x86_64-darwin)
|
|
98
|
+
ffi (1.17.0-x86_64-linux-gnu)
|
|
93
99
|
gli (2.21.1)
|
|
94
100
|
hashdiff (1.1.0)
|
|
95
101
|
i18n (1.14.5)
|
|
@@ -116,6 +122,8 @@ GEM
|
|
|
116
122
|
racc (~> 1.4)
|
|
117
123
|
nokogiri (1.16.5-arm64-darwin)
|
|
118
124
|
racc (~> 1.4)
|
|
125
|
+
nokogiri (1.16.5-x64-mingw-ucrt)
|
|
126
|
+
racc (~> 1.4)
|
|
119
127
|
nokogiri (1.16.5-x86-linux)
|
|
120
128
|
racc (~> 1.4)
|
|
121
129
|
nokogiri (1.16.5-x86_64-darwin)
|
|
@@ -179,7 +187,7 @@ GEM
|
|
|
179
187
|
rspec-mocks (~> 3.13)
|
|
180
188
|
rspec-support (~> 3.13)
|
|
181
189
|
rspec-support (3.13.1)
|
|
182
|
-
rubocop (1.64.
|
|
190
|
+
rubocop (1.64.1)
|
|
183
191
|
json (~> 2.3)
|
|
184
192
|
language_server-protocol (>= 3.17.0)
|
|
185
193
|
parallel (~> 1.10)
|
|
@@ -199,7 +207,7 @@ GEM
|
|
|
199
207
|
rubocop-performance (1.21.0)
|
|
200
208
|
rubocop (>= 1.48.1, < 2.0)
|
|
201
209
|
rubocop-ast (>= 1.31.1, < 2.0)
|
|
202
|
-
rubocop-rspec (2.
|
|
210
|
+
rubocop-rspec (2.30.0)
|
|
203
211
|
rubocop (~> 1.40)
|
|
204
212
|
rubocop-capybara (~> 2.17)
|
|
205
213
|
rubocop-factory_bot (~> 2.22)
|
|
@@ -239,6 +247,7 @@ PLATFORMS
|
|
|
239
247
|
aarch64-linux
|
|
240
248
|
arm-linux
|
|
241
249
|
arm64-darwin
|
|
250
|
+
x64-mingw-ucrt
|
|
242
251
|
x86-linux
|
|
243
252
|
x86_64-darwin
|
|
244
253
|
x86_64-linux
|
|
@@ -250,9 +259,9 @@ DEPENDENCIES
|
|
|
250
259
|
net-ping (= 2.0.8)
|
|
251
260
|
rake (= 13.2.1)
|
|
252
261
|
rspec-rails (= 6.1.2)
|
|
253
|
-
rubocop (= 1.64.
|
|
262
|
+
rubocop (= 1.64.1)
|
|
254
263
|
rubocop-performance (= 1.21.0)
|
|
255
|
-
rubocop-rspec (= 2.
|
|
264
|
+
rubocop-rspec (= 2.30.0)
|
|
256
265
|
simplecov (= 0.22.0)
|
|
257
266
|
simplecov-cobertura (= 2.1.0)
|
|
258
267
|
webmock (= 3.23.1)
|
data/features/test.feature
CHANGED
|
@@ -14,6 +14,16 @@ Feature: Test
|
|
|
14
14
|
|
|
15
15
|
Scenario: Simple test of no judges
|
|
16
16
|
Given I run bin/judges with "test --judge absent_for_sure ./fixtures"
|
|
17
|
+
Then Exit code is zero
|
|
18
|
+
|
|
19
|
+
Scenario: Simple test of no judges at all
|
|
20
|
+
Given I make a temp directory
|
|
21
|
+
Given I run bin/judges with "test ."
|
|
22
|
+
Then Exit code is not zero
|
|
23
|
+
|
|
24
|
+
Scenario: Simple test of no judges at all
|
|
25
|
+
Given I make a temp directory
|
|
26
|
+
Given I run bin/judges with "test --judge some ."
|
|
17
27
|
Then Exit code is not zero
|
|
18
28
|
|
|
19
29
|
Scenario: Simple test of a few judges, with a lib
|
|
@@ -23,12 +33,18 @@ Feature: Test
|
|
|
23
33
|
n = $fb.insert
|
|
24
34
|
n.foo = $foo
|
|
25
35
|
"""
|
|
36
|
+
Then I have a "myjudges/myjudge/good.yml" file with content:
|
|
37
|
+
"""
|
|
38
|
+
---
|
|
39
|
+
category: good
|
|
40
|
+
input: []
|
|
41
|
+
"""
|
|
26
42
|
Then I have a "mylib/foo.rb" file with content:
|
|
27
43
|
"""
|
|
28
44
|
$foo = 42
|
|
29
45
|
"""
|
|
30
46
|
Then I run bin/judges with "test --lib mylib myjudges"
|
|
31
|
-
Then Stdout contains "All 1 judge(s)
|
|
47
|
+
Then Stdout contains "All 1 judge(s) and 1 tests passed"
|
|
32
48
|
And Exit code is zero
|
|
33
49
|
|
|
34
50
|
Scenario: Enable only one category
|
data/features/update.feature
CHANGED
|
@@ -12,7 +12,7 @@ Feature: Update
|
|
|
12
12
|
Then Stdout contains "foo → "
|
|
13
13
|
Then Stdout contains "bar → "
|
|
14
14
|
Then Stdout contains "1 judge(s) processed"
|
|
15
|
-
Then Stdout contains "Update finished
|
|
15
|
+
Then Stdout contains "Update finished in 3 cycle(s), +3 fact(s)"
|
|
16
16
|
And Exit code is zero
|
|
17
17
|
|
|
18
18
|
Scenario: Simple run of a few judges, with a lib
|
|
@@ -28,7 +28,7 @@ Feature: Update
|
|
|
28
28
|
"""
|
|
29
29
|
Then I run bin/judges with "update --lib mylib --max-cycles 1 mine simple.fb"
|
|
30
30
|
Then Stdout contains "1 judge(s) processed"
|
|
31
|
-
Then Stdout contains "Update finished
|
|
31
|
+
Then Stdout contains "Update finished in 1 cycle(s)"
|
|
32
32
|
And Exit code is zero
|
|
33
33
|
|
|
34
34
|
Scenario: The update fails when a bug in a judge
|
data/fixtures/try/try.rb
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
# SOFTWARE.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
$fb.query("(and (exists number) (lt time #{Time.now.utc.iso8601}))").each do |f|
|
|
24
24
|
n = $fb.insert
|
|
25
25
|
n.guess = f.number
|
|
26
26
|
end
|
data/judges.gemspec
CHANGED
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
|
27
27
|
s.required_ruby_version = '>=3.2'
|
|
28
28
|
s.name = 'judges'
|
|
29
|
-
s.version = '0.
|
|
29
|
+
s.version = '0.3.0'
|
|
30
30
|
s.license = 'MIT'
|
|
31
31
|
s.summary = 'Command-Line Tool for a Factbase'
|
|
32
32
|
s.description =
|
|
@@ -44,7 +44,7 @@ Gem::Specification.new do |s|
|
|
|
44
44
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
|
45
45
|
s.add_runtime_dependency 'backtrace', '~> 0.3'
|
|
46
46
|
s.add_runtime_dependency 'concurrent-ruby', '1.2.3'
|
|
47
|
-
s.add_runtime_dependency 'factbase', '~>0.0
|
|
47
|
+
s.add_runtime_dependency 'factbase', '~>0.0'
|
|
48
48
|
s.add_runtime_dependency 'gli', '~>2.21'
|
|
49
49
|
s.add_runtime_dependency 'iri', '~>0.8'
|
|
50
50
|
s.add_runtime_dependency 'loog', '~>0.2'
|
data/lib/judges/commands/test.rb
CHANGED
|
@@ -48,11 +48,16 @@ class Judges::Test
|
|
|
48
48
|
errors = []
|
|
49
49
|
judges = 0
|
|
50
50
|
tests = 0
|
|
51
|
+
visible = []
|
|
51
52
|
elapsed(@loog) do
|
|
52
53
|
Judges::Judges.new(dir, opts['lib'], @loog).each_with_index do |p, i|
|
|
54
|
+
visible << p.name
|
|
53
55
|
next unless include?(opts, p.name)
|
|
54
56
|
@loog.info("\n👉 Testing #{p.script} (##{i}) in #{p.dir.to_rel}...")
|
|
55
57
|
p.tests.each do |f|
|
|
58
|
+
tname = File.basename(f).gsub(/\.yml$/, '')
|
|
59
|
+
visible << " #{p.name}/#{tname}"
|
|
60
|
+
next unless include?(opts, p.name, tname)
|
|
56
61
|
yaml = YAML.load_file(f, permitted_classes: [Time])
|
|
57
62
|
if yaml['skip']
|
|
58
63
|
@loog.info("Skippped #{f.to_rel}")
|
|
@@ -82,17 +87,23 @@ class Judges::Test
|
|
|
82
87
|
raise "#{errors.size} tests failed" unless opts['quiet']
|
|
83
88
|
@loog.debug('Not failing the build with tests failures, due to the --quiet option')
|
|
84
89
|
end
|
|
85
|
-
return unless judges.zero?
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
return unless judges.zero? || tests.zero?
|
|
91
|
+
if opts['judge'].nil?
|
|
92
|
+
raise 'There are seems to be no judges' unless opts['quiet']
|
|
93
|
+
@loog.debug('Not failing the build with no judges tested, due to the --quiet option')
|
|
94
|
+
else
|
|
95
|
+
raise 'There are seems to be no judges' if visible.empty?
|
|
96
|
+
@loog.info("The following judges are available to use with the --judge option:\n #{visible.join("\n ")}")
|
|
97
|
+
end
|
|
88
98
|
end
|
|
89
99
|
|
|
90
100
|
private
|
|
91
101
|
|
|
92
|
-
def include?(opts, name)
|
|
102
|
+
def include?(opts, name, tname = nil)
|
|
93
103
|
judges = opts['judge'] || []
|
|
94
104
|
return true if judges.empty?
|
|
95
|
-
|
|
105
|
+
tre = tname.nil? ? '.+' : tname
|
|
106
|
+
judges.any? { |n| n.match?(%r{^#{name}(/#{tre})?$}) }
|
|
96
107
|
end
|
|
97
108
|
|
|
98
109
|
def test_one(opts, judge, yaml)
|
|
@@ -45,6 +45,7 @@ class Judges::Update
|
|
|
45
45
|
impex = Judges::Impex.new(@loog, args[1])
|
|
46
46
|
fb = impex.import(strict: false)
|
|
47
47
|
fb = Factbase::Looged.new(fb, @loog)
|
|
48
|
+
before = fb.size
|
|
48
49
|
options = Judges::Options.new(opts['option'])
|
|
49
50
|
@loog.debug("The following options provided:\n\t#{options.to_s.gsub("\n", "\n\t")}")
|
|
50
51
|
judges = Judges::Judges.new(dir, opts['lib'], @loog)
|
|
@@ -66,12 +67,12 @@ class Judges::Update
|
|
|
66
67
|
break
|
|
67
68
|
end
|
|
68
69
|
@loog.info(
|
|
69
|
-
"By #{diff}
|
|
70
|
+
"By #{diff.abs} fact(s) the factbase " \
|
|
70
71
|
"#{diff.positive? ? 'increased' : 'decreased'} " \
|
|
71
72
|
"its size at the cycle ##{c}"
|
|
72
73
|
)
|
|
73
74
|
end
|
|
74
|
-
throw :"Update finished
|
|
75
|
+
throw :"Update finished in #{c} cycle(s), #{format('+%d', fb.size - before)} fact(s)"
|
|
75
76
|
end
|
|
76
77
|
end
|
|
77
78
|
|
|
@@ -84,7 +85,7 @@ class Judges::Update
|
|
|
84
85
|
elapsed(@loog) do
|
|
85
86
|
done = judges.each_with_index do |p, i|
|
|
86
87
|
local = {}
|
|
87
|
-
@loog.info("👉 Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
|
|
88
|
+
@loog.info("\n👉 Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
|
|
88
89
|
before = fb.size
|
|
89
90
|
begin
|
|
90
91
|
p.run(fb, global, local, options)
|
data/lib/judges/judge.rb
CHANGED
|
@@ -23,8 +23,6 @@
|
|
|
23
23
|
require_relative '../judges'
|
|
24
24
|
require_relative '../judges/to_rel'
|
|
25
25
|
require_relative '../judges/elapsed'
|
|
26
|
-
require_relative '../judges/fb/once'
|
|
27
|
-
require_relative '../judges/fb/if_absent'
|
|
28
26
|
|
|
29
27
|
# A single judge.
|
|
30
28
|
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
data/lib/judges.rb
CHANGED
data/test/test_judge.rb
CHANGED
|
@@ -55,14 +55,6 @@ class TestPack < Minitest::Test
|
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
def test_with_supplemenary_functions
|
|
59
|
-
Dir.mktmpdir do |d|
|
|
60
|
-
File.write(File.join(d, 'x.rb'), 'each_once($fb, "(always)").to_a')
|
|
61
|
-
judge = Judges::Judge.new(d, nil, Loog::NULL)
|
|
62
|
-
judge.run(Factbase.new, {}, {}, {})
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
58
|
def test_passes_local_vars_between_tests
|
|
67
59
|
Dir.mktmpdir do |d|
|
|
68
60
|
File.write(
|
|
@@ -93,21 +85,6 @@ class TestPack < Minitest::Test
|
|
|
93
85
|
end
|
|
94
86
|
end
|
|
95
87
|
|
|
96
|
-
def test_with_library
|
|
97
|
-
Dir.mktmpdir do |d|
|
|
98
|
-
dir = File.join(d, 'judges')
|
|
99
|
-
FileUtils.mkdir_p(dir)
|
|
100
|
-
File.write(File.join(dir, 'x.rb'), '$fb.insert.bar = $foo; each_once($fb, "(always)").to_a')
|
|
101
|
-
lib = File.join(d, 'lib')
|
|
102
|
-
FileUtils.mkdir_p(lib)
|
|
103
|
-
File.write(File.join(lib, 'y.rb'), '$foo = 42')
|
|
104
|
-
judge = Judges::Judge.new(dir, lib, Loog::NULL)
|
|
105
|
-
fb = Factbase.new
|
|
106
|
-
judge.run(fb, {}, {}, {})
|
|
107
|
-
assert_equal(42, fb.query('(always)').each.to_a.first.bar)
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
|
|
111
88
|
def test_with_broken_ruby_syntax
|
|
112
89
|
assert_raises do
|
|
113
90
|
Dir.mktmpdir do |d|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: judges
|
|
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-06-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: backtrace
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.0
|
|
47
|
+
version: '0.0'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.0
|
|
54
|
+
version: '0.0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: gli
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -187,8 +187,6 @@ files:
|
|
|
187
187
|
- lib/judges/commands/trim.rb
|
|
188
188
|
- lib/judges/commands/update.rb
|
|
189
189
|
- lib/judges/elapsed.rb
|
|
190
|
-
- lib/judges/fb/if_absent.rb
|
|
191
|
-
- lib/judges/fb/once.rb
|
|
192
190
|
- lib/judges/impex.rb
|
|
193
191
|
- lib/judges/judge.rb
|
|
194
192
|
- lib/judges/judges.rb
|
|
@@ -205,8 +203,6 @@ files:
|
|
|
205
203
|
- test/commands/test_test.rb
|
|
206
204
|
- test/commands/test_trim.rb
|
|
207
205
|
- test/commands/test_update.rb
|
|
208
|
-
- test/fb/test_if_absent.rb
|
|
209
|
-
- test/fb/test_once.rb
|
|
210
206
|
- test/test__helper.rb
|
|
211
207
|
- test/test_baza.rb
|
|
212
208
|
- test/test_categories.rb
|
data/lib/judges/fb/if_absent.rb
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright (c) 2024 Yegor Bugayenko
|
|
4
|
-
#
|
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
# of this software and associated documentation files (the 'Software'), to deal
|
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
# furnished to do so, subject to the following conditions:
|
|
11
|
-
#
|
|
12
|
-
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
# copies or substantial portions of the Software.
|
|
14
|
-
#
|
|
15
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
# SOFTWARE.
|
|
22
|
-
|
|
23
|
-
require 'judges'
|
|
24
|
-
require 'time'
|
|
25
|
-
|
|
26
|
-
# Injects a fact if it's absent in the factbase.
|
|
27
|
-
def if_absent(fb)
|
|
28
|
-
attrs = {}
|
|
29
|
-
f = Judges::Accumulator.new(attrs)
|
|
30
|
-
yield f
|
|
31
|
-
q = attrs.map do |k, v|
|
|
32
|
-
vv = v.to_s
|
|
33
|
-
if v.is_a?(String)
|
|
34
|
-
vv = "'#{vv.gsub('"', '\\\\"').gsub("'", "\\\\'")}'"
|
|
35
|
-
elsif v.is_a?(Time)
|
|
36
|
-
vv = v.utc.iso8601
|
|
37
|
-
end
|
|
38
|
-
"(eq #{k} #{vv})"
|
|
39
|
-
end.join(' ')
|
|
40
|
-
q = "(and #{q})"
|
|
41
|
-
return unless fb.query(q).each.to_a.empty?
|
|
42
|
-
n = fb.insert
|
|
43
|
-
attrs.each { |k, v| n.send("#{k}=", v) }
|
|
44
|
-
n
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Predents to be a fact, just accumulating all attribute sets.
|
|
48
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
49
|
-
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
|
50
|
-
# License:: MIT
|
|
51
|
-
class Judges::Accumulator
|
|
52
|
-
def initialize(map)
|
|
53
|
-
@map = map
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def method_missing(*args)
|
|
57
|
-
k = args[0]
|
|
58
|
-
if k.end_with?('=')
|
|
59
|
-
@map[k[0..-2].to_sym] = args[1]
|
|
60
|
-
else
|
|
61
|
-
@map[k.to_sym]
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# rubocop:disable Style/OptionalBooleanParameter
|
|
66
|
-
def respond_to?(_method, _include_private = false)
|
|
67
|
-
# rubocop:enable Style/OptionalBooleanParameter
|
|
68
|
-
true
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def respond_to_missing?(_method, _include_private = false)
|
|
72
|
-
true
|
|
73
|
-
end
|
|
74
|
-
end
|
data/lib/judges/fb/once.rb
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright (c) 2024 Yegor Bugayenko
|
|
4
|
-
#
|
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
# of this software and associated documentation files (the 'Software'), to deal
|
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
# furnished to do so, subject to the following conditions:
|
|
11
|
-
#
|
|
12
|
-
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
# copies or substantial portions of the Software.
|
|
14
|
-
#
|
|
15
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
# SOFTWARE.
|
|
22
|
-
|
|
23
|
-
require 'judges'
|
|
24
|
-
require 'factbase/tuples'
|
|
25
|
-
|
|
26
|
-
# Returns a decorated global factbase, which only touches facts once.
|
|
27
|
-
def each_once(fb, query, judge: $judge)
|
|
28
|
-
return to_enum(__method__, fb, query, judge:) unless block_given?
|
|
29
|
-
q = "(and #{query} (not (eq seen '#{judge}')))"
|
|
30
|
-
fb.query(q).each do |f|
|
|
31
|
-
yield f
|
|
32
|
-
f.seen = judge
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Returns a decorated global factbase, which only touches a tuple once.
|
|
37
|
-
def each_tuple_once(fb, *queries, judge: $judge)
|
|
38
|
-
return to_enum(__method__, fb, *queries, judge:) unless block_given?
|
|
39
|
-
qq = queries.map { |q| "(and #{q} (not (eq seen '#{judge}')))" }
|
|
40
|
-
Factbase::Tuples.new(fb, qq).each do |fs|
|
|
41
|
-
yield fs
|
|
42
|
-
fs.each do |f|
|
|
43
|
-
f.seen = judge
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def each_tuple_once_txn(fb, *queries, judge: $judge)
|
|
49
|
-
fb.txn do |fbt|
|
|
50
|
-
each_tuple_once(fb, *queries, judge:) do |fs|
|
|
51
|
-
yield [fbt] + fs
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
data/test/fb/test_if_absent.rb
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright (c) 2024 Yegor Bugayenko
|
|
4
|
-
#
|
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
# of this software and associated documentation files (the 'Software'), to deal
|
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
# furnished to do so, subject to the following conditions:
|
|
11
|
-
#
|
|
12
|
-
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
# copies or substantial portions of the Software.
|
|
14
|
-
#
|
|
15
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
# SOFTWARE.
|
|
22
|
-
|
|
23
|
-
require 'minitest/autorun'
|
|
24
|
-
require 'tmpdir'
|
|
25
|
-
require 'factbase'
|
|
26
|
-
require 'factbase/looged'
|
|
27
|
-
require 'loog'
|
|
28
|
-
require_relative '../../lib/judges'
|
|
29
|
-
require_relative '../../lib/judges/fb/if_absent'
|
|
30
|
-
|
|
31
|
-
# Test.
|
|
32
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
33
|
-
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
|
34
|
-
# License:: MIT
|
|
35
|
-
class TestIfAbsent < Minitest::Test
|
|
36
|
-
def test_ignores
|
|
37
|
-
fb = Factbase.new
|
|
38
|
-
fb.insert.foo = 'hello dude'
|
|
39
|
-
n = if_absent(fb) do |f|
|
|
40
|
-
f.foo = 'hello dude'
|
|
41
|
-
end
|
|
42
|
-
assert(n.nil?)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def test_ignores_with_time
|
|
46
|
-
fb = Factbase.new
|
|
47
|
-
t = Time.now
|
|
48
|
-
fb.insert.foo = t
|
|
49
|
-
n = if_absent(fb) do |f|
|
|
50
|
-
f.foo = t
|
|
51
|
-
end
|
|
52
|
-
assert(n.nil?)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def test_injects
|
|
56
|
-
fb = Factbase.new
|
|
57
|
-
n = if_absent(fb) do |f|
|
|
58
|
-
f.foo = 42
|
|
59
|
-
end
|
|
60
|
-
assert_equal(42, n.foo)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def test_injects_and_reads
|
|
64
|
-
if_absent(Factbase.new) do |f|
|
|
65
|
-
f.foo = 42
|
|
66
|
-
assert_equal(42, f.foo)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def test_complex_ignores
|
|
71
|
-
fb = Factbase.new
|
|
72
|
-
f1 = fb.insert
|
|
73
|
-
f1.foo = 'hello, "dude"!'
|
|
74
|
-
f1.abc = 42
|
|
75
|
-
t = Time.now
|
|
76
|
-
f1.z = t
|
|
77
|
-
f1.bar = 3.14
|
|
78
|
-
n = if_absent(fb) do |f|
|
|
79
|
-
f.foo = 'hello, "dude"!'
|
|
80
|
-
f.abc = 42
|
|
81
|
-
f.z = t
|
|
82
|
-
f.bar = 3.14
|
|
83
|
-
end
|
|
84
|
-
assert(n.nil?)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def test_complex_injects
|
|
88
|
-
fb = Factbase.new
|
|
89
|
-
f1 = fb.insert
|
|
90
|
-
f1.foo = 'hello, dude!'
|
|
91
|
-
f1.abc = 42
|
|
92
|
-
t = Time.now
|
|
93
|
-
f1.z = t
|
|
94
|
-
f1.bar = 3.14
|
|
95
|
-
n = if_absent(fb) do |f|
|
|
96
|
-
f.foo = "hello, \\\"dude\\\" \\' \\' ( \n\n ) (! '"
|
|
97
|
-
f.abc = 42
|
|
98
|
-
f.z = t + 1
|
|
99
|
-
f.bar = 3.15
|
|
100
|
-
end
|
|
101
|
-
assert(!n.nil?)
|
|
102
|
-
end
|
|
103
|
-
end
|
data/test/fb/test_once.rb
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright (c) 2024 Yegor Bugayenko
|
|
4
|
-
#
|
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
# of this software and associated documentation files (the 'Software'), to deal
|
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
# furnished to do so, subject to the following conditions:
|
|
11
|
-
#
|
|
12
|
-
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
# copies or substantial portions of the Software.
|
|
14
|
-
#
|
|
15
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
# SOFTWARE.
|
|
22
|
-
|
|
23
|
-
require 'minitest/autorun'
|
|
24
|
-
require 'factbase'
|
|
25
|
-
require_relative '../../lib/judges'
|
|
26
|
-
require_relative '../../lib/judges/fb/once'
|
|
27
|
-
|
|
28
|
-
# Test.
|
|
29
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
|
30
|
-
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
|
31
|
-
# License:: MIT
|
|
32
|
-
class TestOnce < Minitest::Test
|
|
33
|
-
def test_touch_once
|
|
34
|
-
fb = Factbase.new
|
|
35
|
-
fb.insert
|
|
36
|
-
assert(!each_once(fb, '(always)', judge: 'something').to_a.empty?)
|
|
37
|
-
assert(each_once(fb, '(always)', judge: 'something').to_a.empty?)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def test_seen_property
|
|
41
|
-
fb = Factbase.new
|
|
42
|
-
f1 = fb.insert
|
|
43
|
-
f1.foo = 42
|
|
44
|
-
assert_equal(1, each_tuple_once(fb, '(eq foo 42)', judge: 'x').to_a.size)
|
|
45
|
-
assert(each_tuple_once(fb, '(eq foo 42)', judge: 'x').to_a.empty?)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def test_seen_all_or_nothing
|
|
49
|
-
fb = Factbase.new
|
|
50
|
-
f1 = fb.insert
|
|
51
|
-
f1.a = 1
|
|
52
|
-
assert(each_tuple_once(fb, '(exists a)', '(exists b)', judge: 'x').to_a.empty?)
|
|
53
|
-
f2 = fb.insert
|
|
54
|
-
f2.b = 1
|
|
55
|
-
assert(!each_tuple_once(fb, '(exists a)', '(exists b)', judge: 'x').to_a.empty?)
|
|
56
|
-
assert(each_tuple_once(fb, '(exists a)', '(exists b)', judge: 'x').to_a.empty?)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def test_with_txn
|
|
60
|
-
fb = Factbase.new
|
|
61
|
-
f1 = fb.insert
|
|
62
|
-
f1.foo = 42
|
|
63
|
-
each_tuple_once(fb, '(exists foo)', judge: 'xx') do |fs|
|
|
64
|
-
fb.txn do |fbt|
|
|
65
|
-
f = fbt.insert
|
|
66
|
-
f.bar = 1
|
|
67
|
-
end
|
|
68
|
-
fs[0].xyz = 'hey'
|
|
69
|
-
end
|
|
70
|
-
assert_equal(1, fb.query('(exists seen)').each.to_a.size)
|
|
71
|
-
assert_equal(1, fb.query('(exists bar)').each.to_a.size)
|
|
72
|
-
assert_equal(1, fb.query('(exists xyz)').each.to_a.size)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def test_with_chain_txn
|
|
76
|
-
fb = Factbase.new
|
|
77
|
-
f1 = fb.insert
|
|
78
|
-
f1.foo = 42
|
|
79
|
-
each_tuple_once_txn(fb, '(exists foo)', judge: 'xx') do |fbt, ff|
|
|
80
|
-
f = fbt.insert
|
|
81
|
-
f.bar = 1
|
|
82
|
-
ff.xyz = 'hey'
|
|
83
|
-
end
|
|
84
|
-
assert_equal(1, fb.query('(exists seen)').each.to_a.size)
|
|
85
|
-
assert_equal(1, fb.query('(exists bar)').each.to_a.size)
|
|
86
|
-
assert_equal(1, fb.query('(exists xyz)').each.to_a.size)
|
|
87
|
-
end
|
|
88
|
-
end
|