judges 0.0.20 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e7ff33d6367a36af90626c45f6ba74195f2e5383bf5f6f30c2888e5ba02eb07
4
- data.tar.gz: b8032fc55743542a488d478cb4eb4dab78b979c2aec60ad6fbbeca3c53eceb5f
3
+ metadata.gz: c7b4a80762cb37240925afe0778c87a829f891a4e5a3a3fb7f22ccc3802c1a3a
4
+ data.tar.gz: 914e85bda9dea1030a06fde8a635d1452ae73c0d3e736e8ef04164cd692df378
5
5
  SHA512:
6
- metadata.gz: 02cb9fee069f3ed10bfad753df016b20b2e1736a66ad9ab633e309f5ae99d5e8445d92f4e909ac826bf95f6cf8b73f3eb2e07968cd38129738e918dcd8f972aa
7
- data.tar.gz: a097276735f3a2f5226061f807c82cb97920aa3ad27e660dc9d7328489dab28692dd0a772a8529a078ffdcc175a145a059b1441206e9f8d9378751ed9b9e3b1c
6
+ metadata.gz: 2fb32730607a2b122391447f7bd371f9b1d318d4c6be50ae1bf2d3bcd46c80561ac1ebe792824909cfa8f7fbd4edda17404e41b2510b9ab25c750fcb34f836ef
7
+ data.tar.gz: 6f6fa5d67867c3f0abb8b54e65d59aedbfa607abde5ca1336505001d35c916c8a928a4228393c2d5d22e2a341ed09afb2c199057389a966ce1f07326b7444e13
data/bin/judges CHANGED
@@ -29,7 +29,7 @@ require 'factbase'
29
29
  Encoding.default_external = Encoding::UTF_8
30
30
  Encoding.default_internal = Encoding::UTF_8
31
31
 
32
- ver = '0.0.20'
32
+ ver = '0.0.22'
33
33
 
34
34
  include GLI::App
35
35
 
@@ -60,6 +60,8 @@ command :update do |c|
60
60
  c.flag([:o, :option], multiple: true, arg_name: '<key=value>')
61
61
  c.desc 'Maximum number of update cycles to run'
62
62
  c.flag([:'max-cycles'], default_value: 8, type: Integer)
63
+ c.desc 'Stay quiet even if some judges fail'
64
+ c.switch([:q, :quiet], default_value: false)
63
65
  c.action do |global, options, args|
64
66
  require_relative '../lib/judges/commands/update'
65
67
  Judges::Update.new(loog).run(options, args)
@@ -88,19 +90,28 @@ desc 'Print the factbase into a human-readable format (YAML, JSON, etc.)'
88
90
  command :print do |c|
89
91
  c.desc 'Output format (xml, json, or yaml)'
90
92
  c.flag([:format], default_value: 'yaml')
91
- c.switch([:auto])
93
+ c.desc 'Generate output name of the file automatically'
94
+ c.switch([:auto], default_value: false)
92
95
  c.action do |global, options, args|
93
96
  require_relative '../lib/judges/commands/print'
94
97
  Judges::Print.new(loog).run(options, args)
95
98
  end
96
99
  end
97
100
 
101
+ desc 'Inspect the factbase and print all its possible meta-data'
102
+ command :inspect do |c|
103
+ c.action do |global, options, args|
104
+ require_relative '../lib/judges/commands/inspect'
105
+ Judges::Inspect.new(loog).run(options, args)
106
+ end
107
+ end
108
+
98
109
  desc 'Run automated tests for all judges'
99
110
  command :test do |c|
100
111
  c.desc 'Name of the test pack to run'
101
112
  c.flag([:pack], multiple: true)
102
- c.desc 'Fail if no judges tested?'
103
- c.flag([:quiet], default_value: false)
113
+ c.desc 'Stay quiet even if some tests fail or simply no tests executed?'
114
+ c.switch([:quiet], default_value: false)
104
115
  c.action do |global, options, args|
105
116
  require_relative '../lib/judges/commands/test'
106
117
  Judges::Test.new(loog).run(options, args)
data/features/cli.feature CHANGED
@@ -17,22 +17,22 @@ Feature: Simple Run
17
17
  n = $fb.insert
18
18
  n.kind = 'yes!'
