judges 0.12.0 → 0.13.1

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: fdaaebbfb61ca792443a79d06439a3946f92bf9fdeb46fdf89ab0f702f0a2176
4
- data.tar.gz: 617dce64bda23eb2d4987ef45b60987766248d48ee5770b6c4f35964d4f73cdf
3
+ metadata.gz: 0e42894e95397d8b62afd1deaf3407d31321475e378f4ebdfd88216571ff742d
4
+ data.tar.gz: d59aaa5f47aa2f7373b78e36869bc09aacd1c52f881c910c45d292407c3da203
5
5
  SHA512:
6
- metadata.gz: 8e0cfe9f3488ed3e67f687400a2d4ab7bd6ccae47985d0eec8681bca3aac61c9bdbef4025ca974adff07e7aadb9a6ab594bc1765f2fccaabc7fa23d0c250201e
7
- data.tar.gz: 8148daa02d6d83ddcc6dcd6093108cbe051cd205876a924c65590a02b52e861b9d9517cef775e4e86e7ff007cc040379ce11d86c4e1b758a7a4eff6aa82ec327
6
+ metadata.gz: 1be5c4aad65f212b8bc700616851356ccf331be5b51a1ccc1e2d9d71e2225c8f648d0604e4ae5b1957d4b0623d43b8de6e78da2a8b1ed5ecdbbbe6db9eba3fc4
7
+ data.tar.gz: 8174ac41e04c618635c868b06164b79939cc2891066bda8063f806f9395b8985a650eab5770fd778fe86ad7f42d8f9496f46331a3cff175d570f39d0af2e00a2
data/Gemfile.lock CHANGED
@@ -3,7 +3,7 @@ PATH
3
3
  specs:
4
4
  judges (0.0.0)
5
5
  backtrace (~> 0.3)
6
- concurrent-ruby (= 1.2.3)
6
+ concurrent-ruby (~> 1.2)
7
7
  factbase (~> 0.0)
8
8
  gli (~> 2.21)
9
9
  iri (~> 0.8)
@@ -51,7 +51,7 @@ GEM
51
51
  base64 (0.2.0)
52
52
  bigdecimal (3.1.8)
53
53
  builder (3.3.0)
54
- concurrent-ruby (1.2.3)
54
+ concurrent-ruby (1.3.3)
55
55
  connection_pool (2.4.1)
56
56
  crack (1.0.0)
57
57
  bigdecimal
@@ -180,7 +180,7 @@ GEM
180
180
  reline (0.5.9)
181
181
  io-console (~> 0.5)
182
182
  retries (0.0.5)
183
- rexml (3.3.0)
183
+ rexml (3.3.1)
184
184
  strscan
185
185
  rspec-core (3.13.0)
186
186
  rspec-support (~> 3.13.0)
data/bin/judges CHANGED
@@ -65,6 +65,8 @@ class App
65
65
  c.flag([:'max-cycles'], default_value: 8, type: Integer)
66
66
  c.desc 'Stay quiet even if some judges fail'
67
67
  c.switch([:q, :quiet], default_value: false)
68
+ c.desc 'Place a summarization fact into the factbase'
69
+ c.switch([:summary], default_value: false)
68
70
  c.desc 'Use default logging facility'
69
71
  c.switch([:log], default_value: true)
70
72
  c.action do |global, options, args|
@@ -9,8 +9,8 @@ Feature: Update
9
9
  n.kind = 'yes!'
