return_bang 1.0 → 1.1

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.
data.tar.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- 9LC��M}
2
- ߁Z�z��ܦ/⊢V��U�^�׭����בlRg�-�$��6���)�G(�s�i�
1
+ 7d+��*"��������N֝��W4�����YH�<!���־�b��5
2
+ k���Sκ������O�4���@M>�~r��e1S��F[y_�Ɓ���e8ӊ�z���� ޒ򔦛��:���{Ϥ�/R�����I��O`�������S�\
3
+ �d���6E<Tr&�d����"\�m�P�C4����|���V��^����e����N��Ty�w���$�2<$�w�|��dJ�)]A8�)�����{?��
@@ -1,5 +1,12 @@
1
+ === 1.1 / 2012-04-01
2
+
3
+ * Minor enhancements
4
+ * Added raise! to raise exceptions
5
+ * Added rescue! to rescue exceptions raised
6
+ * Added ensure! to always execute a block of code to perform cleanup
7
+
1
8
  === 1.0 / 2011-12-20
2
9
 
3
- * Major enhancements
10
+ * Major enhancement
4
11
  * Birthday!
5
12
 
@@ -6,16 +6,26 @@ bugs :: https://github.com/drbrain/return_bang/issues
6
6
 
7
7
  == Description
8
8
 
9
- return_bang implements non-local exits from methods. Use return_bang to exit
10
- back to a processing loop from deeply nested code, or just to confound your
11
- enemies *and* your friends! What could possibly go wrong?
9
+ return_bang implements non-local exits for methods. As a bonus, you also get
10
+ exception handling that ignores standard Ruby's inflexible begin; rescue;
11
+ ensure; end syntax.
12
+
13
+ Use return_bang to exit back to a processing loop from deeply nested code, or
14
+ just to confound your enemies *and* your friends! What could possibly go
15
+ wrong?
12
16
 
13
17
  == Features
14
18
 
15
19
  * Implements non-local exits for methods
16
20
  * Nestable
17
21
  * Named and stack-based exit points, go exactly where you need to be
18
- * Ignores pesky ensure blocks for when you really, really need to return
22
+ * Full exception handling support through raise!, rescue! and ensure!
23
+ * Ignores pesky ensure, rescue and require blocks for when you really, really
24
+ need to return
25
+
26
+ == Problems
27
+
28
+ * Not enough use of continuations
19
29
 
20
30
  == Synopsis
21
31
 
data/Rakefile CHANGED
@@ -5,14 +5,14 @@ require 'hoe'
5
5
 
6
6
  Hoe.plugin :minitest
7
7
  Hoe.plugin :git
8
+ Hoe.plugin :travis
8
9
 
9
10
  Hoe.spec 'return_bang' do
10
11
  developer 'Eric Hodel', '[email protected]'
11
12
 
12
13
  rdoc_locations << 'docs.seattlerb.org:/data/www/docs.seattlerb.org/return_bang/'
13
14
 
14
- self.readme_file = 'README.rdoc'
15
- self.extra_rdoc_files << 'README.rdoc'
15
+ spec_extras['required_ruby_version'] = '>= 1.9.2'
16
16
  end
17
17
 
18
18
  # vim: syntax=ruby
@@ -1,59 +1,78 @@
1
- begin
2
- require 'continuation'
3
- rescue LoadError
4
- # in 1.8 it's built-in
5
- end
1
+ require 'continuation'
6
2
 
7
3
  ##
8
4
  # ReturnBang is allows you to perform non-local exits from your methods. One
9
5
  # potential use of this is in a web framework so that a framework-provided
10
6
  # utility methods can jump directly back to the request loop.
11
7
  #
12
- # return_here is used to designate where execution should be resumed. Return
13
- # points may be arbitrarily nested. #return! resumes at the previous resume
14
- # point, #return_to returns to a named return point.
8
+ # Since providing just non-local exits is insufficient for modern Ruby
9
+ # development, full exception handling support is also provided via #raise!,
10
+ # #rescue! and #ensure!. This exception handling support completely bypasses
11
+ # Ruby's strict <tt>begin; rescue; ensure; return</tt> handling.
15
12
  #
16
13
  # require 'return_bang' gives you a module you may include only in your
17
14
  # application or library code. require 'return_bang/everywhere' includes
18
15
  # ReturnBang in Object, so it is only recommended for application code use.
19
16
  #
20
- # Example:
17
+ # == Methods
18
+ #
19
+ # return_here is used to designate where execution should be resumed. Return
20
+ # points may be arbitrarily nested. #return! resumes at the previous resume
21
+ # point, #return_to returns to a named return point.
22
+ #
23
+ # #raise! is used to indicate an exceptional situation has occurred and you
24
+ # would like to skip the rest of the execution.
25
+ #
26
+ # #rescue! is used to rescue exceptions if you have a way to handle them.
27
+ #
28
+ # #ensure! is used when you need to perform cleanup where an exceptional
29
+ # situation may occur.
30
+ #
31
+ # == Example
21
32
  #
22
33
  # include ReturnBang
23
34
  #
24
35
  # def framework_loop
25
36
  # loop do
26
- # # setup code
27
- #
28
37
  # return_here do
29
- # user_code
30
- # end
38
+ # # setup this request
31
39
  #
32
- # # resume execution here
33
- # end
34
- # end
40
+ # ensure! do
41
+ # # clean up this request
42
+ # end
43
+ #
44
+ # rescue! FrameworkError do
45
+ # # display framework error
46
+ # end
35
47
  #
36
- # def render_error_and_return message
37
- # # generate error
48
+ # rescue! do
49
+ # # display application error
50
+ # end
38
51
  #
39
- # return!
52
+ # user_code
53
+ # end
54
+ # end
40
55
  # end
41
56
  #
42
57
  # def user_code
43
58
  # user_utility_method
44
- # # these lines never reached
45
- # # ...
59
+ #
60
+ # other_condition = some_more code
61
+ #
62
+ # return! if other_condition
63
+ #
64
+ # # rest of user method
46
65
  # end
47
66
  #
48
67
  # def user_utility_method
49
- # render_error_and_return "blah" if some_condition
50
- # # these lines never reached
51
- # # ...
68
+ # raise! "there was an error" if some_condition
69
+ #
70
+ # # rest of utility method
52
71
  # end
53
72
 
54
73
  module ReturnBang
55
74
 
56
- VERSION = '1.0'
75
+ VERSION = '1.1'
57
76
 
58
77
  ##
59
78
  # Raised when attempting to return! when you haven't registered a location
@@ -63,31 +82,185 @@ module ReturnBang
63
82
  class NonLocalJumpError < StandardError
64
83
  end
65
84
 
85
+ def _make_exception args # :nodoc:
86
+ case args.length
87
+ when 0 then
88
+ if exception = Thread.current[:current_exception] then
89
+ exception
90
+ else
91
+ RuntimeError.new
92
+ end
93
+ when 1 then # exception or string
94
+ arg = args.first
95
+
96
+ case arg = args.first
97
+ when Class then
98
+ unless Exception >= arg then
99
+ raise TypeError,
100
+ "exception class/object expected (not #{arg.inspect})"
101
+ end
102
+ arg.new
103
+ else
104
+ RuntimeError.new arg
105
+ end
106
+ when 2 then # exception, string
107
+ klass, message = args
108
+ klass.new message
109
+ else
110
+ raise ArgumentError, 'too many arguments to raise!'
111
+ end
112
+ end
113
+
114
+ ##
115
+ # Executes the ensure blocks in +frames+ in the correct order.
116
+
117
+ def _return_bang_cleanup frames # :nodoc:
118
+ chunked = frames.chunk do |type,|
119
+ type
120
+ end
121
+
122
+ chunked.reverse_each do |type, chunk_frames|
123
+ case type
124
+ when :ensure then
125
+ chunk_frames.each do |_, block|
126
+ block.call
127
+ end
128
+ when :rescue then
129
+ if exception = Thread.current[:current_exception] then
130
+ frame = chunk_frames.find do |_, block, objects|
131
+ objects.any? do |object|
132
+ object === exception
133
+ end
134
+ end
135
+
136
+ next unless frame
137
+
138
+ # rebuild stack since we've got a handler for the exception.
139
+ unexecuted = frames[0, frames.index(frame) - 1]
140
+ _return_bang_stack.concat unexecuted if unexecuted
141
+
142
+ _, handler, = frame
143
+ handler.call exception
144
+
145
+ return # the exception was handled, don't continue up the stack
146
+ end
147
+ when :return then
148
+ # ignore
149
+ else
150
+ raise "[bug] unknown return_bang frame type #{type}"
151
+ end
152
+ end
153
+ end
154
+
66
155
  def _return_bang_names # :nodoc:
67
156
  Thread.current[:return_bang_names] ||= {}
68
157
  end
69
158
 
70
- if {}.respond_to? :key then # 1.9
71
- def _return_bang_pop # :nodoc:
72
- return_point = _return_bang_stack.pop
159
+ def _return_bang_pop # :nodoc:
160
+ frame = _return_bang_stack.pop
161
+
162
+ _return_bang_names.delete _return_bang_names.key _return_bang_stack.length
163
+
164
+ frame
165
+ end
166
+
167
+ def _return_bang_stack # :nodoc:
168
+ Thread.current[:return_bang_stack] ||= []
169
+ end
170
+
171
+ ##
172
+ # Unwinds the stack to +continuation+ including trimming the stack above the
173
+ # continuation, removing named return_heres that can't be reached and
174
+ # executing any ensures in the trimmed stack.
73
175
 
74
- _return_bang_names.delete _return_bang_names.key _return_bang_stack.length
176
+ def _return_bang_unwind_to continuation # :nodoc:
177
+ found = false
75
178
 
76
- return_point
179
+ frames = _return_bang_stack.select do |_, block|
180
+ found || found = block == continuation
77
181
  end
78
- else # 1.8
79
- def _return_bang_pop # :nodoc:
80
- return_point = _return_bang_stack.pop
81
- value = _return_bang_stack.length
82
182
 
83
- _return_bang_names.delete _return_bang_names.index value
183
+ start = _return_bang_stack.length - frames.length
184
+
185
+ _return_bang_stack.slice! start, frames.length
84
186
 
85
- return_point
187
+ frames.each_index do |index|
188
+ offset = start + index
189
+
190
+ _return_bang_names.delete _return_bang_names.key offset
86
191
  end
192
+
193
+ _return_bang_cleanup frames
87
194
  end
88
195
 
89
- def _return_bang_stack # :nodoc:
90
- Thread.current[:return_bang_stack] ||= []
196
+ ##
197
+ # Adds an ensure block that will be run when exiting this return_here block.
198
+ #
199
+ # ensure! blocks run in the order defined and can be added at any time. If
200
+ # an exception is raised before an ensure! block is encountered, that block
201
+ # will not be executed.
202
+ #
203
+ # Example:
204
+ #
205
+ # return_here do
206
+ # ensure! do
207
+ # # this ensure! will be executed
208
+ # end
209
+ #
210
+ # raise! "uh-oh!"
211
+ #
212
+ # ensure! do
213
+ # # this ensure! will not be executed
214
+ # end
215
+ # end
216
+
217
+ def ensure! &block
218
+ _return_bang_stack.push [:ensure, block]
219
+ end
220
+
221
+ ##
222
+ # Raises an exception like Kernel#raise.
223
+ #
224
+ # ensure! blocks and rescue! exception handlers will be run as the exception
225
+ # is propagated up the stack.
226
+
227
+ def raise! *args
228
+ Thread.current[:current_exception] = _make_exception args
229
+
230
+ type, = _return_bang_stack.first
231
+
232
+ _, final = _return_bang_stack.shift if type == :return
233
+
234
+ frames = _return_bang_stack.dup
235
+
236
+ _return_bang_stack.clear
237
+
238
+ _return_bang_cleanup frames
239
+
240
+ final.call if final
241
+ end
242
+
243
+ ##
244
+ # Rescues +exceptions+ raised by raise! and yields the exception caught to
245
+ # the block given.
246
+ #
247
+ # If no exceptions are given, StandardError is rescued (like the rescue
248
+ # keyword).
249
+ #
250
+ # Example:
251
+ #
252
+ # return_here do
253
+ # rescue! do |e|
254
+ # puts "handled exception #{e.class}: #{e}"
255
+ # end
256
+ #
257
+ # raise! "raising an exception"
258
+ # end
259
+
260
+ def rescue! *exceptions, &block
261
+ exceptions = [StandardError] if exceptions.empty?
262
+
263
+ _return_bang_stack.push [:rescue, block, exceptions]
91
264
  end
92
265
 
93
266
  ##
@@ -99,7 +272,13 @@ module ReturnBang
99
272
  raise NonLocalJumpError, 'nowhere to return to' if
100
273
  _return_bang_stack.empty?
101
274
 
102
- _return_bang_pop.call value
275
+ _, continuation, = _return_bang_stack.reverse.find do |type,|
276
+ type == :return
277
+ end
278
+
279
+ _return_bang_unwind_to continuation
280
+
281
+ continuation.call value
103
282
  end
104
283
 
105
284
  ##
@@ -112,15 +291,21 @@ module ReturnBang
112
291
 
113
292
  value = callcc do |cc|
114
293
  _return_bang_names[name] = _return_bang_stack.length if name
115
- _return_bang_stack.push cc
294
+ _return_bang_stack.push [:return, cc]
116
295
 
117
296
  begin
118
297
  yield
119
298
  ensure
120
- _return_bang_pop
299
+ _return_bang_unwind_to cc
121
300
  end
122
301
  end
123
302
 
303
+ if exception = Thread.current[:current_exception] then
304
+ Thread.current[:current_exception] = nil
305
+
306
+ raise exception
307
+ end
308
+
124
309
  # here is where the magic happens
125
310
  unwind_to = Thread.current[:unwind_to]
126
311
 
@@ -13,6 +13,324 @@ class TestReturnBang < MiniTest::Unit::TestCase
13
13
  def teardown
14
14
  assert_empty _return_bang_stack
15
15
  assert_empty _return_bang_names
16
+ assert_nil Thread.current[:current_exception]
17
+ end
18
+
19
+ def test__make_exception
20
+ e = _make_exception []
21
+
22
+ assert_instance_of RuntimeError, e
23
+ end
24
+
25
+ def test__make_exception_class
26
+ e = _make_exception [StandardError]
27
+
28
+ assert_instance_of StandardError, e
29
+ end
30
+
31
+ def test__make_exception_class_message
32
+ e = _make_exception [StandardError, 'hello']
33
+
34
+ assert_instance_of StandardError, e
35
+
36
+ assert_equal 'hello', e.message
37
+ end
38
+
39
+ def test__make_exception_current_exception
40
+ expected = ArgumentError.new
41
+ Thread.current[:current_exception] = expected
42
+
43
+ e = _make_exception []
44
+
45
+ assert_same expected, e
46
+ ensure
47
+ Thread.current[:current_exception] = nil
48
+ end
49
+
50
+ def test__make_exception_message
51
+ e = _make_exception %w[hello]
52
+
53
+ assert_instance_of RuntimeError, e
54
+ assert_equal 'hello', e.message
55
+ end
56
+
57
+ def test__make_exception_non_Exception
58
+ e = assert_raises TypeError do
59
+ _make_exception [String]
60
+ end
61
+
62
+ assert_equal 'exception class/object expected (not String)', e.message
63
+ end
64
+
65
+ def test_ensure_bang
66
+ ensured = false
67
+
68
+ return_here do
69
+ ensure! do
70
+ ensured = true
71
+ end
72
+ end
73
+
74
+ assert ensured, 'ensured was not executed'
75
+ end
76
+
77
+ def test_ensure_bang_multiple
78
+ ensured = []
79
+
80
+ return_here do
81
+ ensure! do
82
+ ensured << 1
83
+ end
84
+ ensure! do
85
+ ensured << 2
86
+ end
87
+ end
88
+
89
+ assert_equal [1, 2], ensured
90
+ end
91
+
92
+ def test_ensure_bang_multiple_return
93
+ ensured = []
94
+
95
+ return_here do
96
+ ensure! do
97
+ ensured << 1
98
+ end
99
+ ensure! do
100
+ ensured << 2
101
+ end
102
+
103
+ return!
104
+ end
105
+
106
+ assert_equal [1, 2], ensured
107
+ end
108
+
109
+ def test_ensure_bang_nest
110
+ ensured = []
111
+
112
+ return_here do
113
+ ensure! do
114
+ ensured << 2
115
+ end
116
+ return_here do
117
+ ensure! do
118
+ ensured << 1
119
+ end
120
+ end
121
+ end
122
+
123
+ assert_equal [1, 2], ensured
124
+ end
125
+
126
+ def test_ensure_bang_nest_raise
127
+ ensured = []
128
+
129
+ assert_raises RuntimeError do
130
+ return_here do
131
+ ensure! do
132
+ ensured << 2
133
+ end
134
+ return_here do
135
+ ensure! do
136
+ ensured << 1
137
+ end
138
+
139
+ raise!
140
+ end
141
+ end
142
+ end
143
+
144
+ assert_equal [1, 2], ensured
145
+ end
146
+
147
+ def test_ensure_bang_raise_after
148
+ ensured = false
149
+
150
+ assert_raises RuntimeError do
151
+ return_here do
152
+ ensure! do
153
+ ensured = true
154
+ end
155
+
156
+ refute ensured, 'ensure! executed too soon'
157
+
158
+ raise!
159
+ end
160
+ end
161
+
162
+ assert ensured, 'ensure! not executed'
163
+ end
164
+
165
+ def test_ensure_bang_raise_before
166
+ ensured = false
167
+
168
+ assert_raises RuntimeError do
169
+ return_here do
170
+ raise!
171
+
172
+ ensure! do
173
+ ensured = true
174
+ end
175
+ end
176
+ end
177
+
178
+ refute ensured, 'ensure! must not be executed'
179
+ end
180
+
181
+ def test_ensure_bang_raise_in_ensure
182
+ ensured = []
183
+
184
+ assert_raises RuntimeError do
185
+ return_here do
186
+ ensure! do
187
+ ensured << 2
188
+ end
189
+
190
+ return_here do
191
+ ensure! do
192
+ ensured << 1
193
+ raise!
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ assert_equal [1, 2], ensured
200
+ end
201
+
202
+ def test_raise_bang
203
+ e = assert_raises RuntimeError do
204
+ return_here do
205
+ raise! 'hello'
206
+ end
207
+ end
208
+
209
+ assert_equal 'hello', e.message
210
+ end
211
+
212
+ def test_raise_bang_ignore_rescue
213
+ assert_raises RuntimeError do
214
+ return_here do
215
+ begin
216
+ raise! 'hello'
217
+ rescue
218
+ flunk 'must not execute rescue body'
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ def test_raise_bang_re_raise
225
+ rescues = []
226
+
227
+ assert_raises ArgumentError do
228
+ return_here do
229
+ rescue! do
230
+ rescues << 2
231
+ end
232
+
233
+ return_here do
234
+ rescue! do
235
+ rescues << 1
236
+
237
+ raise!
238
+ end
239
+
240
+ raise! ArgumentError, 'hello'
241
+ end
242
+ end
243
+ end
244
+
245
+ assert_equal [1, 2], rescues
246
+ end
247
+
248
+ def test_rescue_bang
249
+ rescued = false
250
+
251
+ assert_raises RuntimeError do
252
+ return_here do
253
+ rescue! do
254
+ rescued = true
255
+ end
256
+
257
+ raise! 'hello'
258
+ end
259
+ end
260
+
261
+ assert rescued, 'rescue not executed'
262
+ end
263
+
264
+ def test_rescue_bang_default
265
+ rescued = false
266
+
267
+ assert_raises Exception do
268
+ return_here do
269
+ rescue! do
270
+ rescued = true
271
+ end
272
+
273
+ raise! Exception
274
+ end
275
+ end
276
+
277
+ refute rescued, 'rescue must default to StandardError'
278
+ end
279
+
280
+ def test_rescue_bang_exceptions
281
+ rescued = false
282
+ ensured = true
283
+
284
+ return_here do
285
+ rescue! do
286
+ rescued = true
287
+ end
288
+
289
+ ensure! do
290
+ ensured = true
291
+ end
292
+
293
+ return!
294
+ end
295
+
296
+ refute rescued, 'rescue! must not execute'
297
+ assert ensured, 'ensure! must execute'
298
+ end
299
+
300
+ def test_rescue_bang_multiple
301
+ rescued = false
302
+
303
+ assert_raises TypeError do
304
+ return_here do
305
+ rescue! ArgumentError, TypeError do
306
+ rescued = true
307
+ end
308
+
309
+ raise! TypeError
310
+ end
311
+ end
312
+
313
+ assert rescued, 'rescue not executed'
314
+ end
315
+
316
+ def test_rescue_bang_type
317
+ rescued = false
318
+
319
+ assert_raises StandardError do
320
+ return_here do
321
+ rescue! StandardError do
322
+ rescued = true
323
+ end
324
+
325
+ rescue! RuntimeError do
326
+ flunk 'wrong rescue! executed'
327
+ end
328
+
329
+ raise! StandardError
330
+ end
331
+ end
332
+
333
+ assert rescued, 'StandardError exception not rescued'
16
334
  end
17
335
 
18
336
  def test_return_bang_no_return_here
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: return_bang
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 0
9
- version: "1.0"
8
+ - 1
9
+ version: "1.1"
10
10
  platform: ruby
11
11
  authors:
12
12
  - Eric Hodel
@@ -15,9 +15,9 @@ bindir: bin
15
15
  cert_chain:
16
16
  - |
17
17
  -----BEGIN CERTIFICATE-----
18
- MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
18
+ MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
19
19
  YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
20
- ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
20
+ ZXQwHhcNMTIwMjI4MTc1NDI1WhcNMTMwMjI3MTc1NDI1WjBBMRAwDgYDVQQDDAdk
21
21
  cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
22
22
  FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
23
23
  LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
@@ -25,17 +25,18 @@ cert_chain:
25
25
  Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
26
26
  mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
27
27
  g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
28
- sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
29
- BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
30
- kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
31
- bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
32
- DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
33
- UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
34
- 14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
35
- x52qPcexcYZR7w==
28
+ sCANiQ8BAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
29
+ BBS5k4Z75VSpdM0AclG2UvzFA/VW5DAfBgNVHREEGDAWgRRkcmJyYWluQHNlZ21l
30
+ bnQ3Lm5ldDAfBgNVHRIEGDAWgRRkcmJyYWluQHNlZ21lbnQ3Lm5ldDANBgkqhkiG
31
+ 9w0BAQUFAAOCAQEAPeWzFnrcvC6eVzdlhmjUub2s6qieBkongKRDHQz5MEeQv4LS
32
+ SARnoHY+uCAVL/1xGAhmpzqQ3fJGWK9eBacW/e8E5GF9xQcV3mE1bA0WNaiDlX5j
33
+ U2aI+ZGSblqvHUCxKBHR1s7UMHsbz1saOmgdRTyPx0juJs68ocbUTeYBLWu9V4KP
34
+ zdGAG2JXO2gONg3b4tYDvpBLbry+KOX27iAJulUaH9TiTOULL4ITJVFsK0mYVqmR
35
+ Q8Tno9S3e4XGGP1ZWfLrTWEJbavFfhGHut2iMRwfC7s/YILAHNATopaJdH9DNpd1
36
+ U81zGHMUBOvz/VGT6wJwYJ3emS2nfA2NOHFfgA==
36
37
  -----END CERTIFICATE-----
37
38
 
38
- date: 2011-12-21 00:00:00 Z
39
+ date: 2012-04-01 00:00:00 Z
39
40
  dependencies:
40
41
  - !ruby/object:Gem::Dependency
41
42
  name: minitest
@@ -45,32 +46,51 @@ dependencies:
45
46
  requirements:
46
47
  - - ~>
47
48
  - !ruby/object:Gem::Version
48
- hash: 15
49
+ hash: 21
49
50
  segments:
50
51
  - 2
51
- - 6
52
- version: "2.6"
52
+ - 11
53
+ version: "2.11"
53
54
  type: :development
54
55
  version_requirements: *id001
55
56
  - !ruby/object:Gem::Dependency
56
- name: hoe
57
+ name: rdoc
57
58
  prerelease: false
58
59
  requirement: &id002 !ruby/object:Gem::Requirement
59
60
  none: false
60
61
  requirements:
61
62
  - - ~>
62
63
  - !ruby/object:Gem::Version
63
- hash: 27
64
+ hash: 19
64
65
  segments:
65
- - 2
66
- - 12
67
- version: "2.12"
66
+ - 3
67
+ - 10
68
+ version: "3.10"
68
69
  type: :development
69
70
  version_requirements: *id002
71
+ - !ruby/object:Gem::Dependency
72
+ name: hoe
73
+ prerelease: false
74
+ requirement: &id003 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ hash: 35
80
+ segments:
81
+ - 2
82
+ - 16
83
+ version: "2.16"
84
+ type: :development
85
+ version_requirements: *id003
70
86
  description: |-
71
- return_bang implements non-local exits from methods. Use return_bang to exit
72
- back to a processing loop from deeply nested code, or just to confound your
73
- enemies *and* your friends! What could possibly go wrong?
87
+ return_bang implements non-local exits for methods. As a bonus, you also get
88
+ exception handling that ignores standard Ruby's inflexible begin; rescue;
89
+ ensure; end syntax.
90
+
91
+ Use return_bang to exit back to a processing loop from deeply nested code, or
92
+ just to confound your enemies *and* your friends! What could possibly go
93
+ wrong?
74
94
  email:
75
95
76
96
  executables: []
@@ -105,10 +125,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
125
  requirements:
106
126
  - - ">="
107
127
  - !ruby/object:Gem::Version
108
- hash: 3
128
+ hash: 55
109
129
  segments:
110
- - 0
111
- version: "0"
130
+ - 1
131
+ - 9
132
+ - 2
133
+ version: 1.9.2
112
134
  required_rubygems_version: !ruby/object:Gem::Requirement
113
135
  none: false
114
136
  requirements:
@@ -121,9 +143,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
143
  requirements: []
122
144
 
123
145
  rubyforge_project: return_bang
124
- rubygems_version: 1.8.12
146
+ rubygems_version: 1.8.21
125
147
  signing_key:
126
148
  specification_version: 3
127
- summary: return_bang implements non-local exits from methods
149
+ summary: return_bang implements non-local exits for methods
128
150
  test_files:
129
151
  - test/test_return_bang.rb
metadata.gz.sig CHANGED
@@ -1,2 +1,4 @@
1
- `"t�TW��nW��G$��c�=gTV�=�z|��t"�;� ��Jv�_�X2��:����,����V��|c��xD��ܫ�s�]�}F�$�E�'uJ�{���۔Y���t������4KϞ2���E�j����u�ԕ�'U �A��y����$��ޅ
2
- 稼�F�D�!�c����9 RsJ��҇�AF�a��y�=s`O�YQ�Z�w��~�~j�otɋ[1�臼�A��[�a_�`
1
+ V���Ɗ`�`u�LN]n��ԙ�
2
+ 1��j%>��
3
+ p�-ZyQ��
4
+ �*�o�辵�2�ϸg�_���Q��]�
OSZAR »