judges 0.53.0 → 0.53.2

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: 28476c2fdf2ce4ade1719df441e59d5b1b0cd8f2504419bb298aa11c05c7bbc1
4
- data.tar.gz: 6a02a3d691eb27817517a49e60e089a72c40c2e41a844c992c50e0368ea04e18
3
+ metadata.gz: aa86305c49cd5701b671c3e8a6705e07971e7000ea5c327ad6db9e0aa688f4c8
4
+ data.tar.gz: 9f9445c8c832b285b75d6b816127bb504e6bb3e548616c6cc999dda56dbe15c4
5
5
  SHA512:
6
- metadata.gz: 35b6719aac90034754e98a74a2a16da99995b06f6bf17e7d20a1c604cbb5efdf7af388b41ee60cf55c9b022076eaa8a862c93ed2db70168d05c3e6d1b3025502
7
- data.tar.gz: c92556ae80920c8079187acf6bae340a42f9636b96d92f998229e62e931defa5b0dd6e5b3dc3ea2bc25fadff1417e234e97c0ed1f6b07a05bb66c83dd612855f
6
+ metadata.gz: b07a315a2bbd216ce359b6f81b1a04993929dc58feaa315413254ef0d72335a6fca76ef1716e597b39e81c8d5cc9f4a03f2d9de365b0e614f9420425afa9c81b
7
+ data.tar.gz: 9732e62b8e45b852b6eaa673a5924d61f7d6f67e0fae1f4bd76f0ecc996337236c3b52e2212a1b7efe2a31a701aae2f874f1be1bf15f814131dea9f90f4c3761
@@ -14,7 +14,7 @@ jobs:
14
14
  rake:
15
15
  strategy:
16
16
  matrix:
17
- os: [ubuntu-24.04, macos-15]
17
+ os: [ubuntu-24.04, macos-15, windows-2022]
18
18
  ruby: [3.3]
19
19
  runs-on: ${{ matrix.os }}
20
20
  steps:
@@ -16,4 +16,4 @@ jobs:
16
16
  runs-on: ubuntu-24.04
17
17
  steps:
18
18
  - uses: actions/checkout@v5
19
- - uses: crate-ci/typos@v1.35.4
19
+ - uses: crate-ci/typos@v1.35.5
data/Gemfile CHANGED
@@ -12,7 +12,6 @@ gem 'diff-lcs', '1.6.2', require: false # GPL
12
12
  gem 'minitest', '~>5.25', require: false
13
13
  gem 'minitest-reporters', '~>1.7', require: false
14
14
  gem 'minitest-retry', '~>0.2', require: false
15
- gem 'net-ping', '~>2.0', require: false
16
15
  gem 'online', '~>0.0', require: false
17
16
  gem 'os', '~>1.1', require: false
18
17
  gem 'qbash', '~>0.4', require: false
data/Gemfile.lock CHANGED
@@ -46,7 +46,7 @@ GEM
46
46
  crack (1.0.0)
47
47
  bigdecimal
48
48
  rexml
49
- cucumber (10.0.0)
49
+ cucumber (10.1.0)
50
50
  base64 (~> 0.2)
51
51
  builder (~> 3.2)
52
52
  cucumber-ci-environment (> 9, < 11)
@@ -59,7 +59,7 @@ GEM
59
59
  multi_test (~> 1.1)
60
60
  sys-uname (~> 1.3)
61
61
  cucumber-ci-environment (10.0.1)
62
- cucumber-core (15.2.0)
62
+ cucumber-core (15.2.1)
63
63
  cucumber-gherkin (> 27, < 33)
64
64
  cucumber-messages (> 26, < 30)
65
65
  cucumber-tag-expressions (> 5, < 7)
@@ -78,18 +78,18 @@ GEM
78
78
  loog (~> 0.6)
79
79
  tago (~> 0.1)
80
80
  ellipsized (0.3.0)
81
- ethon (0.16.0)
81
+ ethon (0.17.0)
82
82
  ffi (>= 1.15.0)
83
- factbase (0.15.0)
83
+ factbase (0.15.6)
84
84
  backtrace (~> 0.4)
85
- decoor (~> 0.0)
85
+ decoor (~> 0.1)
86
86
  ellipsized (~> 0.3)
87
87
  json (~> 2.7)
88
88
  logger (~> 1.0)
89
89
  loog (~> 0.6)