19
19
  """
20
- Then I run bin/judges with "--verbose update -o foo=1 -o bar=2 --max-cycles 3 . simple.fb"
20
+ Then I run bin/judges with "--verbose update --quiet -o foo=1 -o bar=2 --max-cycles 3 . simple.fb"
21
21
  Then Stdout contains "foo → "
22
22
  Then Stdout contains "bar → "
23
- Then Stdout contains "1 judges processed"
23
+ Then Stdout contains "1 judge(s) processed"
24
24
  Then Stdout contains "Update finished in 3 cycles"
25
25
  And Exit code is zero
26
26
 
27
27
  Scenario: Simple test of a few judges
28
28
  Given I run bin/judges with "test ./fixtures"
29
29
  Then Stdout contains "👉 Testing"
30
- Then Stdout contains "judges tested successfully"
30
+ Then Stdout contains "judge(s) tested successfully"
31
31
  And Exit code is zero
32
32
 
33
33
  Scenario: Simple test of just one pack
34
34
  Given I run bin/judges with "test --pack reward_for_good_bug ./fixtures"
35
- Then Stdout contains "judges tested successfully"
35
+ Then Stdout contains "judge(s) tested successfully"
36
36
  And Exit code is zero
37
37
 
38
38
  Scenario: Simple test of no packs
@@ -64,3 +64,16 @@ Feature: Simple Run
64
64
  Then Stdout contains "printed"
65
65
  And Exit code is zero
66
66
 
67
+ Scenario: Simple inspect of a small factbase
68
+ Given I make a temp directory
69
+ Then I have a "simple/simple_judge.rb" file with content:
70
+ """
71
+ return if $fb.size > 2
72
+ n = $fb.insert
73
+ n.kind = 'yes!'
74
+ """
75
+ Then I run bin/judges with "update . simple.fb"
76
+ Then I run bin/judges with "inspect simple.fb"
77
+ Then Stdout contains "Facts: 3"
78
+ And Exit code is zero
79
+
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.0.20'
29
+ s.version = '0.0.22'
30
30
  s.license = 'MIT'
31
31
  s.summary = 'Command-Line Tool for a Factbase'
32
32
  s.description = '
@@ -42,7 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.rdoc_options = ['--charset=UTF-8']
43
43
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
44
44
  s.add_runtime_dependency 'backtrace', '~> 0.3'
45
- s.add_runtime_dependency 'factbase', '~>0.0.17'
45
+ s.add_runtime_dependency 'factbase', '~>0.0.21'
46
46
  s.add_runtime_dependency 'gli', '~>2.21'
47
47
  s.add_runtime_dependency 'loog', '~>0.2'
48
48
  s.add_runtime_dependency 'nokogiri', '~> 1.10'
@@ -0,0 +1,40 @@
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_relative '../../judges'
24
+ require_relative '../../judges/impex'
25
+
26
+ # Inspect.
27
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
29
+ # License:: MIT
30
+ class Judges::Inspect
31
+ def initialize(loog)
32
+ @loog = loog
33
+ end
34
+
35
+ def run(_opts, args)
36
+ raise 'At lease one argument required' if args.empty?
37
+ fb = Judges::Impex.new(@loog, args[0]).import
38
+ @loog.info("Facts: #{fb.size}")
39
+ end
40
+ end
@@ -23,8 +23,7 @@
23
23
  require 'fileutils'
24
24
  require 'factbase'
25
25
  require_relative '../../judges'
26
- require_relative '../../judges/to_rel'
27
- require_relative '../../judges/packs'
26
+ require_relative '../../judges/impex'
28
27
 
29
28
  # Update.
30
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -37,17 +36,14 @@ class Judges::Print
37
36
 
38
37
  def run(opts, args)
39
38
  raise 'At lease one argument required' if args.empty?
40
- f = args[0]
41
- raise "The file is absent: #{f.to_rel}" unless File.exist?(f)
42
39
  o = args[1]
40
+ f = args[0]
41
+ fb = Judges::Impex.new(@loog, f).import
43
42
  if o.nil?
44
43
  raise 'Either provide output file name or use --auto' unless opts[:auto]
45
44
  o = File.join(File.dirname(f), File.basename(f).gsub(/\.[^.]*$/, ''))
46
45
  o = "#{o}.#{opts[:format]}"
47
46
  end
48
- fb = Factbase.new
49
- fb.import(File.binread(f))
50
- @loog.info("Factbase imported from #{f.to_rel} (#{File.size(f)} bytes)")
51
47
  FileUtils.mkdir_p(File.dirname(o))
52
48
  output =
53
49
  case opts[:format].downcase
@@ -59,12 +59,14 @@ class Judges::Test
59
59
  end
60
60
  done += 1
61
61
  end
62
- raise 'No judges tested :(' if done.zero? && !opts['quiet']
63
- if errors.empty?
64
- @loog.info("\nAll #{done} judges tested successfully")
62
+ if done.zero?
63
+ raise 'No judges tested :(' unless opts['quiet']
64
+ @loog.warn("\n👍 No judges tested")
65
+ elsif errors.empty?
66
+ @loog.info("\n👍 All #{done} judge(s) tested successfully")
65
67
  else
66
- @loog.info("\n#{done} judges tested, #{errors.size} of them failed")
67
- raise "#{errors.size} tests failed" unless errors.empty?
68
+ @loog.info("\n#{done} judge(s) tested, #{errors.size} of them failed")
69
+ raise "#{errors.size} tests failed" unless opts['quiet']
68
70
  end
69
71
  end
70
72
 
@@ -67,7 +67,7 @@ class Judges::Update
67
67
  errors = []
68
68
  diff = 0
69
69
  done = packs.each_with_index do |p, i|
70
- @loog.info("👍 Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
70
+ @loog.info("👉 Running #{p.name} (##{i}) at #{p.dir.to_rel}...")
71
71
  before = fb.size
72
72
  begin
73
73
  p.run(fb, options)
@@ -76,11 +76,15 @@ class Judges::Update
76
76
  errors << p.script
77
77
  end
78
78
  after = fb.size
79
- @loog.info("Pack #{p.dir.to_rel} added #{after - before} facts") if after > before
79
+ @loog.info("👍 Pack #{p.dir.to_rel} added #{after - before} facts") if after > before
80
80
  diff += after - before
81
81
  end
82
- @loog.info("#{done} judges processed (#{errors.size} errors)")
83
- raise "Failed to update correctly (#{errors.size} errors)" unless errors.empty?
82
+ if errors.empty?
83
+ @loog.info("👍 #{done} judge(s) processed")
84
+ else
85
+ @loog.info("❌ #{done} judge(s) processed with #{errors.size} errors")
86
+ raise "Failed to update correctly (#{errors.size} errors)" unless opts['quiet']
87
+ end
84
88
  impex.export(fb)
85
89
  diff
86
90
  end
@@ -21,14 +21,24 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'judges'
24
+ require 'time'
24
25
 
25
26
  # Injects a fact if it's absent in the factbase.
26
27
  def if_absent(fb)
27
28
  attrs = {}
28
29
  f = Judges::Accumulator.new(attrs)
29
30
  yield f
30
- q = attrs.map { |k, v| "(eq #{k} '#{v}')" }.join(' ')
31
- return unless fb.query("(and #{q})").each.to_a.empty?
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.iso8601
37
+ end
38
+ "(eq #{k} #{vv})"
39
+ end.join(' ')
40
+ q = "(and #{q})"
41
+ return unless fb.query(q).each.to_a.empty?
32
42
  n = fb.insert
33
43
  attrs.each { |k, v| n.send("#{k}=", v) }
34
44
  n
@@ -0,0 +1,46 @@
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 'loog'
25
+ require 'factbase'
26
+ require_relative '../../lib/judges'
27
+ require_relative '../../lib/judges/commands/inspect'
28
+
29
+ # Test.
30
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
32
+ # License:: MIT
33
+ class TestInspect < Minitest::Test
34
+ def test_simple_inspect
35
+ Dir.mktmpdir do |d|
36
+ f = File.join(d, 'base.fb')
37
+ fb = Factbase.new
38
+ fb.insert
39
+ fb.insert
40
+ File.binwrite(f, fb.export)
41
+ loog = Loog::Buffer.new
42
+ Judges::Inspect.new(loog).run({}, [f])
43
+ assert(loog.to_s.include?('Facts: 2'))
44
+ end
45
+ end
46
+ end
@@ -23,6 +23,8 @@
23
23
  require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require 'factbase'
26
+ require 'factbase/looged'
27
+ require 'loog'
26
28
  require_relative '../../lib/judges'
27
29
  require_relative '../../lib/judges/fb/if_absent'
28
30
 
@@ -40,6 +42,16 @@ class TestIfAbsent < Minitest::Test
40
42
  assert(n.nil?)
41
43
  end
42
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
+
43
55
  def test_injects
44
56
  fb = Factbase.new
45
57
  n = if_absent(fb) do |f|
@@ -47,4 +59,38 @@ class TestIfAbsent < Minitest::Test
47
59
  end
48
60
  assert_equal(42, n.foo)
49
61
  end
62
+
63
+ def test_complex_ignores
64
+ fb = Factbase.new
65
+ f1 = fb.insert
66
+ f1.foo = 'hello, "dude"!'
67
+ f1.abc = 42
68
+ t = Time.now
69
+ f1.z = t
70
+ f1.bar = 3.14
71
+ n = if_absent(fb) do |f|
72
+ f.foo = 'hello, "dude"!'
73
+ f.abc = 42
74
+ f.z = t
75
+ f.bar = 3.14
76
+ end
77
+ assert(n.nil?)
78
+ end
79
+
80
+ def test_complex_injects
81
+ fb = Factbase.new
82
+ f1 = fb.insert
83
+ f1.foo = 'hello, "dude"!'
84
+ f1.abc = 42
85
+ t = Time.now
86
+ f1.z = t
87
+ f1.bar = 3.14
88
+ n = if_absent(fb) do |f|
89
+ f.foo = 'hello, "dude"!'
90
+ f.abc = 42
91
+ f.z = t + 1
92
+ f.bar = 3.15
93
+ end
94
+ assert(!n.nil?)
95
+ end
50
96
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: judges
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.17
33
+ version: 0.0.21
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.17
40
+ version: 0.0.21
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: gli
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -121,6 +121,7 @@ files:
121
121
  - fixtures/reward_for_good_bug/simple-reward.yml
122
122
  - judges.gemspec
123
123
  - lib/judges.rb
124
+ - lib/judges/commands/inspect.rb
124
125
  - lib/judges/commands/join.rb
125
126
  - lib/judges/commands/print.rb
126
127
  - lib/judges/commands/test.rb
@@ -134,6 +135,7 @@ files:
134
135
  - lib/judges/packs.rb
135
136
  - lib/judges/to_rel.rb
136
137
  - renovate.json
138
+ - test/commands/test_inspect.rb
137
139
  - test/commands/test_join.rb
138
140
  - test/commands/test_print.rb
139
141
  - test/commands/test_test.rb