prop_check 0.13.0 → 0.14.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/.rubocop.yml +2 -0
- data/CHANGELOG.md +1 -0
- data/lib/prop_check/generators.rb +85 -26
- data/lib/prop_check/hooks.rb +20 -13
- data/lib/prop_check/property.rb +56 -28
- data/lib/prop_check/property/configuration.rb +1 -1
- data/lib/prop_check/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 013ca5101f31799feb0c86533c4100a781c451f937d6d8497a30476073e27e4b
|
4
|
+
data.tar.gz: f592ec086ca3018cfca1016baa1690619a5783274f02c910eb2ad03e5861a53d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f49b2514fe4e179013bd8c4a4683c1210b65d6852901156c6c5373f26305343fa4cae40860f13386a8f1fda33406927bf20a357f88cd5b99936318410837ba00
|
7
|
+
data.tar.gz: 261b980fb68c2d1af8baccb09919a838f91c1f6ae33f8c8a79923b2cb50490e4406e848ffbf6a75361d13d33719907a3342b4a7eed88ebdf37d1bdd8cd981ee4
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
- 0.14.0 - Adds `uniq: true` option to `Generators.array`. Makes `PropCheck::Property` an immutable object that returns copies that have changes whenever reconfiguring, allowing re-usable configuration.
|
1
2
|
- 0.13.0 - Adds Generator#resize
|
2
3
|
- 0.12.1 - Fixes shrinking when filtering bug.
|
3
4
|
- 0.12.0 - `PropCheck::Generators#instance`
|
@@ -9,7 +9,7 @@ module PropCheck
|
|
9
9
|
# Use this module by including it in the class (e.g. in your test suite)
|
10
10
|
# where you want to use them.
|
11
11
|
module Generators
|
12
|
-
|
12
|
+
module_function
|
13
13
|
|
14
14
|
##
|
15
15
|
# Always returns the same value, regardless of `size` or `rng` (random number generator state)
|
@@ -146,7 +146,7 @@ module PropCheck
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
149
|
-
|
149
|
+
@@special_floats = [Float::NAN, Float::INFINITY, -Float::INFINITY, Float::MAX, Float::MIN, 0.0.next_float, 0.0.prev_float]
|
150
150
|
##
|
151
151
|
# Generates floating-point numbers
|
152
152
|
# Will generate NaN, Infinity, -Infinity,
|
@@ -159,7 +159,7 @@ module PropCheck
|
|
159
159
|
# >> Generators.float().sample(10, size: 10, rng: Random.new(42))
|
160
160
|
# => [4.0, 9.555555555555555, 0.0, -Float::INFINITY, 5.5, -5.818181818181818, 1.1428571428571428, 0.0, 8.0, 7.857142857142858]
|
161
161
|
def float
|
162
|
-
frequency(99 => real_float, 1 => one_of(
|
162
|
+
frequency(99 => real_float, 1 => one_of(*@@special_floats.map(&method(:constant))))
|
163
163
|
end
|
164
164
|
|
165
165
|
##
|
@@ -241,6 +241,12 @@ module PropCheck
|
|
241
241
|
# `empty:` When false, behaves the same as `min: 1`
|
242
242
|
# `min:` Ensures at least this many elements are generated. (default: 0)
|
243
243
|
# `max:` Ensures at most this many elements are generated. When nil, an arbitrary count is used instead. (default: nil)
|
244
|
+
# `uniq:` When `true`, ensures that all elements in the array are unique.
|
245
|
+
# When given a proc, uses the result of this proc to check for uniqueness.
|
246
|
+
# (matching the behaviour of `Array#uniq`)
|
247
|
+
# If it is not possible to generate another unique value after the configured `max_consecutive_attempts`
|
248
|
+
# an `PropCheck::Errors::GeneratorExhaustedError` will be raised.
|
249
|
+
# (default: `false`)
|
244
250
|
#
|
245
251
|
#
|
246
252
|
# >> Generators.array(Generators.positive_integer).sample(5, size: 1, rng: Random.new(42))
|
@@ -252,25 +258,68 @@ module PropCheck
|
|
252
258
|
# => [[], [2], [], [], [2]]
|
253
259
|
# >> Generators.array(Generators.positive_integer, empty: false).sample(5, size: 1, rng: Random.new(1))
|
254
260
|
# => [[2], [1], [2], [1], [1]]
|
261
|
+
#
|
262
|
+
# >> Generators.array(Generators.boolean, uniq: true).sample(5, rng: Random.new(1))
|
263
|
+
# => [[true, false], [false, true], [true, false], [false, true], [false, true]]
|
255
264
|
|
256
|
-
|
257
|
-
def array(element_generator, min: 0, max: nil, empty: true)
|
265
|
+
def array(element_generator, min: 0, max: nil, empty: true, uniq: false)
|
258
266
|
min = 1 if min.zero? && !empty
|
267
|
+
uniq = proc { |x| x } if uniq == true
|
259
268
|
|
260
|
-
|
261
|
-
count
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
269
|
+
if max.nil?
|
270
|
+
nonnegative_integer.bind { |count| make_array(element_generator, min, count, uniq) }
|
271
|
+
else
|
272
|
+
make_array(element_generator, min, max, uniq)
|
273
|
+
end
|
274
|
+
end
|
266
275
|
|
267
|
-
|
276
|
+
private def make_array(element_generator, min, count, uniq)
|
277
|
+
amount = min if count < min
|
278
|
+
amount = min if count == min && min != 0
|
279
|
+
amount ||= (count - min)
|
280
|
+
|
281
|
+
# Simple, optimized implementation:
|
282
|
+
return make_array_simple(element_generator, amount) unless uniq
|
283
|
+
|
284
|
+
# More complex implementation that filters duplicates
|
285
|
+
make_array_uniq(element_generator, min, amount, uniq)
|
286
|
+
end
|
287
|
+
|
288
|
+
private def make_array_simple(element_generator, amount)
|
289
|
+
generators = amount.times.map do
|
290
|
+
element_generator.clone
|
268
291
|
end
|
269
292
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
293
|
+
tuple(*generators)
|
294
|
+
end
|
295
|
+
|
296
|
+
private def make_array_uniq(element_generator, min, amount, uniq_fun)
|
297
|
+
Generator.new do |**kwargs|
|
298
|
+
arr = []
|
299
|
+
uniques = Set.new
|
300
|
+
count = 0
|
301
|
+
(0..).lazy.map do
|
302
|
+
elem = element_generator.clone.generate(**kwargs)
|
303
|
+
if uniques.add?(uniq_fun.call(elem.root))
|
304
|
+
arr.push(elem)
|
305
|
+
count = 0
|
306
|
+
else
|
307
|
+
count += 1
|
308
|
+
end
|
309
|
+
|
310
|
+
if count > kwargs[:max_consecutive_attempts]
|
311
|
+
if arr.size >= min
|
312
|
+
# Give up and return shorter array in this case
|
313
|
+
amount = min
|
314
|
+
else
|
315
|
+
raise Errors::GeneratorExhaustedError, "Too many consecutive elements filtered by 'uniq:'."
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
.take_while { arr.size < amount }
|
320
|
+
.force
|
321
|
+
|
322
|
+
LazyTree.zip(arr).map { |array| array.uniq(&uniq_fun) }
|
274
323
|
end
|
275
324
|
end
|
276
325
|
|
@@ -300,7 +349,7 @@ module PropCheck
|
|
300
349
|
.map(&:to_h)
|
301
350
|
end
|
302
351
|
|
303
|
-
|
352
|
+
@@alphanumeric_chars = [('a'..'z'), ('A'..'Z'), ('0'..'9')].flat_map(&:to_a).freeze
|
304
353
|
##
|
305
354
|
# Generates a single-character string
|
306
355
|
# containing one of a..z, A..Z, 0..9
|
@@ -310,7 +359,7 @@ module PropCheck
|
|
310
359
|
# >> Generators.alphanumeric_char.sample(5, size: 10, rng: Random.new(42))
|
311
360
|
# => ["M", "Z", "C", "o", "Q"]
|
312
361
|
def alphanumeric_char
|
313
|
-
one_of(
|
362
|
+
one_of(*@@alphanumeric_chars.map(&method(:constant)))
|
314
363
|
end
|
315
364
|
|
316
365
|
##
|
@@ -321,11 +370,13 @@ module PropCheck
|
|
321
370
|
#
|
322
371
|
# >> Generators.alphanumeric_string.sample(5, size: 10, rng: Random.new(42))
|
323
372
|
# => ["ZCoQ", "8uM", "wkkx0JNx", "v0bxRDLb", "Gl5v8RyWA6"]
|
373
|
+
#
|
374
|
+
# Accepts the same options as `array`
|
324
375
|
def alphanumeric_string(**kwargs)
|
325
376
|
array(alphanumeric_char, **kwargs).map(&:join)
|
326
377
|
end
|
327
378
|
|
328
|
-
|
379
|
+
@@printable_ascii_chars = (' '..'~').to_a.freeze
|
329
380
|
|
330
381
|
##
|
331
382
|
# Generates a single-character string
|
@@ -336,7 +387,7 @@ module PropCheck
|
|
336
387
|
# >> Generators.printable_ascii_char.sample(size: 10, rng: Random.new(42))
|
337
388
|
# => ["S", "|", ".", "g", "\\", "4", "r", "v", "j", "j"]
|
338
389
|
def printable_ascii_char
|
339
|
-
one_of(
|
390
|
+
one_of(*@@printable_ascii_chars.map(&method(:constant)))
|
340
391
|
end
|
341
392
|
|
342
393
|
##
|
@@ -347,12 +398,14 @@ module PropCheck
|
|
347
398
|
#
|
348
399
|
# >> Generators.printable_ascii_string.sample(5, size: 10, rng: Random.new(42))
|
349
400
|
# => ["S|.g", "rvjjw7\"5T!", "=", "!_[4@", "Y"]
|
401
|
+
#
|
402
|
+
# Accepts the same options as `array`
|
350
403
|
def printable_ascii_string(**kwargs)
|
351
404
|
array(printable_ascii_char, **kwargs).map(&:join)
|
352
405
|
end
|
353
406
|
|
354
|
-
|
355
|
-
|
407
|
+
@@ascii_chars = [
|
408
|
+
@@printable_ascii_chars,
|
356
409
|
[
|
357
410
|
"\n",
|
358
411
|
"\r",
|
@@ -375,7 +428,7 @@ module PropCheck
|
|
375
428
|
# >> Generators.ascii_char.sample(size: 10, rng: Random.new(42))
|
376
429
|
# => ["d", "S", "|", ".", "g", "\\", "4", "d", "r", "v"]
|
377
430
|
def ascii_char
|
378
|
-
one_of(
|
431
|
+
one_of(*@@ascii_chars.map(&method(:constant)))
|
379
432
|
end
|
380
433
|
|
381
434
|
##
|
@@ -386,12 +439,14 @@ module PropCheck
|
|
386
439
|
#
|
387
440
|
# >> Generators.ascii_string.sample(5, size: 10, rng: Random.new(42))
|
388
441
|
# => ["S|.g", "drvjjw\b\a7\"", "!w=E!_[4@k", "x", "zZI{[o"]
|
442
|
+
#
|
443
|
+
# Accepts the same options as `array`
|
389
444
|
def ascii_string(**kwargs)
|
390
445
|
array(ascii_char, **kwargs).map(&:join)
|
391
446
|
end
|
392
447
|
|
393
|
-
|
394
|
-
|
448
|
+
@@printable_chars = [
|
449
|
+
@@ascii_chars,
|
395
450
|
"\u{A0}".."\u{D7FF}",
|
396
451
|
"\u{E000}".."\u{FFFD}",
|
397
452
|
"\u{10000}".."\u{10FFFF}"
|
@@ -406,7 +461,7 @@ module PropCheck
|
|
406
461
|
# >> Generators.printable_char.sample(size: 10, rng: Random.new(42))
|
407
462
|
# => ["吏", "", "", "", "", "", "", "", "", "Ȍ"]
|
408
463
|
def printable_char
|
409
|
-
one_of(
|
464
|
+
one_of(*@@printable_chars.map(&method(:constant)))
|
410
465
|
end
|
411
466
|
|
412
467
|
##
|
@@ -417,6 +472,8 @@ module PropCheck
|
|
417
472
|
#
|
418
473
|
# >> Generators.printable_string.sample(5, size: 10, rng: Random.new(42))
|
419
474
|
# => ["", "Ȍ", "𐁂", "Ȕ", ""]
|
475
|
+
#
|
476
|
+
# Accepts the same options as `array`
|
420
477
|
def printable_string(**kwargs)
|
421
478
|
array(printable_char, **kwargs).map(&:join)
|
422
479
|
end
|
@@ -443,6 +500,8 @@ module PropCheck
|
|
443
500
|
#
|
444
501
|
# >> Generators.string.sample(5, size: 10, rng: Random.new(42))
|
445
502
|
# => ["\u{A3DB3}𠍜\u{3F46A}\u{1AEBC}", "𡡹\u{DED74}𪱣\u{43E97}ꂂ\u{50695}\u{C0301}", "\u{4FD9D}", "\u{C14BF}\u{193BB}𭇋\u{76B58}", "𦐺\u{9FDDB}\u{80ABB}\u{9E3CF}𐂽\u{14AAE}"]
|
503
|
+
#
|
504
|
+
# Accepts the same options as `array`
|
446
505
|
def string(**kwargs)
|
447
506
|
array(char, **kwargs).map(&:join)
|
448
507
|
end
|
data/lib/prop_check/hooks.rb
CHANGED
@@ -19,10 +19,11 @@
|
|
19
19
|
# wrapping the elements of an enumerable with hooks.
|
20
20
|
class PropCheck::Hooks
|
21
21
|
# attr_reader :before, :after, :around
|
22
|
-
def initialize()
|
23
|
-
@before =
|
24
|
-
@after =
|
25
|
-
@around =
|
22
|
+
def initialize(before: proc {}, after: proc {}, around: proc { |*args, &block| block.call(*args) })
|
23
|
+
@before = before
|
24
|
+
@after = after
|
25
|
+
@around = around
|
26
|
+
freeze
|
26
27
|
end
|
27
28
|
|
28
29
|
def wrap_enum(enumerable)
|
@@ -59,34 +60,40 @@ class PropCheck::Hooks
|
|
59
60
|
# Adds `hook` to the `before` proc.
|
60
61
|
# It is called after earlier-added `before` procs.
|
61
62
|
def add_before(&hook)
|
62
|
-
old_before = @before
|
63
|
-
|
64
|
-
|
63
|
+
# old_before = @before
|
64
|
+
new_before = proc {
|
65
|
+
@before.call
|
65
66
|
hook.call
|
66
67
|
}
|
68
|
+
# self
|
69
|
+
self.class.new(before: new_before, after: @after, around: @around)
|
67
70
|
end
|
68
71
|
|
69
72
|
##
|
70
73
|
# Adds `hook` to the `after` proc.
|
71
74
|
# It is called before earlier-added `after` procs.
|
72
75
|
def add_after(&hook)
|
73
|
-
old_after = @after
|
74
|
-
|
76
|
+
# old_after = @after
|
77
|
+
new_after = proc {
|
75
78
|
hook.call
|
76
|
-
|
79
|
+
@after.call
|
77
80
|
}
|
81
|
+
# self
|
82
|
+
self.class.new(before: @before, after: new_after, around: @around)
|
78
83
|
end
|
79
84
|
|
80
85
|
##
|
81
86
|
# Adds `hook` to the `around` proc.
|
82
87
|
# It is called _inside_ earlier-added `around` procs.
|
83
88
|
def add_around(&hook)
|
84
|
-
old_around = @around
|
85
|
-
|
86
|
-
|
89
|
+
# old_around = @around
|
90
|
+
new_around = proc do |&block|
|
91
|
+
@around.call do |*args|
|
87
92
|
hook.call(*args, &block)
|
88
93
|
end
|
89
94
|
end
|
95
|
+
# self
|
96
|
+
self.class.new(before: @before, after: @after, around: new_around)
|
90
97
|
end
|
91
98
|
|
92
99
|
##
|
data/lib/prop_check/property.rb
CHANGED
@@ -7,9 +7,15 @@ require 'prop_check/property/shrinker'
|
|
7
7
|
require 'prop_check/hooks'
|
8
8
|
module PropCheck
|
9
9
|
##
|
10
|
-
#
|
10
|
+
# Create and run property-checks.
|
11
|
+
#
|
12
|
+
# For simple usage, see `.forall`.
|
13
|
+
#
|
14
|
+
# For advanced usage, call `PropCheck::Property.new(...)` and then configure it to your liking
|
15
|
+
# using e.g. `#with_config`, `#before`, `#after`, `#around` etc.
|
16
|
+
# Each of these methods will return a new `Property`, so earlier properties are not mutated.
|
17
|
+
# This allows you to re-use configuration and hooks between multiple tests.
|
11
18
|
class Property
|
12
|
-
|
13
19
|
##
|
14
20
|
# Main entry-point to create (and possibly immediately run) a property-test.
|
15
21
|
#
|
@@ -36,7 +42,6 @@ module PropCheck
|
|
36
42
|
# of this class on before finally passing a block to it using `#check`.
|
37
43
|
# (so `forall(Generators.integer) do |val| ... end` and forall(Generators.integer).check do |val| ... end` are the same)
|
38
44
|
def self.forall(*bindings, **kwbindings, &block)
|
39
|
-
|
40
45
|
property = new(*bindings, **kwbindings)
|
41
46
|
|
42
47
|
return property.check(&block) if block_given?
|
@@ -61,19 +66,25 @@ module PropCheck
|
|
61
66
|
yield(configuration)
|
62
67
|
end
|
63
68
|
|
64
|
-
attr_reader :bindings, :condition
|
65
|
-
|
66
69
|
def initialize(*bindings, **kwbindings)
|
67
|
-
raise ArgumentError, 'No bindings specified!' if bindings.empty? && kwbindings.empty?
|
68
|
-
|
69
|
-
# @bindings = bindings
|
70
|
-
# @kwbindings = kwbindings
|
71
|
-
@gen = gen_from_bindings(bindings, kwbindings)
|
72
|
-
@condition = proc { true }
|
73
70
|
@config = self.class.configuration
|
74
71
|
@hooks = PropCheck::Hooks.new
|
72
|
+
|
73
|
+
@gen = gen_from_bindings(bindings, kwbindings) unless bindings.empty? && kwbindings.empty?
|
74
|
+
freeze
|
75
75
|
end
|
76
76
|
|
77
|
+
# [:condition, :config, :hooks, :gen].each do |symbol|
|
78
|
+
# define_method(symbol) do
|
79
|
+
# self.instance_variable_get("@#{symbol}")
|
80
|
+
# end
|
81
|
+
|
82
|
+
# protected define_method("#{symbol}=") do |value|
|
83
|
+
# duplicate = self.dup
|
84
|
+
# duplicate.instance_variable_set("@#{symbol}", value)
|
85
|
+
# duplicate
|
86
|
+
# end
|
87
|
+
|
77
88
|
##
|
78
89
|
# Returns the configuration of this property
|
79
90
|
# for introspection.
|
@@ -91,11 +102,22 @@ module PropCheck
|
|
91
102
|
# you can immediately pass a block to this method.
|
92
103
|
# (so `forall(a: Generators.integer).with_config(verbose: true) do ... end` is the same as `forall(a: Generators.integer).with_config(verbose: true).check do ... end`)
|
93
104
|
def with_config(**config, &block)
|
94
|
-
|
105
|
+
duplicate = self.dup
|
106
|
+
duplicate.instance_variable_set(:@config, @config.merge(config))
|
107
|
+
duplicate.freeze
|
95
108
|
|
96
|
-
return
|
109
|
+
return duplicate.check(&block) if block_given?
|
97
110
|
|
98
|
-
|
111
|
+
duplicate
|
112
|
+
end
|
113
|
+
|
114
|
+
def with_bindings(*bindings, **kwbindings)
|
115
|
+
raise ArgumentError, 'No bindings specified!' if bindings.empty? && kwbindings.empty?
|
116
|
+
|
117
|
+
duplicate = self.dup
|
118
|
+
duplicate.instance_variable_set(:@gen, gen_from_bindings(bindings, kwbindings))
|
119
|
+
duplicate.freeze
|
120
|
+
duplicate
|
99
121
|
end
|
100
122
|
|
101
123
|
##
|
@@ -107,14 +129,12 @@ module PropCheck
|
|
107
129
|
# you might encounter a GeneratorExhaustedError.
|
108
130
|
# Only filter if you have few inputs to reject. Otherwise, improve your generators.
|
109
131
|
def where(&condition)
|
110
|
-
#
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
self
|
132
|
+
raise ArgumentError, 'No generator bindings specified! #where should be called after `#forall` or `#with_bindings`.' unless @gen
|
133
|
+
|
134
|
+
duplicate = self.dup
|
135
|
+
duplicate.instance_variable_set(:@gen, @gen.where(&condition))
|
136
|
+
duplicate.freeze
|
137
|
+
duplicate
|
118
138
|
end
|
119
139
|
|
120
140
|
|
@@ -124,8 +144,10 @@ module PropCheck
|
|
124
144
|
# This is useful to add setup logic
|
125
145
|
# When called multiple times, earlier-added hooks will be called _before_ `hook` is called.
|
126
146
|
def before(&hook)
|
127
|
-
|
128
|
-
|
147
|
+
duplicate = self.dup
|
148
|
+
duplicate.instance_variable_set(:@hooks, @hooks.add_before(&hook))
|
149
|
+
duplicate.freeze
|
150
|
+
duplicate
|
129
151
|
end
|
130
152
|
|
131
153
|
##
|
@@ -134,8 +156,10 @@ module PropCheck
|
|
134
156
|
# This is useful to add teardown logic
|
135
157
|
# When called multiple times, earlier-added hooks will be called _after_ `hook` is called.
|
136
158
|
def after(&hook)
|
137
|
-
|
138
|
-
|
159
|
+
duplicate = self.dup
|
160
|
+
duplicate.instance_variable_set(:@hooks, @hooks.add_after(&hook))
|
161
|
+
duplicate.freeze
|
162
|
+
duplicate
|
139
163
|
end
|
140
164
|
|
141
165
|
##
|
@@ -152,8 +176,10 @@ module PropCheck
|
|
152
176
|
# it is possible for the code after `yield` not to be called.
|
153
177
|
# So make sure that cleanup logic is wrapped with the `ensure` keyword.
|
154
178
|
def around(&hook)
|
155
|
-
|
156
|
-
|
179
|
+
duplicate = self.dup
|
180
|
+
duplicate.instance_variable_set(:@hooks, @hooks.add_around(&hook))
|
181
|
+
duplicate.freeze
|
182
|
+
duplicate
|
157
183
|
end
|
158
184
|
|
159
185
|
##
|
@@ -238,6 +264,8 @@ c.f. https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-k
|
|
238
264
|
end
|
239
265
|
|
240
266
|
private def attempts_enum(binding_generator)
|
267
|
+
ap @hooks
|
268
|
+
|
241
269
|
@hooks
|
242
270
|
.wrap_enum(raw_attempts_enum(binding_generator))
|
243
271
|
.lazy
|
data/lib/prop_check/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prop_check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Qqwy/Wiebe-Marten Wijnja
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|