90
90
  nokogiri (~> 1.10)
91
- others (~> 0.0)
92
- tago (~> 0.0)
91
+ others (~> 0.1)
92
+ tago (~> 0.1)
93
93
  yaml (~> 0.3)
94
94
  faraday (2.13.4)
95
95
  faraday-net_http (>= 2.0, < 3.5)
@@ -136,7 +136,6 @@ GEM
136
136
  multipart-post (2.4.1)
137
137
  net-http (0.6.0)
138
138
  uri
139
- net-ping (2.0.8)
140
139
  nokogiri (1.18.9-aarch64-linux-gnu)
141
140
  racc (~> 1.4)
142
141
  nokogiri (1.18.9-aarch64-linux-musl)
@@ -179,7 +178,7 @@ GEM
179
178
  regexp_parser (2.11.2)
180
179
  retries (0.0.5)
181
180
  rexml (3.4.1)
182
- rubocop (1.79.2)
181
+ rubocop (1.80.0)
183
182
  json (~> 2.3)
184
183
  language_server-protocol (~> 3.17.0.2)
185
184
  lint_roller (~> 1.1.0)
@@ -255,7 +254,6 @@ DEPENDENCIES
255
254
  minitest (~> 5.25)
256
255
  minitest-reporters (~> 1.7)
257
256
  minitest-retry (~> 0.2)
258
- net-ping (~> 2.0)
259
257
  online (~> 0.0)
260
258
  os (~> 1.1)
261
259
  qbash (~> 0.4)
@@ -16,9 +16,9 @@ Feature: Test
16
16
  And Exit code is zero
17
17
 
18
18
  Scenario: Factbase version can be set
19
- When I run bin/judges with "--factbase 0.15.0 --verbose test --judge guess ./fixtures"
19
+ When I run bin/judges with "--factbase 0.15.6 --verbose test --judge guess ./fixtures"
20
20
  Then Exit code is zero
21
- And Stdout contains "Factbase version to be used: '0.15.0'"
21
+ And Stdout contains "Factbase version to be used: '0.15.6'"
22
22
 
23
23
  Scenario: Simple test of no judges
24
24
  Given I run bin/judges with "test --judge absent_for_sure ./fixtures"
@@ -55,16 +55,15 @@ Feature: Update
55
55
  """
56
56
  n = $fb.insert
57
57
  n.type = 'first'
58
- sleep 1
58
+ sleep 1.9
59
59
  """
60
60
  Then I have a "second/second.rb" file with content:
61
61
  """
62
62
  n = $fb.insert
63
63
  n.type = 'second'
64
64
  """
65
- Then I run bin/judges with "--verbose update --quiet --lifetime 1 --max-cycles 5 . simple.fb"
66
- Then Stdout contains "The 'second' judge skipped, no time left"
67
- Then Stdout contains "Update completed in 1 cycle(s), did 1i/0d/1a"
65
+ Then I run bin/judges with "--verbose update --quiet --lifetime 2 --timeout 1 --max-cycles 5 . simple.fb"
66
+ Then Stdout contains "Update completed in 2 cycle(s), did 1i/0d/1a"
68
67
  And Exit code is zero
69
68
 
70
69
  Scenario: Use options from a file
data/judges.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
10
10
  s.required_ruby_version = '>=3.2'
11
11
  s.name = 'judges'
12
- s.version = '0.53.0'
12
+ s.version = '0.53.2'
13
13
  s.license = 'MIT'
14
14
  s.summary = 'Command-Line Tool for a Factbase'
15
15
  s.description =
@@ -42,11 +42,13 @@ class Judges::Update
42
42
  raise 'Exactly two arguments required' unless args.size == 2
43
43
  dir = args[0]
44
44
  raise "The directory is absent: #{dir.to_rel}" unless File.exist?(dir)
45
- start = Time.now
46
45
  impex = Judges::Impex.new(@loog, args[1])
47
46
  fb = impex.import(strict: false)
48
47
  fb = Factbase::Logged.new(fb, @loog) if opts['log']
49
- options = Judges::Options.new(timeout: opts['timeout'], lifetime: opts['lifetime'])
48
+ options = Judges::Options.new(timeout: opts['timeout']&.to_i, lifetime: opts['lifetime']&.to_i)
49
+ if options.lifetime && options.timeout && options.lifetime < options.timeout * 1.1
50
+ raise "The --timeout=#{options.timeout} must be at least 10 percent smaller than --lifetime=#{options.lifetime}"
51
+ end
50
52
  options += Judges::Options.new(opts['option'])
