pry-rescue 0.5 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rescue +1 -1
- data/lib/pry-rescue.rb +70 -19
- data/pry-rescue.gemspec +1 -1
- data/spec/fixtures/coderay.rb +3 -0
- data/spec/fixtures/simple.rb +1 -0
- data/spec/fixtures/uri.rb +2 -0
- data/spec/pry_rescue_spec.rb +70 -0
- metadata +5 -1
data/bin/rescue
CHANGED
data/lib/pry-rescue.rb
CHANGED
@@ -18,28 +18,85 @@ class PryRescue
|
|
18
18
|
# @param [Array<Binding>] bindings The call stack.
|
19
19
|
def enter_exception_context(raised)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
if bindings.size > 1 && internal_binding?(bindings.first)
|
25
|
-
raised.pop
|
26
|
-
exception, bindings = raised.last
|
27
|
-
prune_call_stack!(bindings)
|
21
|
+
raised = raised.map do |e, bs|
|
22
|
+
[e, without_bindings_below_raise(bs)]
|
28
23
|
end
|
29
24
|
|
25
|
+
raised.pop if phantom_load_raise?(*raised.last)
|
26
|
+
exception, bindings = raised.last
|
27
|
+
|
30
28
|
if defined?(PryStackExplorer)
|
31
|
-
pry :call_stack => bindings,
|
29
|
+
pry :call_stack => without_duplicates(bindings),
|
30
|
+
:hooks => pry_hooks(exception, raised),
|
31
|
+
:initial_frame => initial_frame(bindings)
|
32
32
|
else
|
33
|
-
bindings.first
|
33
|
+
Pry.start bindings.first, :hooks => pry_hooks(exception, raised)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
# Load a script wrapped in Pry::rescue{ }
|
38
|
+
# @param [String] The name of the script
|
39
|
+
def load(script)
|
40
|
+
Pry::rescue{ Kernel.load script }
|
41
|
+
end
|
42
|
+
|
37
43
|
private
|
38
44
|
|
39
|
-
#
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
# Did this raise happen within pry-rescue?
|
46
|
+
#
|
47
|
+
# This is designed to remove the extra raise that is caused by PryRescue.load.
|
48
|
+
# TODO: we should figure out why it happens...
|
49
|
+
# @param [Array<Binding>]
|
50
|
+
def phantom_load_raise?(e, bindings)
|
51
|
+
bindings.any? && bindings.first.eval("__FILE__") == __FILE__
|
52
|
+
end
|
53
|
+
|
54
|
+
# When using pry-stack-explorer we want to start the rescue session outside of gems
|
55
|
+
# and the standard library, as that is most helpful for users.
|
56
|
+
#
|
57
|
+
# @param [Array<Bindings>] All bindings
|
58
|
+
# @return [Fixnum] The offset of the first binding of user code
|
59
|
+
def initial_frame(bindings)
|
60
|
+
bindings.each_with_index do |binding, i|
|
61
|
+
return i if user_path?(binding.eval("__FILE__"))
|
62
|
+
end
|
63
|
+
|
64
|
+
0
|
65
|
+
end
|
66
|
+
|
67
|
+
# Is this path likely to be code the user is working with right now?
|
68
|
+
#
|
69
|
+
# @param [String] the absolute path
|
70
|
+
# @return [Boolean]
|
71
|
+
def user_path?(file)
|
72
|
+
!file.start_with?(RbConfig::CONFIG['libdir']) &&
|
73
|
+
!Gem::Specification.any?{ |gem| file.start_with?(gem.full_gem_path) }
|
74
|
+
end
|
75
|
+
|
76
|
+
# Remove bindings that are part of Interception/Pry.rescue's internal
|
77
|
+
# event handling that happens as part of the exception hooking process.
|
78
|
+
#
|
79
|
+
# @param [Array<Binding>] bindings The call stack.
|
80
|
+
def without_bindings_below_raise(bindings)
|
81
|
+
return bindings if bindings.size <= 1
|
82
|
+
bindings.drop_while do |b|
|
83
|
+
b.eval("__FILE__") == File.expand_path("../pry-rescue/core_ext.rb", __FILE__)
|
84
|
+
end.drop_while do |b|
|
85
|
+
b.eval("self") == Interception
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Remove multiple bindings for the same function.
|
90
|
+
#
|
91
|
+
# @param [Array<Bindings>]
|
92
|
+
# @return [Array<Bindings>]
|
93
|
+
def without_duplicates(bindings)
|
94
|
+
bindings.zip([nil] + bindings).reject do |b, c|
|
95
|
+
# The eval('__method__') is there as a shortcut as loading a method
|
96
|
+
# from a binding is very slow.
|
97
|
+
c && (b.eval("__method__") == c.eval("__method__")) &&
|
98
|
+
Pry::Method.from_binding(b) == Pry::Method.from_binding(c)
|
99
|
+
end.map(&:first)
|
43
100
|
end
|
44
101
|
|
45
102
|
# Define the :before_session hook for the Pry instance.
|
@@ -56,11 +113,5 @@ class PryRescue
|
|
56
113
|
|
57
114
|
hooks
|
58
115
|
end
|
59
|
-
|
60
|
-
# Sanitize the call stack.
|
61
|
-
# @param [Array<Binding>] bindings The call stack.
|
62
|
-
def prune_call_stack!(bindings)
|
63
|
-
bindings.delete_if { |b| [Pry, Interception].include?(b.eval("self")) }
|
64
|
-
end
|
65
116
|
end
|
66
117
|
end
|
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.6'
|
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 @@
|
|
1
|
+
raise "fixtures/simple"
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.expand_path('../../lib/pry-rescue.rb', __FILE__)
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
describe "PryRescue.load" do
|
5
|
+
if defined?(PryStackExplorer)
|
6
|
+
it "should open at the correct point" do
|
7
|
+
PryRescue.should_receive(:pry).once{ |opts|
|
8
|
+
opts[:call_stack].first.eval("__FILE__").should end_with('spec/fixtures/simple.rb')
|
9
|
+
}
|
10
|
+
lambda{
|
11
|
+
PryRescue.load("spec/fixtures/simple.rb")
|
12
|
+
}.should raise_error(/fixtures.simple/)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should open above the standard library" do
|
16
|
+
PryRescue.should_receive(:pry).once do |opts|
|
17
|
+
opts[:call_stack][opts[:initial_frame]].eval("__FILE__").should end_with('spec/fixtures/uri.rb')
|
18
|
+
end
|
19
|
+
lambda{
|
20
|
+
PryRescue.load("spec/fixtures/uri.rb")
|
21
|
+
}.should raise_error(URI::InvalidURIError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should keep the standard library on the binding stack" do
|
25
|
+
PryRescue.should_receive(:pry).once do |opts|
|
26
|
+
opts[:call_stack].first.eval("__FILE__").should start_with(RbConfig::CONFIG['libdir'])
|
27
|
+
end
|
28
|
+
lambda{
|
29
|
+
PryRescue.load("spec/fixtures/uri.rb")
|
30
|
+
}.should raise_error(URI::InvalidURIError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should open above gems" do
|
34
|
+
PryRescue.should_receive(:pry).once do |opts|
|
35
|
+
opts[:call_stack][opts[:initial_frame]].eval("__FILE__").should end_with('spec/fixtures/coderay.rb')
|
36
|
+
end
|
37
|
+
lambda{
|
38
|
+
PryRescue.load("spec/fixtures/coderay.rb")
|
39
|
+
}.should raise_error(ArgumentError)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should open above gems" do
|
43
|
+
PryRescue.should_receive(:pry).once do |opts|
|
44
|
+
opts[:call_stack].first.eval("__FILE__").should start_with(Gem::Specification.detect{|x| x.name == 'coderay' }.full_gem_path)
|
45
|
+
end
|
46
|
+
lambda{
|
47
|
+
PryRescue.load("spec/fixtures/coderay.rb")
|
48
|
+
}.should raise_error(ArgumentError)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should filter out duplicate stack frames" do
|
52
|
+
PryRescue.should_receive(:pry).once do |opts|
|
53
|
+
opts[:call_stack][0].eval("__LINE__").should == 4
|
54
|
+
opts[:call_stack][1].eval("__LINE__").should == 12
|
55
|
+
end
|
56
|
+
lambda{
|
57
|
+
PryRescue.load("spec/fixtures/super.rb")
|
58
|
+
}.should raise_error(/fixtures.super/)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
it "should open at the correct point" do
|
62
|
+
Pry.should_receive(:start).once{ |binding, h|
|
63
|
+
binding.eval("__FILE__").should end_with('spec/fixtures/simple.rb')
|
64
|
+
}
|
65
|
+
lambda{
|
66
|
+
PryRescue.load("spec/fixtures/simple.rb")
|
67
|
+
}.should raise_error(/fixtures.simple/)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
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.6'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -70,6 +70,10 @@ files:
|
|
70
70
|
- lib/pry/rescue.rb
|
71
71
|
- pry-rescue.gemspec
|
72
72
|
- spec/core_ext_spec.rb
|
73
|
+
- spec/fixtures/coderay.rb
|
74
|
+
- spec/fixtures/simple.rb
|
75
|
+
- spec/fixtures/uri.rb
|
76
|
+
- spec/pry_rescue_spec.rb
|
73
77
|
homepage: https://github.com/ConradIrwin/pry-rescue
|
74
78
|
licenses: []
|
75
79
|
post_install_message:
|