mutant 0.11.0 → 0.11.4

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: dfa3f4386dd2bb68e31b67124aac333cf71d13bb2fec0cf46fea56360475f3f4
4
- data.tar.gz: c1c3284ed18f7e2b268c8536a9103d11b7eb8abb0f3fc73a1890ffc8d461e9e5
3
+ metadata.gz: 70a7ce19bef24f9e278efb7beee74d9ae0eed625f0e4e4a712d9330ac1907339
4
+ data.tar.gz: 814ca08aed382018685010ca642903ea1e4da3226ae4c7c0fb0fae920818be49
5
5
  SHA512:
6
- metadata.gz: a20b1be07d23f2a0939bab498c500cf1707f75c647af84409d5ec42437bdd26aa6d4f89c9f70e558408e1280812da0cbc7cf7758af1c80c499289e3554b0b92d
7
- data.tar.gz: 276e169499aa4b48bc2488178de01b3d3ce1cb4647796bef023491c5d21faaed2d88e1ee61ae012c09d5c86f68ac68cda4a705174cc3cb88dab69e7cc4ea1578
6
+ metadata.gz: 3461d1141fdb8ec16d4262aaf9542ec9db4fc00bc31adf97024803ebd71133de3738c55dd08000f080ae59c8a29a6877eb9758001ea42ff54637a7b09d91e1ac
7
+ data.tar.gz: e03447c1d1d192fa98641fbee718ef3e6440b69a43d88023741635e348df94fe336cd92e716a1d8a9e638fba230530377a98ea413890f97b6654c0e45e88960e
data/LICENSE CHANGED
@@ -5,8 +5,8 @@ END-USER LICENSE AGREEMENT
5
5
  IMPORTANT: THIS SOFTWARE END-USER LICENSE AGREEMENT ("EULA") IS A LEGAL
6
6
  AGREEMENT (“Agreement”) BETWEEN YOU (THE CUSTOMER, EITHER AS AN INDIVIDUAL OR,
7
7
  IF PURCHASED OR OTHERWISE ACQUIRED BY OR FOR AN ENTITY, AS AN ENTITY) AND
8
- CONTRIBUTED SYSTEMS. READ IT CAREFULLY BEFORE COMPLETING THE INSTALLATION
9
- PROCESS AND USING SIDEKIQ PRO AND RELATED SOFTWARE COMPONENTS (“SOFTWARE”).
8
+ SCHIRP DSO LTD. READ IT CAREFULLY BEFORE COMPLETING THE INSTALLATION
9
+ PROCESS AND USING MUTANT AND RELATED SOFTWARE COMPONENTS (“SOFTWARE”).
10
10
 
11
11
  IT PROVIDES A LICENSE TO USE THE SOFTWARE AND CONTAINS WARRANTY INFORMATION
12
12
  AND LIABILITY DISCLAIMERS. BY INSTALLING AND USING THE SOFTWARE, YOU ARE
@@ -71,6 +71,10 @@ module Mutant
71
71
 
72
72
  hooks.run(:env_infection_pre, env)
73
73
 
74
+ config.environment_variables.each do |key, value|
75
+ world.environment_variables[key] = value
76
+ end
77
+
74
78
  config.includes.each(&world.load_path.public_method(:<<))
75
79
  config.requires.each(&world.kernel.public_method(:require))
76
80
 
@@ -62,6 +62,7 @@ module Mutant
62
62
  set(matcher: @config.matcher.add(attribute, value))
63
63
  end
64
64
 
65
+ # rubocop:disable Metrics/MethodLength
65
66
  def add_environment_options(parser)
66
67
  parser.separator('Environment:')
67
68
  parser.on('--zombie', 'Run mutant zombified') do
@@ -73,7 +74,14 @@ module Mutant
73
74
  parser.on('-r', '--require NAME', 'Require file with NAME') do |name|
74
75
  add(:requires, name)
75
76
  end