10
10
  """
11
11
  Then I run bin/judges with "--verbose update --quiet -o foo=1 -o bar=2 --max-cycles 3 . simple.fb"
12
- Then Stdout contains "foo → "
13
- Then Stdout contains "bar → "
12
+ Then Stdout contains "FOO → "
13
+ Then Stdout contains "BAR → "
14
14
  Then Stdout contains "1 judge(s) processed"
15
15
  Then Stdout contains "Update finished in 3 cycle(s), modified 3/0 fact(s)"
16
16
  And Exit code is zero
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.12.0'
29
+ s.version = '0.13.1'
30
30
  s.license = 'MIT'
31
31
  s.summary = 'Command-Line Tool for a Factbase'
32
32
  s.description =
@@ -43,7 +43,7 @@ Gem::Specification.new do |s|
43
43
  s.rdoc_options = ['--charset=UTF-8']
44
44
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
45
45
  s.add_runtime_dependency 'backtrace', '~>0.3'
46
- s.add_runtime_dependency 'concurrent-ruby', '1.2.3'
46
+ s.add_runtime_dependency 'concurrent-ruby', '~>1.2'
47
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'
data/lib/judges/churn.rb CHANGED
@@ -27,34 +27,40 @@ require_relative '../judges'
27
27
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
28
28
  # License:: MIT
29
29
  class Judges::Churn
30
- attr_reader :added, :removed
30
+ attr_reader :added, :removed, :errors
31
31
 
32
- def initialize(added, removed)
32
+ def initialize(added, removed, errors = [])
33
33
  @added = added
34
34
  @removed = removed
35
+ @errors = errors
35
36
  end
36
37
 
37
38
  def to_s
38
- "#{@added}/#{@removed}"
39
+ "#{@added}/#{@removed}#{@errors.empty? ? '' : "/#{@errors.size}"}"
39
40
  end
40
41
 
41
42
  def zero?
42
- @added.zero? && @removed.zero?
43
+ @added.zero? && @removed.zero? && @errors.empty?
44
+ end
45
+
46
+ def <<(error)
47
+ @errors << error
48
+ nil
43
49
  end
44
50
 
45
51
  def +(other)
46
52
  if other.is_a?(Judges::Churn)
47
- Judges::Churn.new(@added + other.added, @removed + other.removed)
53
+ Judges::Churn.new(@added + other.added, @removed + other.removed, @errors + other.errors)
48
54
  else
49
- Judges::Churn.new(@added + other, @removed)
55
+ Judges::Churn.new(@added + other, @removed, @errors)
50
56
  end
51
57
  end
52
58
 
53
59
  def -(other)
54
60
  if other.is_a?(Judges::Churn)
55
- Judges::Churn.new(@added - other.added, @removed - other.removed)
61
+ Judges::Churn.new(@added - other.added, @removed - other.removed, @errors + other.errors)
56
62
  else
57
- Judges::Churn.new(@added, @removed + other)
63
+ Judges::Churn.new(@added, @removed + other, @errors)
58
64
  end
59
65
  end
60
66
  end
@@ -47,7 +47,11 @@ class Judges::Update
47
47
  fb = impex.import(strict: false)
48
48
  fb = Factbase::Looged.new(fb, @loog) if opts['log']
49
49
  options = Judges::Options.new(opts['option'])
50
- @loog.debug("The following options provided:\n\t#{options.to_s.gsub("\n", "\n\t")}")
50
+ if options.empty?
51
+ @loog.debug('No options provided by the --option flag')
52
+ else
53
+ @loog.debug("The following options provided:\n\t#{options.to_s.gsub("\n", "\n\t")}")
54
+ end
51
55
  judges = Judges::Judges.new(dir, opts['lib'], @loog)
52
56
  c = 0
53
57
  churn = Judges::Churn.new(0, 0)
@@ -72,6 +76,17 @@ class Judges::Update
72
76
  end
73
77
  throw :"Update finished in #{c} cycle(s), modified #{churn} fact(s)"
74
78
  end
79
+ return if churn.zero? || !opts['summary']
80
+ fb.query('(eq what "judges-summary")').delete!
81
+ f = fb.insert
82
+ f.what = 'judges-summary'
83
+ f.when = Time.now
84
+ f.version = Judges::VERSION
85
+ f.cycles = c
86
+ f.added = churn.added.size
87
+ f.removed = churn.removed.size
88
+ churn.errors.each { |e| f.error = e }
89
+ impex.export(fb)
75
90
  end
76
91
 
77
92
  private
@@ -79,7 +94,6 @@ class Judges::Update
79
94
  # Run all judges in a full cycle, one by one.
80
95
  # @return [Churn] How many modifications have been made
81
96
  def cycle(opts, judges, fb, options)
82
- errors = []
83
97
  churn = Judges::Churn.new(0, 0)
84
98
  global = {}
85
99
  elapsed(@loog) do
@@ -92,13 +106,13 @@ class Judges::Update
92
106
  end
93
107
  rescue StandardError, SyntaxError => e
94
108
  @loog.warn(Backtrace.new(e))
95
- errors << p.script
109
+ churn << e.message
96
110
  end
97
- throw :"👍 #{done} judge(s) processed" if errors.empty?
98
- throw :"❌ #{done} judge(s) processed with #{errors.size} errors"
111
+ throw :"👍 #{done} judge(s) processed" if churn.errors.empty?
112
+ throw :"❌ #{done} judge(s) processed with #{churn.errors.size} errors"
99
113
  end
100
- unless errors.empty?
101
- raise "Failed to update correctly (#{errors.size} errors)" unless opts['quiet']
114
+ unless churn.errors.empty?
115
+ raise "Failed to update correctly (#{churn.errors.size} errors)" unless opts['quiet']
102
116
  @loog.info('Not failing because of the --quiet flag provided')
103
117
  end
104
118
  churn
@@ -34,6 +34,11 @@ class Judges::Options
34
34
  @pairs = pairs
35
35
  end
36
36
 
37
+ def empty?
38
+ touch # this will trigger method_missing() method, which will create @hash
39
+ @hash.empty?
40
+ end
41
+
37
42
  def +(other)
38
43
  touch # this will trigger method_missing() method, which will create @hash
39
44
  h = @hash.dup
@@ -62,15 +67,16 @@ class Judges::Options
62
67
  pp = pp.split(',') if pp.is_a?(String)
63
68
  pp.compact!
64
69
  pp.reject!(&:empty?)
65
- pp.to_h do |pair|
70
+ pp.map! do |pair|
66
71
  p = pair.split('=', 2)
67
- k = p[0].strip
72
+ k = p[0].strip.upcase
68
73
  v = p[1]
69
74
  v = v.nil? ? 'true' : v.strip
70
75
  [k.to_sym, v.match?(/^[0-9]+$/) ? v.to_i : v]
71
76
  end
77
+ pp.reject { |p| p[0].empty? }.to_h
72
78
  end
73
- k = args[0].downcase
79
+ k = args[0].upcase
74
80
  @hash[k]
75
81
  end
76
82
  end
data/lib/judges.rb CHANGED
@@ -25,5 +25,5 @@
25
25
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Judges
28
- VERSION = '0.12.0'
28
+ VERSION = '0.13.1'
29
29
  end
@@ -64,7 +64,7 @@ class TestUpdate < Minitest::Test
64
64
  Dir.mktmpdir do |d|
65
65
  File.write(File.join(d, 'foo.rb'), 'this$is$a$broken$Ruby$script')
66
66
  file = File.join(d, 'base.fb')
67
- Judges::Update.new(Loog::NULL).run({ 'quiet' => true }, [d, file])
67
+ Judges::Update.new(Loog::NULL).run({ 'quiet' => true, 'max-cycles' => 2 }, [d, file])
68
68
  end
69
69
  end
70
70
 
@@ -77,4 +77,23 @@ class TestUpdate < Minitest::Test
77
77
  end
78
78
  end
79
79
  end
80
+
81
+ def test_update_with_error_and_summary
82
+ Dir.mktmpdir do |d|
83
+ File.write(File.join(d, 'foo.rb'), 'this$is$a$broken$Ruby$script')
84
+ file = File.join(d, 'base.fb')
85
+ 2.times do
86
+ Judges::Update.new(Loog::NULL).run(
87
+ { 'quiet' => true, 'summary' => true, 'max-cycles' => 2 },
88
+ [d, file]
89
+ )
90
+ end
91
+ fb = Factbase.new
92
+ fb.import(File.binread(file))
93
+ sums = fb.query('(eq what "judges-summary")').each.to_a
94
+ assert_equal(1, sums.size)
95
+ f = sums.first
96
+ assert(f.error.include?('unexpected global variable'), f.error)
97
+ end
98
+ end
80
99
  end
data/test/test_churn.rb CHANGED
@@ -35,4 +35,12 @@ class TestChurn < Minitest::Test
35
35
  assert_equal('42/0', (churn + 42).to_s)
36
36
  assert_equal('0/17', (churn - 17).to_s)
37
37
  end
38
+
39
+ def test_with_errors
40
+ churn = Judges::Churn.new(0, 0)
41
+ churn << 'oops'
42
+ assert_equal('0/0/1', churn.to_s)
43
+ assert_equal('42/0/1', (churn + 42).to_s)
44
+ assert_equal('0/0/1', (Judges::Churn.new(0, 0) + churn).to_s)
45
+ end
38
46
  end
data/test/test_options.rb CHANGED
@@ -41,19 +41,27 @@ class TestOptions < Minitest::Test
41
41
  assert_equal(42, opts.max)
42
42
  end
43
43
 
44
+ def test_case_insensitive
45
+ opts = Judges::Options.new(['aBcDeF=1', 'aBCDEf=2'])
46
+ assert_equal(2, opts.abcdef)
47
+ end
48
+
44
49
  def test_with_nil
45
50
  opts = Judges::Options.new(nil)
46
51
  assert(opts.foo.nil?)
52
+ assert(opts.empty?)
47
53
  end
48
54
 
49
55
  def test_with_empty_string
50
56
  opts = Judges::Options.new(' ')
51
57
  assert(opts.foo.nil?)
58
+ assert(opts.empty?)
52
59
  end
53
60
 
54
61
  def test_with_empty_strings
55
62
  opts = Judges::Options.new(['', nil])
56
63
  assert(opts.foo.nil?)
64
+ assert(opts.empty?)
57
65
  end
58
66
 
59
67
  def test_with_string
@@ -72,7 +80,7 @@ class TestOptions < Minitest::Test
72
80
  def test_converts_to_string
73
81
  opts = Judges::Options.new('foo' => 44, 'bar' => 'long-string-maybe-secret')
74
82
  s = opts.to_s
75
- assert(s.include?('foo → "44"'))
83
+ assert(s.include?('FOO → "44"'))
76
84
  assert(s.include?('"long********************"'))
77
85
  end
78
86
 
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.12.0
4
+ version: 0.13.1
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-06-25 00:00:00.000000000 Z
11
+ date: 2024-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: concurrent-ruby
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.2.3
33
+ version: '1.2'
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: 1.2.3
40
+ version: '1.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: factbase
43
43
  requirement: !ruby/object:Gem::Requirement