coffee_break 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 389dc9b0d377763ef61f9501dec4519620d27403
4
+ data.tar.gz: 8c35aa3c7630152482761965517cd75d11e55647
5
+ SHA512:
6
+ metadata.gz: 577b11e440f1beb387ad15eeab849f417ea79d198755df2d35e3f0d6faa208cc8b80a67a4fb9e0a7457f6bbb360e5636ae33763b3e3cc8c2e0fb09121c054152
7
+ data.tar.gz: eda560c9cd0d74b48159b653041ffe8a020019eccc28bd159469153c031966901adb174b6a283d7c9c76618dab13fbf36a3595f4e196f8aa6c1bd4e00e77d076
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Cohen Carlisle
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # CoffeeBreak
2
+
3
+ A gem to handle waiting until a condition is true.
4
+
5
+ ## About
6
+
7
+ By default, CoffeeBreak calls the supplied block every 0.1 seconds while the
8
+ result of calling the block is falsey. If the block returns a truthy value, that
9
+ value is returned and program execution resumes. If the block isn't truthy
10
+ before the default timeout period of 30 seconds, a `CoffeeBreak::TimeoutError`
11
+ is raised.
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ require 'coffee_break'
17
+ include CoffeeBreak::Waiter
18
+
19
+ Coffee.break.until { 2 + 2 } # => returns 4
20
+ Coffee.break.until { 2 + 2 == 4 } # => returns true
21
+ Coffee.break.until { 2 + 2 == 5 } # => raises CoffeeBreak::TimeoutError
22
+ ```
23
+
24
+ The timeout and time between block calls (interval) can be set in two ways:
25
+
26
+ ```ruby
27
+ ## Universal default
28
+ CoffeeBreak.default_timeout = 5
29
+ CoffeeBreak.default_interval = 0.1
30
+ ## One time setting
31
+ Coffee.break(timeout: 5, interval: 0.1).until { foo }
32
+ ```
33
+
34
+ Similarly, you can tell CoffeeBreak to rescue either one class of errors or an
35
+ array of error classes that the block could raise.
36
+
37
+ ```ruby
38
+ ## Universal default
39
+ CoffeeBreak.default_rescues = NameError
40
+ # or CoffeeBreak.default_rescues = [ArgumentError, NoMethodError]
41
+ ## One time setting
42
+ Coffee.break(rescues: [TypeError, ZeroDivisionError]).until { foo }
43
+ # or Coffee.break(rescues: RuntimeError).until { foo }
44
+ ```
45
+
46
+ You can also tell CoffeeBreak not to raise an error on timeout. Instead, the
47
+ result of calling the block is returned.
48
+
49
+ ```ruby
50
+ ## Universal default
51
+ CoffeeBreak.default_raise = false
52
+ ## One time setting
53
+ Coffee.break(raise: false).until { falsey } # => returns false or nil
54
+ ```
55
+
56
+ Finally, you can provide a message to be used if your block times out. If a
57
+ `CoffeeBreak::TimeoutError` is raised, this will replace the default error
58
+ message. If a timeout occurs but no error is raised (you set raise to `false`),
59
+ the message will print as a warning (otherwise no warning is printed). This is
60
+ only set in `until` (not `break`) and the universal default can't be changed.
61
+
62
+ ```ruby
63
+ ## One time setting
64
+ Coffee.break.until(message: "foo couldn't bar") { foo.bar }
65
+ ```
66
+
67
+ If you don't want `Coffee` in your top level namespace or don't like the above
68
+ syntax, you can use the alternate syntax below. Note that `message` and the
69
+ configuration arguments are all passed to `until`, unlike the above syntax which
70
+ keeps your configuration and `message` arguments separate.
71
+
72
+ ```ruby
73
+ CoffeeBreak.until(message: 'No yo', timeout: 5, raise: false) { Yo.yo? }
74
+ ```
75
+
76
+ ## Development
77
+
78
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
79
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
80
+ prompt that will allow you to experiment.
81
+
82
+ To install this gem onto your local machine, run `bundle exec rake install`. To
83
+ release a new version, update the version number in `version.rb`, and then run
84
+ `bundle exec rake release`, which will create a git tag for the version, push
85
+ git commits and tags, and push the `.gem` file to [rubygems.org]
86
+ (https://rubygems.org).
87
+
88
+ ## Contributing
89
+
90
+ Bug reports and pull requests are welcome on GitHub at
91
+ https://github.com/Cohen-Carlisle/coffee_break.
92
+
93
+
94
+ ## License
95
+
96
+ The gem is available as open source under the terms of the [MIT License]
97
+ (http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "coffee_break"
5
+ require "pry"
6
+
7
+ include CoffeeBreak::Waiter
8
+
9
+ pry
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+ IFS=$'\n\t'
5
+ set -vx
6
+
7
+ bundle install
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'coffee_break/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "coffee_break"
8
+ spec.version = CoffeeBreak::VERSION
9
+ spec.authors = ["Cohen Carlisle"]
10
+ spec.email = ["cohen.carlisle@gmail.com"]
11
+
12
+ spec.summary = "A gem to handle waiting until a condition is true"
13
+ spec.homepage = "https://github.com/Cohen-Carlisle/coffee_break"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.11"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.0"
24
+ spec.add_development_dependency "pry", "~> 0.10"
25
+ end
@@ -0,0 +1,46 @@
1
+ require "coffee_break/version"
2
+ require "coffee_break/errors"
3
+ require "coffee_break/default"
4
+ require "coffee_break/waiter/coffee"
5
+
6
+ module CoffeeBreak
7
+ def self.until(timeout: DEFAULT[:timeout], interval: DEFAULT[:interval],
8
+ rescues: DEFAULT[:rescues], raise: DEFAULT[:raise],
9
+ message: nil, &block)
10
+
11
+ Waiter::Coffee.break(timeout: timeout, interval: interval, rescues: rescues,
12
+ raise: raise).until(message: message, &block)
13
+ end
14
+
15
+ def self.default_timeout
16
+ DEFAULT[:timeout]
17
+ end
18
+
19
+ def self.default_timeout=(seconds)
20
+ DEFAULT[:timeout] = seconds
21
+ end
22
+
23
+ def self.default_interval
24
+ DEFAULT[:interval]
25
+ end
26
+
27
+ def self.default_interval=(seconds)
28
+ DEFAULT[:interval] = seconds
29
+ end
30
+
31
+ def self.default_rescues
32
+ DEFAULT[:rescues]
33
+ end
34
+
35
+ def self.default_rescues=(exceptions)
36
+ DEFAULT[:rescues] = exceptions
37
+ end
38
+
39
+ def self.default_raise
40
+ DEFAULT[:raise]
41
+ end
42
+
43
+ def self.default_raise=(boolean)
44
+ DEFAULT[:raise] = boolean
45
+ end
46
+ end
@@ -0,0 +1,9 @@
1
+ module CoffeeBreak
2
+ # private
3
+ DEFAULT = {
4
+ timeout: 30,
5
+ interval: 0.1,
6
+ rescues: [],
7
+ raise: true
8
+ }
9
+ end
@@ -0,0 +1,3 @@
1
+ module CoffeeBreak
2
+ class TimeoutError < RuntimeError; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module CoffeeBreak
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,38 @@
1
+ module CoffeeBreak
2
+ module Waiter
3
+ class Coffee
4
+ def initialize(timeout: DEFAULT[:timeout], interval: DEFAULT[:interval],
5
+ rescues: DEFAULT[:rescues], raise: DEFAULT[:raise])
6
+
7
+ @timeout = timeout
8
+ @interval = interval
9
+ @rescues = rescues
10
+ @raise = raise
11
+ end
12
+
13
+ class << self
14
+ alias break new
15
+ end
16
+
17
+ def until(message: nil)
18
+ result = nil
19
+ end_time = Time.now + @timeout
20
+ loop do
21
+ begin
22
+ result = yield
23
+ return result if result
24
+ rescue *@rescues
25
+ end
26
+ break if Time.now >= end_time
27
+ sleep @interval
28
+ end
29
+ if @raise
30
+ raise(TimeoutError, message || "Timed out after #{@timeout} seconds")
31
+ else
32
+ warn message if message
33
+ result
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,185 @@
1
+ require 'spec_helper'
2
+
3
+ describe CoffeeBreak do
4
+ it 'has a version number' do
5
+ expect(CoffeeBreak::VERSION).not_to be nil
6
+ end
7
+
8
+ describe '#until' do
9
+ it 'can call Coffee::break and Coffee#until' do
10
+ break_args = {timeout: 9, interval: 8, rescues: 7, raise: 6}
11
+ until_args = {message: 5}
12
+ until_blok = -> { 4 }
13
+ coffee_obj = instance_double(Coffee)
14
+ expect(Coffee).to receive(:break).with(break_args).and_return(coffee_obj)
15
+ expect(coffee_obj).to receive(:until).with(until_args).and_yield
16
+ CoffeeBreak.until(break_args.merge(until_args), &until_blok)
17
+ end
18
+ end
19
+
20
+ context 'can set and get', reset: true do
21
+ it 'default_timeout' do
22
+ CoffeeBreak.default_timeout = 0.05
23
+ expect(CoffeeBreak.default_timeout).to eq 0.05
24
+ interval = CoffeeBreak.default_interval
25
+ time = Benchmark.measure { Coffee.break(raise: false).until { false } }
26
+ expect(time.real).to be_between(0.05, 0.05 + interval * 2)
27
+ end
28
+
29
+ it 'default_interval' do
30
+ CoffeeBreak.default_interval = 0.002
31
+ expect(CoffeeBreak.default_interval).to eq 0.002
32
+ timeout = CoffeeBreak.default_timeout
33
+ counter = 0
34
+ increment_counter = -> { counter += 1; false }
35
+ Coffee.break(raise: false).until(&increment_counter)
36
+ expect(counter).to eq(timeout / 0.002).or eq(timeout / 0.002 + 1)
37
+ end
38
+
39
+ it 'default_rescues with class argument' do
40
+ CoffeeBreak.default_rescues = ArgumentError
41
+ expect(CoffeeBreak.default_rescues).to eq ArgumentError
42
+ would_raise_argument_error = -> do
43
+ Coffee.break(raise: false).until { Object.new(1) }
44
+ end
45
+ expect(would_raise_argument_error).not_to raise_error
46
+ end
47
+
48
+ it 'default_rescues with array argument' do
49
+ CoffeeBreak.default_rescues = [ArgumentError, NoMethodError]
50
+ expect(CoffeeBreak.default_rescues).to eq [ArgumentError, NoMethodError]
51
+ would_raise_no_method_error = -> do
52
+ Coffee.break(raise: false).until { Object.new.potato }
53
+ end
54
+ expect(would_raise_no_method_error).not_to raise_error
55
+ end
56
+
57
+ it 'default_raise' do
58
+ CoffeeBreak.default_raise = false
59
+ expect(CoffeeBreak.default_raise).to eq false
60
+ would_raise_timeout_error = -> do
61
+ Coffee.break.until { 2 + 2 == 5 }
62
+ end
63
+ expect(would_raise_timeout_error).not_to raise_error
64
+ end
65
+ end
66
+
67
+ describe Coffee do
68
+ describe '::break' do
69
+ it 'can set the timeout' do
70
+ interval = CoffeeBreak.default_interval
71
+ coffee_break = Coffee.break(raise: false, timeout: 0.05)
72
+ time = Benchmark.measure { coffee_break.until { 2 + 2 == 5 } }
73
+ expect(time.real).to be_between(0.05, 0.05 + interval * 2)
74
+ end
75
+
76
+ it 'can set the interval' do
77
+ timeout = CoffeeBreak.default_timeout
78
+ counter = 0
79
+ increment_counter = -> { counter += 1; false }
80
+ Coffee.break(raise: false, interval: 0.002).until(&increment_counter)
81
+ expect(counter).to eq(timeout / 0.002).or eq(timeout / 0.002 + 1)
82
+ end
83
+
84
+ it 'can set the rescues with class argument' do
85
+ cb = Coffee.break(raise: false, rescues: ArgumentError)
86
+ would_raise_argument_error = -> do
87
+ cb.until { Object.new(1) }
88
+ end
89
+ expect(would_raise_argument_error).not_to raise_error
90
+ end
91
+
92
+ it 'can set the rescues with array argument' do
93
+ cb = Coffee.break(raise: false, rescues: [ArgumentError, NoMethodError])
94
+ would_raise_no_method_error = -> do
95
+ cb.until { Object.new.potato }
96
+ end
97
+ expect(would_raise_no_method_error).not_to raise_error
98
+ end
99
+
100
+ it 'can set the raise' do
101
+ would_raise_timeout_error = -> do
102
+ Coffee.break(raise: false).until { 2 + 2 == 5 }
103
+ end
104
+ expect(would_raise_timeout_error).not_to raise_error
105
+ end
106
+ end
107
+
108
+ describe '#until' do
109
+ context 'when the block evaluates to a truthy value' do
110
+ it 'returns the result' do
111
+ expect(Coffee.break.until { 2 + 2 == 4 }).to be true
112
+ expect(Coffee.break.until { 'truthy' }).to eq 'truthy'
113
+ end
114
+
115
+ it 'returns immediately' do
116
+ time = Benchmark.measure { Coffee.break(timeout: 1).until { true } }
117
+ expect(time.real).to be < 0.001
118
+ end
119
+
120
+ it 'evaluates the block at least once' do
121
+ counter = 0
122
+ expect(Coffee.break(timeout: -1).until { counter += 1 }).to eq 1
123
+ expect(counter).to eq 1
124
+ end
125
+ end
126
+
127
+ context 'when the block evaluates to a falsey value' do
128
+ it 'raises a TimeoutError with a default error message by default' do
129
+ error = CoffeeBreak::TimeoutError
130
+ message = "Timed out after #{CoffeeBreak::default_timeout} seconds"
131
+ with_falsey_block = -> { Coffee.break.until { 2 + 2 == 5 } }
132
+ expect(with_falsey_block).to raise_error(error, message)
133
+ end
134
+
135
+ it 'can report a custom error message when raise is true' do
136
+ custom_message = 'This is a custom message'
137
+ timeout = -> { Coffee.break.until(message: custom_message) { false } }
138
+ expect(timeout).to raise_error(custom_message)
139
+ end
140
+
141
+ it 'can warn with a custom message when raise is false' do
142
+ custom_message = 'This is a custom message'
143
+ timeout = -> do
144
+ Coffee.break(raise: false).until(message: custom_message) { false }
145
+ end
146
+ expect(timeout).to output(/#{custom_message}/).to_stderr
147
+ end
148
+
149
+ it 'does not warn by default' do
150
+ timeout = -> { Coffee.break(raise: false).until { false } }
151
+ expect(timeout).not_to output.to_stderr
152
+ end
153
+
154
+ it 'returns the result if configured not to raise error on timeout' do
155
+ coffee_break = Coffee.break(raise: false)
156
+ expect(coffee_break.until { 2 + 2 == 5 }).to be false
157
+ expect(coffee_break.until { nil }).to be nil
158
+ end
159
+
160
+ it 'continues evaluating the block until timeout' do
161
+ interval = CoffeeBreak.default_interval
162
+ coffee_break = Coffee.break(raise: false, timeout: 0.05)
163
+ time = Benchmark.measure { coffee_break.until { 2 + 2 == 5 } }
164
+ expect(time.real).to be_between(0.05, 0.05 + interval * 2)
165
+ end
166
+
167
+ it 'can rescue errors during wait and then raise TimeoutError' do
168
+ rescue_and_raise = -> do
169
+ Coffee.break(rescues: RuntimeError).until { raise }
170
+ end
171
+ expect(rescue_and_raise).to raise_error(CoffeeBreak::TimeoutError)
172
+ end
173
+
174
+ it 'evaluates the block at least once' do
175
+ counter = 0
176
+ negative_timer = -> do
177
+ Coffee.break(timeout: -1).until { counter += 1; false }
178
+ end
179
+ expect(negative_timer).to raise_error(CoffeeBreak::TimeoutError)
180
+ expect(counter).to eq 1
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'benchmark'
3
+ require 'coffee_break'
4
+ include CoffeeBreak::Waiter
5
+ CoffeeBreak::DEFAULT[:interval] = 0.001
6
+ CoffeeBreak::DEFAULT[:timeout] = 0.01
7
+ RSpec.configure do |config|
8
+ config.before(:example, reset: true) do
9
+ @defaults = CoffeeBreak::DEFAULT.dup
10
+ end
11
+
12
+ config.after(:example, reset: true) do
13
+ @defaults.each { |k,v| CoffeeBreak::DEFAULT[k] = v }
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coffee_break
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Cohen Carlisle
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-01-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.10'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.10'
69
+ description:
70
+ email:
71
+ - cohen.carlisle@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - coffee_break.gemspec
86
+ - lib/coffee_break.rb
87
+ - lib/coffee_break/default.rb
88
+ - lib/coffee_break/errors.rb
89
+ - lib/coffee_break/version.rb
90
+ - lib/coffee_break/waiter/coffee.rb
91
+ - spec/coffee_break_spec.rb
92
+ - spec/spec_helper.rb
93
+ homepage: https://github.com/Cohen-Carlisle/coffee_break
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.5.1
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: A gem to handle waiting until a condition is true
117
+ test_files: []