51
53
  if opts['options-file']
52
54
  options += Judges::Options.new(
@@ -62,8 +64,19 @@ class Judges::Update
62
64
  else
63
65
  @loog.debug("The following options provided:\n\t#{options.to_s.gsub("\n", "\n\t")}")
64
66
  end
65
- judges = Judges::Judges.new(dir, opts['lib'], @loog, start:, shuffle: opts['shuffle'], boost: opts['boost'],
66
- demote: opts['demote'])
67
+ judges = Judges::Judges.new(
68
+ dir, opts['lib'], @loog,
69
+ start: @start, shuffle: opts['shuffle'], boost: opts['boost'],
70
+ demote: opts['demote']
71
+ )
72
+ Timeout.timeout(opts['lifetime']) do
73
+ loop_them(impex, judges, fb, opts, options)
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def loop_them(impex, judges, fb, opts, options)
67
80
  c = 0
68
81
  churn = Factbase::Churn.new
69
82
  errors = []
@@ -80,14 +93,14 @@ class Judges::Update
80
93
  loop do
81
94
  c += 1
82
95
  if c > 1
83
- if opts['lifetime'] && Time.now - @start > opts['lifetime']
96
+ if opts['lifetime'] && Time.now - @start > opts['lifetime'] * 0.51
84
97
  @loog.info("Not starting cycle ##{c}, no time left")
85
98
  c -= 1
86
99
  break
87
100
  end
88
101
  @loog.info("\nStarting cycle ##{c}#{" (out of #{opts['max-cycles']})" if opts['max-cycles']}...")
89
102
  end
90
- delta = cycle(opts, judges, fb, options, start, errors)
103
+ delta = cycle(opts, judges, fb, options, errors)
91
104
  churn += delta
92
105
  impex.export(fb)
93
106
  if delta.zero?
@@ -107,26 +120,23 @@ class Judges::Update
107
120
  throw :"šŸ‘ Update completed in #{c} cycle(s), did #{churn}"
108
121
  end
109
122
  return unless %w[add append].include?(opts['summary'])
110
- summarize(fb, churn, errors, start, c)
123
+ summarize(fb, churn, errors, c)
111
124
  impex.export(fb)
112
125
  end
113
126
 
114
- private
115
-
116
127
  # Update the summary.
117
128
  # @param [Factbase] fb The factbase
118
129
  # @param [Churn] churn The churn
119
130
  # @param [Array<String>] errors List of errors
120
- # @param [Time] start When we started
121
131
  # @param [Integer] cycles How many cycles
122
- def summarize(fb, churn, errors, start, cycles)
132
+ def summarize(fb, churn, errors, cycles)
123
133
  before = fb.query('(eq what "judges-summary")').each.to_a
124
134
  if before.empty?
125
135
  s = fb.insert
126
136
  s.what = 'judges-summary'
127
137
  s.when = Time.now
128
138
  s.version = Judges::VERSION
129
- s.seconds = Time.now - start
139
+ s.seconds = Time.now - @start
130
140
  s.cycles = cycles
131
141
  s.inserted = churn.inserted.size
132
142
  s.deleted = churn.deleted.size
@@ -153,10 +163,9 @@ class Judges::Update
153
163
  # @param [Judges::Judges] judges The judges
154
164
  # @param [Factbase] fb The factbase
155
165
  # @param [Judges::Options] options The options
156
- # @param [Float] start When we started
157
166
  # @param [Array<String>] errors List of errors
158
167
  # @return [Factbase::Churn] How many modifications have been made
159
- def cycle(opts, judges, fb, options, start, errors)
168
+ def cycle(opts, judges, fb, options, errors)
160
169
  churn = Factbase::Churn.new
161
170
  global = {}
162
171
  used = 0
@@ -168,7 +177,7 @@ class Judges::Update
168
177
  next
169
178
  end
170
179
  next unless include?(opts, judge.name)
171
- @loog.info("\nšŸ‘‰ Running #{judge.name} (##{i}) at #{judge.dir.to_rel} (#{start.ago} already)...")
180
+ @loog.info("\nšŸ‘‰ Running #{judge.name} (##{i}) at #{judge.dir.to_rel} (#{@start.ago} already)...")
172
181
  used += 1
173
182
  elapsed(@loog, level: Logger::INFO) do
174
183
  c = one_judge(opts, fb, judge, global, options, errors)
@@ -86,9 +86,14 @@ class Judges::Options
86
86
  # # token → "supe****oken"
87
87
  def to_s
88
88
  to_h.map do |k, v|
89
- v = v.to_s
90
- v = "#{v[0..3]}#{'*' * (v.length - 8)}#{v[-4..]}" if v.length > 8
91
- "#{k} → \"#{v}\""
89
+ v = "#{v[0..3]}#{'*' * (v.length - 8)}#{v[-4..]}" if v.is_a?(String) && v.length > 8
90
+ v =
91
+ if v.is_a?(String)
92
+ "\"#{v}\""
93
+ else
94
+ "#{v} (#{v.class.name})"
95
+ end
96
+ "#{k} → #{v}"
92
97
  end.sort.join("\n")
93
98
  end
94
99
 
@@ -122,6 +127,7 @@ class Judges::Options
122
127
  end
123
128
  pp
124
129
  .reject { |k, _| k.nil? }
130
+ .compact
125
131
  .reject { |k, _| k.is_a?(String) && k.empty? }
126
132
  .to_h
127
133
  .transform_values { |v| v.nil? ? 'true' : v }
data/lib/judges.rb CHANGED
@@ -8,5 +8,5 @@
8
8
  # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
9
9
  # License:: MIT
10
10
  module Judges
11
- VERSION = '0.53.0' unless const_defined?(:VERSION)
11
+ VERSION = '0.53.2' unless const_defined?(:VERSION)
12
12
  end
@@ -51,6 +51,18 @@ class TestUpdate < Minitest::Test
51
51
  end
52
52
  end
53
53
 
54
+ def test_accepts_changes_from_slow_judge
55
+ Dir.mktmpdir do |d|
56
+ save_it(File.join(d, 'foo/foo.rb'), '$fb.insert.foo = 1; sleep 10')
57
+ file = File.join(d, 'base.fb')
58
+ Judges::Update.new(Loog::NULL).run({ 'timeout' => 0.1, 'quiet' => true }, [d, file])
59
+ fb = Factbase.new
60
+ fb.import(File.binread(file))
61
+ xml = Nokogiri::XML.parse(Factbase::ToXML.new(fb).xml)
62
+ refute_empty(xml.xpath('/fb/f[foo]'), xml)
63
+ end
64
+ end
65
+
54
66
  def test_extend_existing_factbase
55
67
  Dir.mktmpdir do |d|
56
68
  file = File.join(d, 'base.fb')
@@ -89,6 +101,18 @@ class TestUpdate < Minitest::Test
89
101
  end
90
102
  end
91
103
 
104
+ def test_terminates_on_lifetime
105
+ Dir.mktmpdir do |d|
106
+ save_it(File.join(d, 'foo/foo.rb'), 'sleep 999')
107
+ file = File.join(d, 'base.fb')
108
+ log = Loog::Buffer.new
109
+ assert_raises(StandardError) do
110
+ Judges::Update.new(Loog::Tee.new(log, Loog::NULL)).run({ 'lifetime' => 0.1 }, [d, file])
111
+ end
112
+ assert_includes(log.to_s, 'execution expired')
113
+ end
114
+ end
115
+
92
116
  def test_passes_timeout_and_lifetime_through
93
117
  %w[lifetime timeout].each do |o|
94
118
  Dir.mktmpdir do |d|
data/test/test_options.rb CHANGED
@@ -60,10 +60,15 @@ class TestOptions < Minitest::Test
60
60
  assert_nil(opts.xxx)
61
61
  end
62
62
 
63
+ def test_with_nil_values
64
+ opts = Judges::Options.new('foo' => nil)
65
+ assert_nil(opts.foo)
66
+ end
67
+
63
68
  def test_converts_to_string
64
69
  opts = Judges::Options.new('foo' => 44, 'bar' => 'long-string-maybe-secret')
65
70
  s = opts.to_s
66
- assert_includes(s, 'FOO → "44"', s)
71
+ assert_includes(s, 'FOO → 44 (Integer)', s)
67
72
  assert_includes(s, '"long****************cret"', s)
68
73
  end
69
74
 
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.53.0
4
+ version: 0.53.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko