pry-rescue 0.3 → 0.4
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/README.md +7 -29
- data/lib/pry-rescue/commands.rb +2 -2
- data/lib/pry-rescue/core_ext.rb +38 -12
- data/lib/pry-rescue.rb +13 -1
- data/pry-rescue.gemspec +1 -1
- data/spec/core_ext_spec.rb +96 -0
- metadata +3 -2
data/README.md
CHANGED
@@ -1,38 +1,18 @@
|
|
1
1
|
|
2
|
-
**pry-rescue**
|
3
|
-
|
4
|
-
Installation
|
5
|
-
============
|
6
|
-
|
7
|
-
Either `gem install pry-rescue`, or add it to the development section of your Gemfile:
|
8
|
-
|
9
|
-
```ruby
|
10
|
-
source :rubygems
|
11
|
-
group :development do
|
12
|
-
gem 'pry-rescue'
|
13
|
-
gem 'pry-stack_explorer' # if you're using MRI 1.9 and you want it to be awesome.
|
14
|
-
end
|
15
|
-
```
|
2
|
+
**pry-rescue** super-fast, painless, debugging for the (ruby) masses. (See [Pry to the rescue!](https://cirw.in/blog/pry-to-the-rescue))
|
16
3
|
|
17
4
|
Usage
|
18
5
|
=====
|
19
6
|
|
20
|
-
|
21
|
-
|
22
|
-
Wrap an entire script
|
23
|
-
---------------------
|
24
|
-
|
25
|
-
Use the launcher script:
|
7
|
+
First `gem install pry-rescue pry-stack_explorer`. Then run your program with `rescue`
|
8
|
+
instead of `ruby`:
|
26
9
|
|
27
10
|
```
|
28
11
|
rescue <script.rb> [arguments..]
|
29
12
|
```
|
30
13
|
|
31
|
-
|
32
|
-
|
33
|
-
In development, wrap your code in `Pry::rescue{ }`; then any exceptions that are raised
|
34
|
-
but not rescued will open a pry session. This is particularly useful for debugging
|
35
|
-
servers and other long-running processes.
|
14
|
+
If you want more fine-grained control over which parts of your code are rescued, you can
|
15
|
+
also use the block form:
|
36
16
|
|
37
17
|
```ruby
|
38
18
|
require 'pry-rescue'
|
@@ -47,7 +27,6 @@ Pry.rescue do
|
|
47
27
|
test
|
48
28
|
end
|
49
29
|
```
|
50
|
-
|
51
30
|
This will land you in a pry-session:
|
52
31
|
|
53
32
|
```
|
@@ -119,9 +98,8 @@ you can get a better idea of why your function ended up in a bad state. Run
|
|
119
98
|
Known bugs
|
120
99
|
==========
|
121
100
|
|
122
|
-
Occasionally, when using ruby-1.8
|
123
|
-
|
124
|
-
expect.
|
101
|
+
Occasionally, when using ruby-1.8 the value for `self` will be incorrect. You will still
|
102
|
+
be able to access local variables, but calling methods will not work as you expect.
|
125
103
|
|
126
104
|
On rbx we are unable to intercept some exceptions thrown from inside the C++ VM, for
|
127
105
|
example the ZeroDivisionError in `1 / 0`.
|
data/lib/pry-rescue/commands.rb
CHANGED
@@ -31,7 +31,7 @@ Pry::Commands.create_command "cd-cause", "Move to the previously raised exceptio
|
|
31
31
|
BANNER
|
32
32
|
|
33
33
|
def process
|
34
|
-
raised = target.eval("_raised_ rescue nil")
|
34
|
+
raised = target.eval("_raised_.dup rescue nil")
|
35
35
|
raise Pry::CommandError, "cd-cause only works in a pry session created by Pry::rescue{}" unless raised
|
36
36
|
raised.pop
|
37
37
|
|
@@ -60,6 +60,6 @@ Pry::Commands.create_command "try-again", "Re-try the code that caused this exce
|
|
60
60
|
BANNER
|
61
61
|
|
62
62
|
def process
|
63
|
-
|
63
|
+
throw :try_again
|
64
64
|
end
|
65
65
|
end
|
data/lib/pry-rescue/core_ext.rb
CHANGED
@@ -10,21 +10,47 @@ class Pry
|
|
10
10
|
# @return [Object] The return value of the block
|
11
11
|
def self.rescue(&block)
|
12
12
|
raised = []
|
13
|
+
(@raised_stack ||= []) << raised
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
raised
|
17
|
-
|
18
|
-
|
15
|
+
loop do
|
16
|
+
catch(:try_again) do
|
17
|
+
raised.clear
|
18
|
+
begin
|
19
|
+
return Interception.listen(block) do |exception, binding|
|
20
|
+
if defined?(PryStackExplorer)
|
21
|
+
raised << [exception, binding.callers]
|
22
|
+
else
|
23
|
+
raised << [exception, Array(binding)]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
rescue Exception => e
|
27
|
+
PryRescue.enter_exception_context(raised)
|
28
|
+
raise e
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
32
|
+
ensure
|
33
|
+
@raised_stack.pop
|
34
|
+
end
|
21
35
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
36
|
+
# Start a pry session on an exception that you rescued within a Pry::rescue{ }.
|
37
|
+
#
|
38
|
+
# @example
|
39
|
+
# Pry::rescue do
|
40
|
+
# begin
|
41
|
+
# raise "foo"
|
42
|
+
# rescue => e
|
43
|
+
# Pry::rescued(e)
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
def self.rescued(e=$!)
|
48
|
+
raise "Tried to inspect rescued exception outside Pry::rescue{ } block" unless @raised_stack.any?
|
49
|
+
|
50
|
+
raised = @raised_stack.last.dup
|
51
|
+
raised.pop until raised.empty? || raised.last.first == e
|
52
|
+
raise "Tried to inspect an exception that was not raised in this Pry::rescue{ } block" unless raised.any?
|
53
|
+
|
54
|
+
PryRescue.enter_exception_context(raised)
|
29
55
|
end
|
30
56
|
end
|
data/lib/pry-rescue.rb
CHANGED
@@ -17,10 +17,16 @@ class PryRescue
|
|
17
17
|
# @param [Exception] exception The exception.
|
18
18
|
# @param [Array<Binding>] bindings The call stack.
|
19
19
|
def enter_exception_context(raised)
|
20
|
-
exception, bindings = raised.last
|
21
20
|
|
21
|
+
exception, bindings = raised.last
|
22
22
|
prune_call_stack!(bindings)
|
23
23
|
|
24
|
+
if bindings.size > 1 && internal_binding?(bindings.first)
|
25
|
+
raised.pop
|
26
|
+
exception, bindings = raised.last
|
27
|
+
prune_call_stack!(bindings)
|
28
|
+
end
|
29
|
+
|
24
30
|
if defined?(PryStackExplorer)
|
25
31
|
pry :call_stack => bindings, :hooks => pry_hooks(exception, raised)
|
26
32
|
else
|
@@ -30,6 +36,12 @@ class PryRescue
|
|
30
36
|
|
31
37
|
private
|
32
38
|
|
39
|
+
# Is this binding within pry-rescue?
|
40
|
+
def internal_binding?(binding)
|
41
|
+
binding.eval("__FILE__").start_with?(File.expand_path('../../lib', __FILE__)) ||
|
42
|
+
binding.eval("__FILE__").start_with?(File.expand_path('../../bin', __FILE__))
|
43
|
+
end
|
44
|
+
|
33
45
|
# Define the :before_session hook for the Pry instance.
|
34
46
|
# This ensures that the `_ex_` and `_raised_` sticky locals are
|
35
47
|
# properly set.
|
data/pry-rescue.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'pry-rescue'
|
3
|
-
s.version = '0.
|
3
|
+
s.version = '0.4'
|
4
4
|
s.summary = 'Open a pry session on any unhandled exceptions'
|
5
5
|
s.description = 'Allows you to wrap code in Pry::rescue{ } to open a pry session at any unhandled exceptions'
|
6
6
|
s.homepage = 'https://github.com/ConradIrwin/pry-rescue'
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.expand_path('../../lib/pry-rescue.rb', __FILE__)
|
2
|
+
|
3
|
+
describe 'Pry.rescue' do
|
4
|
+
it 'should call PryRescue.enter_exception_context' do
|
5
|
+
lambda{
|
6
|
+
PryRescue.should_receive(:enter_exception_context).once
|
7
|
+
Pry::rescue{ raise "foobar" }
|
8
|
+
}.should raise_error(/foobar/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should retry on try-again" do
|
12
|
+
@called = 0
|
13
|
+
PryRescue.should_receive(:enter_exception_context).once{ throw :try_again }
|
14
|
+
Pry::rescue do
|
15
|
+
@called += 1
|
16
|
+
raise "foobar" if @called == 1
|
17
|
+
end
|
18
|
+
@called.should == 2
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should try-again from innermost block" do
|
22
|
+
@outer = @inner = 0
|
23
|
+
PryRescue.should_receive(:enter_exception_context).once{ throw :try_again }
|
24
|
+
Pry::rescue do
|
25
|
+
@outer += 1
|
26
|
+
Pry::rescue do
|
27
|
+
@inner += 1
|
28
|
+
raise "oops" if @inner == 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
@outer.should == 1
|
33
|
+
@inner.should == 2
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should clear out exceptions between retrys at the same level" do
|
37
|
+
@outer = @inner = 0
|
38
|
+
PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
|
39
|
+
PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
|
40
|
+
Pry::rescue do
|
41
|
+
@outer += 1
|
42
|
+
Pry::rescue do
|
43
|
+
@inner += 1
|
44
|
+
raise "oops" if @inner <= 2
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should preserve exceptions between retrys at a higher level" do
|
50
|
+
@outer = @inner = 0
|
51
|
+
PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
|
52
|
+
PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
|
53
|
+
PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 3; throw :try_again }
|
54
|
+
Pry::rescue do
|
55
|
+
@outer += 1
|
56
|
+
Pry::rescue do
|
57
|
+
@inner += 1
|
58
|
+
raise "oops" if @inner <= 2
|
59
|
+
end
|
60
|
+
raise "foops" if @outer == 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "Pry.rescued" do
|
66
|
+
|
67
|
+
it "should raise an error if used outwith Pry::rescue" do
|
68
|
+
begin
|
69
|
+
raise "foo"
|
70
|
+
rescue => e
|
71
|
+
lambda{
|
72
|
+
Pry.rescued(e)
|
73
|
+
}.should raise_error(/outside Pry::rescue/)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should raise an error if used on an exception not raised" do
|
78
|
+
Pry::rescue do
|
79
|
+
lambda{
|
80
|
+
Pry.rescued(RuntimeError.new("foo").exception)
|
81
|
+
}.should raise_error(/not raised/)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should call Pry.enter_exception_context" do
|
86
|
+
Pry::rescue do
|
87
|
+
begin
|
88
|
+
raise "foo"
|
89
|
+
rescue => e
|
90
|
+
PryRescue.should_receive(:enter_exception_context).once
|
91
|
+
Pry::rescued(e)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pry-rescue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.4'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-08-
|
14
|
+
date: 2012-08-26 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: interception
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- lib/pry-rescue/commands.rb
|
52
52
|
- lib/pry-rescue/core_ext.rb
|
53
53
|
- pry-rescue.gemspec
|
54
|
+
- spec/core_ext_spec.rb
|
54
55
|
homepage: https://github.com/ConradIrwin/pry-rescue
|
55
56
|
licenses: []
|
56
57
|
post_install_message:
|