77
+ parser.on('--env KEY=VALUE', 'Set environment variable') do |value|
78
+ match = ENV_VARIABLE_KEY_VALUE_REGEXP.match(value) || fail("Invalid env variable: #{value.inspect}")
79
+ set(
80
+ environment_variables: @config.environment_variables.merge(match[:key] => match[:value])
81
+ )
82
+ end
76
83
  end
84
+ # rubocop:enable Metrics/MethodLength
77
85
 
78
86
  def add_integration_options(parser)
79
87
  parser.separator('Integration:')
data/lib/mutant/config.rb CHANGED
@@ -5,9 +5,12 @@ module Mutant
5
5
  #
6
6
  # Does not reference any "external" volatile state. The configuration applied
7
7
  # to current environment is being represented by the Mutant::Env object.
8
+ #
9
+ # rubocop:disable Metrics/ClassLength
8
10
  class Config
9
11
  include Adamantium, Anima.new(
10
12
  :coverage_criteria,
13
+ :environment_variables,
11
14
  :expression_parser,
12
15
  :fail_fast,
13
16
  :hooks,
@@ -48,16 +51,17 @@ module Mutant
48
51
  # rubocop:disable Metrics/MethodLength
49
52
  def merge(other)
50
53
  other.with(
51
- coverage_criteria: coverage_criteria.merge(other.coverage_criteria),
52
- fail_fast: fail_fast || other.fail_fast,
53
- hooks: hooks + other.hooks,
54
- includes: includes + other.includes,
55
- integration: other.integration || integration,
56
- jobs: other.jobs || jobs,
57
- matcher: matcher.merge(other.matcher),
58
- mutation_timeout: other.mutation_timeout || mutation_timeout,
59
- requires: requires + other.requires,
60
- zombie: zombie || other.zombie
54
+ coverage_criteria: coverage_criteria.merge(other.coverage_criteria),
55
+ environment_variables: environment_variables.merge(other.environment_variables),
56
+ fail_fast: fail_fast || other.fail_fast,
57
+ hooks: hooks + other.hooks,
58
+ includes: includes + other.includes,
59
+ integration: other.integration || integration,
60
+ jobs: other.jobs || jobs,
61
+ matcher: matcher.merge(other.matcher),
62
+ mutation_timeout: other.mutation_timeout || mutation_timeout,
63
+ requires: requires + other.requires,
64
+ zombie: zombie || other.zombie
61
65
  )
62
66
  end
63
67
  # rubocop:enable Metrics/AbcSize
@@ -117,6 +121,24 @@ module Mutant
117
121
  )
118
122
  )
119
123
 
124
+ # Parse a hash of environment variables
125
+ #
126
+ # @param [Hash<Object,Object>]
127
+ #
128
+ # @return [Either<String,Hash<String,String>]
129
+ #
130
+ def self.parse_environment_variables(hash)
131
+ invalid = hash.keys.reject { |key| key.instance_of?(String) }
132
+ return Either::Left.new("Non string keys: #{invalid}") if invalid.any?
133
+
134
+ invalid = hash.keys.grep_v(ENV_VARIABLE_KEY_REGEXP)
135
+ return Either::Left.new("Invalid keys: #{invalid}") if invalid.any?
136
+
137
+ invalid = hash.values.reject { |value| value.instance_of?(String) }
138
+ return Either::Left.new("Non string values: #{invalid}") if invalid.any?
139
+
140
+ Either::Right.new(hash)
141
+ end
120
142
  TRANSFORM = Transform::Sequence.new(
121
143
  [
122
144
  Transform::Exception.new(SystemCallError, :read.to_proc),
@@ -124,14 +146,23 @@ module Mutant
124
146
  Transform::Hash.new(
125
147
  optional: [
126
148
  Transform::Hash::Key.new('coverage_criteria', ->(value) { CoverageCriteria::TRANSFORM.call(value) }),
127
- Transform::Hash::Key.new('fail_fast', Transform::BOOLEAN),
128
- Transform::Hash::Key.new('hooks', PATHNAME_ARRAY),
129
- Transform::Hash::Key.new('includes', Transform::STRING_ARRAY),
130
- Transform::Hash::Key.new('integration', Transform::STRING),
131
- Transform::Hash::Key.new('jobs', Transform::INTEGER),
132
- Transform::Hash::Key.new('matcher', Matcher::Config::LOADER),
133
- Transform::Hash::Key.new('mutation_timeout', Transform::FLOAT),
134
- Transform::Hash::Key.new('requires', Transform::STRING_ARRAY)
149
+ Transform::Hash::Key.new(
150
+ 'environment_variables',
151
+ Transform::Sequence.new(
152
+ [
153
+ Transform::Primitive.new(Hash),
154
+ Transform::Block.capture(:environment_variables, &method(:parse_environment_variables))
155
+ ]
156
+ )
157
+ ),
158
+ Transform::Hash::Key.new('fail_fast', Transform::BOOLEAN),
159
+ Transform::Hash::Key.new('hooks', PATHNAME_ARRAY),
160
+ Transform::Hash::Key.new('includes', Transform::STRING_ARRAY),
161
+ Transform::Hash::Key.new('integration', Transform::STRING),
162
+ Transform::Hash::Key.new('jobs', Transform::INTEGER),
163
+ Transform::Hash::Key.new('matcher', Matcher::Config::LOADER),
164
+ Transform::Hash::Key.new('mutation_timeout', Transform::FLOAT),
165
+ Transform::Hash::Key.new('requires', Transform::STRING_ARRAY)
135
166
  ],
136
167
  required: []
137
168
  ),
@@ -141,4 +172,5 @@ module Mutant
141
172
 
142
173
  private_constant(:TRANSFORM)
143
174
  end # Config
175
+ # rubocop:enable Metrics/ClassLength
144
176
  end # Mutant
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ class Expression
5
+ class Descendants < self
6
+ include Anima.new(:const_name)
7
+
8
+ REGEXP = /\Adescendants:(?<const_name>.+)\z/.freeze
9
+
10
+ def syntax
11
+ "descendants:#{const_name}"
12
+ end
13
+
14
+ def matcher
15
+ Matcher::Descendants.new(const_name: const_name)
16
+ end
17
+ end # Descendants
18
+ end # Expression
19
+ end # Mutant
@@ -14,7 +14,7 @@ module Mutant
14
14
  def call(env)
15
15
  matchers.flat_map do |matcher|
16
16
  matcher.call(env)
17
- end
17
+ end.uniq
18
18
  end
19
19
 
20
20
  end # Chain
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ class Matcher
5
+ # Matcher for all descendants by constant name
6
+ class Descendants < self
7
+ include Anima.new(:const_name)
8
+
9
+ def call(env)
10
+ const = env.world.try_const_get(const_name) or return EMPTY_ARRAY
11
+
12
+ Chain.new(
13
+ matched_scopes(env, const).map { |scope| Scope.new(scope.raw) }
14
+ ).call(env)
15
+ end
16
+
17
+ private
18
+
19
+ def matched_scopes(env, const)
20
+ env.matchable_scopes.select do |scope|
21
+ scope.raw.equal?(const) || const > scope.raw
22
+ end
23
+ end
24
+ end # Descendant
25
+ end # Matcher
26
+ end # Mutant
@@ -21,7 +21,7 @@ module Mutant
21
21
  # @return [Enumerable<Subject>]
22
22
  def call(env)
23
23
  Chain.new(
24
- methods.map { |method| matcher.new(scope, method) }
24
+ methods(env).map { |method| matcher.new(scope, method) }
25
25
  ).call(env)
26
26
  end
27
27
 
@@ -31,17 +31,16 @@ module Mutant
31
31
  self.class::MATCHER
32
32
  end
33
33
 
34
- def methods
34
+ def methods(env)
35
35
  candidate_names.each_with_object([]) do |name, methods|
36
- method = access(name)
37
- methods << method if method.owner.equal?(candidate_scope)
36
+ method = access(env, name)
37
+ methods << method if method&.owner.equal?(candidate_scope)
38
38
  end
39
39
  end
40
- memoize :methods
41
40
 
42
41
  def candidate_names
43
42
  CANDIDATE_NAMES
44
- .map(&candidate_scope.public_method(:public_send))
43
+ .map { |name| candidate_scope.public_send(name, false) }
45
44
  .reduce(:+)
46
45
  .sort
47
46
  end
@@ -55,7 +54,7 @@ module Mutant
55
54
 
56
55
  private
57
56
 
58
- def access(method_name)
57
+ def access(_env, method_name)
59
58
  scope.method(method_name)
60
59
  end
61
60
 
@@ -71,7 +70,7 @@ module Mutant
71
70
 
72
71
  private
73
72
 
74
- def access(method_name)
73
+ def access(_env, method_name)
75
74
  scope.method(method_name)
76
75
  end
77
76
 
@@ -84,11 +83,35 @@ module Mutant
84
83
  class Instance < self
85
84
  MATCHER = Matcher::Method::Instance
86
85
 
86
+ MESSAGE = <<~'MESSAGE'
87
+ Caught an exception while accessing a method with
88
+ #instance_method that is part of #{public,privat,protected}_instance_methods.
89
+
90
+ This is a bug in your ruby implementation its stdlib, libaries our your code.
91
+
92
+ Mutant will ignore this method:
93
+
94
+ Object: %<scope>s
95
+ Method: %<method_name>s
96
+ Exception:
97
+
98
+ %<exception>s
99
+
100
+ See: https://github.com/mbj/mutant/issues/1273
101
+ MESSAGE
102
+
87
103
  private
88
104
 
89
- def access(method_name)
105
+ # rubocop:disable Lint/RescueException
106
+ def access(env, method_name)
90
107
  scope.instance_method(method_name)
108
+ rescue Exception => exception
109
+ env.warn(
110
+ MESSAGE % { scope: scope, method_name: method_name, exception: exception }
111
+ )
112
+ nil
91
113
  end
114
+ # rubocop:enable Lint/RescueException
92
115
 
93
116
  def candidate_scope
94
117
  scope
@@ -6,6 +6,8 @@ module Mutant
6
6
  # Mutator for arguments node
7
7
  class Arguments < self
8
8
 
9
+ ANONYMOUS_BLOCKARG_PRED = ::Parser::AST::Node.new(:blockarg, [nil]).method(:eql?)
10
+
9
11
  handle(:args)
10
12
 
11
13
  private
@@ -17,15 +19,24 @@ module Mutant
17
19
  end
18
20
 
19
21
  def emit_argument_presence
20
- emit_type
22
+ emit_type unless removed_block_arg?(EMPTY_ARRAY)
21
23
 
22
24
  Util::Array::Presence.call(children).each do |children|
23
- unless children.one? && n_mlhs?(children.first)
25
+ unless removed_block_arg?(children) || (children.one? && n_mlhs?(children.first))
24
26
  emit_type(*children)
25
27
  end
26
28
  end
27
29
  end
28
30
 
31
+ def removed_block_arg?(children)
32
+ anonymous_block_arg? && children.none?(&ANONYMOUS_BLOCKARG_PRED)
33
+ end
34
+
35
+ def anonymous_block_arg?
36
+ children.any?(&ANONYMOUS_BLOCKARG_PRED)
37
+ end
38
+ memoize :anonymous_block_arg?
39
+
29
40
  def emit_argument_mutations
30
41
  children.each_with_index do |child, index|
31
42
  Mutator.mutate(child).each do |mutant|
@@ -12,6 +12,7 @@ module Mutant
12
12
  private
13
13
 
14
14
  def dispatch
15
+ return unless argument
15
16
  emit_argument_mutations
16
17
  emit_symbol_to_proc_mutations
17
18
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # Current mutant version
5
- VERSION = '0.11.0'
5
+ VERSION = '0.11.4'
6
6
  end # Mutant
data/lib/mutant/world.rb CHANGED
@@ -5,6 +5,7 @@ module Mutant
5
5
  class World
6
6
  include Adamantium, Anima.new(
7
7
  :condition_variable,
8
+ :environment_variables,
8
9
  :gem,
9
10
  :gem_method,
10
11
  :io,
@@ -49,6 +50,19 @@ module Mutant
49
50
  end
50
51
  end
51
52
 
53
+ # Try const get
54
+ #
55
+ # @param [String]
56
+ #
57
+ # @return [Class|Module|nil]
58
+ #
59
+ # rubocop:disable Lint/SuppressedException
60
+ def try_const_get(name)
61
+ kernel.const_get(name)
62
+ rescue NameError
63
+ end
64
+ # rubocop:enable Lint/SuppressedException
65
+
52
66
  # Deadline
53
67
  #
54
68
  # @param [Float, nil] allowed_time
data/lib/mutant.rb CHANGED
@@ -38,6 +38,11 @@ module Mutant
38
38
  EMPTY_ARRAY = [].freeze
39
39
  EMPTY_HASH = {}.freeze
40
40
  SCOPE_OPERATOR = '::'
41
+
42
+ env_key = /[a-zA-Z_\d]+/
43
+
44
+ ENV_VARIABLE_KEY_VALUE_REGEXP = /\A(?<key>#{env_key}+)=(?<value>.*)\z/.freeze
45
+ ENV_VARIABLE_KEY_REGEXP = /\A#{env_key}\z/.freeze
41
46
  end # Mutant
42
47
 
43
48
  require 'mutant/procto'
@@ -164,23 +169,25 @@ require 'mutant/subject/method/instance'
164
169
  require 'mutant/subject/method/singleton'
165
170
  require 'mutant/subject/method/metaclass'
166
171
  require 'mutant/matcher'
167
- require 'mutant/matcher/config'
168
172
  require 'mutant/matcher/chain'
173
+ require 'mutant/matcher/config'
174
+ require 'mutant/matcher/descendants'
175
+ require 'mutant/matcher/filter'
169
176
  require 'mutant/matcher/method'
170
- require 'mutant/matcher/method/singleton'
171
- require 'mutant/matcher/method/metaclass'
172
177
  require 'mutant/matcher/method/instance'
178
+ require 'mutant/matcher/method/metaclass'
179
+ require 'mutant/matcher/method/singleton'
173
180
  require 'mutant/matcher/methods'
174
181
  require 'mutant/matcher/namespace'
175
- require 'mutant/matcher/scope'
176
- require 'mutant/matcher/filter'
177
182
  require 'mutant/matcher/null'
183
+ require 'mutant/matcher/scope'
178
184
  require 'mutant/matcher/static'
179
185
  require 'mutant/expression'
180
- require 'mutant/expression/parser'
186
+ require 'mutant/expression/descendants'
181
187
  require 'mutant/expression/method'
182
188
  require 'mutant/expression/methods'
183
189
  require 'mutant/expression/namespace'
190
+ require 'mutant/expression/parser'
184
191
  require 'mutant/test'
185
192
  require 'mutant/timer'
186
193
  require 'mutant/integration'
@@ -234,46 +241,49 @@ require 'mutant/license/subscription/commercial'
234
241
 
235
242
  module Mutant
236
243
  WORLD = World.new(
237
- condition_variable: ConditionVariable,
238
- gem: Gem,
239
- gem_method: method(:gem),
240
- io: IO,
241
- json: JSON,
242
- kernel: Kernel,
243
- load_path: $LOAD_PATH,
244
- marshal: Marshal,
245
- mutex: Mutex,
246
- object_space: ObjectSpace,
247
- open3: Open3,
248
- pathname: Pathname,
249
- process: Process,
250
- stderr: $stderr,
251
- stdout: $stdout,
252
- thread: Thread,
253
- timer: Timer.new(Process)
244
+ condition_variable: ConditionVariable,
245
+ environment_variables: ENV,
246
+ gem: Gem,
247
+ gem_method: method(:gem),
248
+ io: IO,
249
+ json: JSON,
250
+ kernel: Kernel,
251
+ load_path: $LOAD_PATH,
252
+ marshal: Marshal,
253
+ mutex: Mutex,
254
+ object_space: ObjectSpace,
255
+ open3: Open3,
256
+ pathname: Pathname,
257
+ process: Process,
258
+ stderr: $stderr,
259
+ stdout: $stdout,
260
+ thread: Thread,
261
+ timer: Timer.new(Process)
254
262
  )
255
263
 
256
264
  # Reopen class to initialize constant to avoid dep circle
257
265
  class Config
258
266
  DEFAULT = new(
259
- coverage_criteria: Config::CoverageCriteria::EMPTY,
260
- expression_parser: Expression::Parser.new([
267
+ coverage_criteria: Config::CoverageCriteria::EMPTY,
268
+ expression_parser: Expression::Parser.new([
269
+ Expression::Descendants,
261
270
  Expression::Method,
262
271
  Expression::Methods,
263
272
  Expression::Namespace::Exact,
264
273
  Expression::Namespace::Recursive
265
274
  ]),
266
- fail_fast: false,
267
- hooks: EMPTY_ARRAY,
268
- includes: EMPTY_ARRAY,
269
- integration: nil,
270
- isolation: Mutant::Isolation::Fork.new(WORLD),
271
- jobs: nil,
272
- matcher: Matcher::Config::DEFAULT,
273
- mutation_timeout: nil,
274
- reporter: Reporter::CLI.build(WORLD.stdout),
275
- requires: EMPTY_ARRAY,
276
- zombie: false
275
+ fail_fast: false,
276
+ environment_variables: EMPTY_HASH,
277
+ hooks: EMPTY_ARRAY,
278
+ includes: EMPTY_ARRAY,
279
+ integration: nil,
280
+ isolation: Mutant::Isolation::Fork.new(WORLD),
281
+ jobs: nil,
282
+ matcher: Matcher::Config::DEFAULT,
283
+ mutation_timeout: nil,
284
+ reporter: Reporter::CLI.build(WORLD.stdout),
285
+ requires: EMPTY_ARRAY,
286
+ zombie: false
277
287
  )
278
288
  end # Config
279
289
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.11.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-18 00:00:00.000000000 Z
11
+ date: 2022-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diff-lcs
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 3.0.0
33
+ version: 3.1.0
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: 3.0.0
40
+ version: 3.1.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: regexp_parser
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +78,14 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: 0.6.0
81
+ version: 0.6.4
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: 0.6.0
88
+ version: 0.6.4
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: parallel
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -207,6 +207,7 @@ files:
207
207
  - lib/mutant/context.rb
208
208
  - lib/mutant/env.rb
209
209
  - lib/mutant/expression.rb
210
+ - lib/mutant/expression/descendants.rb
210
211
  - lib/mutant/expression/method.rb
211
212
  - lib/mutant/expression/methods.rb
212
213
  - lib/mutant/expression/namespace.rb
@@ -226,6 +227,7 @@ files:
226
227
  - lib/mutant/matcher.rb
227
228
  - lib/mutant/matcher/chain.rb
228
229
  - lib/mutant/matcher/config.rb
230
+ - lib/mutant/matcher/descendants.rb
229
231
  - lib/mutant/matcher/filter.rb
230
232
  - lib/mutant/matcher/method.rb
231
233
  - lib/mutant/matcher/method/instance.rb
@@ -382,7 +384,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
382
384
  - !ruby/object:Gem::Version
383
385
  version: '0'
384
386
  requirements: []
385
- rubygems_version: 3.1.6
387
+ rubygems_version: 3.3.3
386
388
  signing_key:
387
389
  specification_version: 4
388
390
  summary: ''