pry-exception_explorer 0.1.1pre3 → 0.1.1pre5
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/Rakefile +13 -1
- data/examples/example.rb +30 -0
- data/lib/pry-exception_explorer/commands.rb +38 -8
- data/lib/pry-exception_explorer/exception_wrap.rb +13 -9
- data/lib/pry-exception_explorer/version.rb +1 -1
- data/lib/pry-exception_explorer.rb +23 -1
- data/pry-exception_explorer.gemspec +4 -4
- data/test/helper.rb +11 -0
- data/test/test_exceptions_in_pry.rb +70 -3
- data/test/test_inline_exceptions.rb +262 -0
- data/test/test_wrapped_exceptions.rb +24 -1
- metadata +5 -4
- data/test/test_exception_explorer.rb +0 -159
data/Rakefile
CHANGED
@@ -43,9 +43,21 @@ task :reinstall => :gems do
|
|
43
43
|
sh "gem install #{direc}/pkg/pry-exception_explorer-#{PryExceptionExplorer::VERSION}.gem"
|
44
44
|
end
|
45
45
|
|
46
|
+
desc "Run example"
|
47
|
+
task :example do
|
48
|
+
sh "ruby -I#{direc}/lib/ #{direc}/examples/example.rb "
|
49
|
+
end
|
50
|
+
|
51
|
+
task :default => :test
|
52
|
+
|
53
|
+
desc "Show version"
|
54
|
+
task :version do
|
55
|
+
puts "PryExceptionExplorer version: #{PryExceptionExplorer::VERSION}"
|
56
|
+
end
|
57
|
+
|
46
58
|
desc "run tests"
|
47
59
|
task :test do
|
48
|
-
sh "bacon -Itest -rubygems -a"
|
60
|
+
sh "bacon -Itest -rubygems -a -q"
|
49
61
|
end
|
50
62
|
|
51
63
|
desc "Build gemspec"
|
data/examples/example.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
unless Object.const_defined? :PryExceptionExplorer
|
2
|
+
$:.unshift File.expand_path '../../lib', __FILE__
|
3
|
+
require 'pry'
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'pry-exception_explorer'
|
7
|
+
require 'pry-exception_explorer/exception_wrap'
|
8
|
+
|
9
|
+
def alpha
|
10
|
+
name = "john"
|
11
|
+
beta
|
12
|
+
puts name
|
13
|
+
end
|
14
|
+
|
15
|
+
def beta
|
16
|
+
x = 20
|
17
|
+
gamma
|
18
|
+
puts x
|
19
|
+
end
|
20
|
+
|
21
|
+
def gamma
|
22
|
+
raise "oh my, an exception"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
PryExceptionExplorer.intercept(Exception)
|
27
|
+
|
28
|
+
PryExceptionExplorer.wrap do
|
29
|
+
alpha
|
30
|
+
end
|
@@ -5,6 +5,7 @@ PryExceptionExplorer::Commands = Pry::CommandSet.new do
|
|
5
5
|
command "enter-exception", "Enter the context of the last exception" do
|
6
6
|
ex = _pry_.last_exception
|
7
7
|
if ex && ex.exception_call_stack
|
8
|
+
_pry_.backtrace = ex.backtrace
|
8
9
|
PryStackExplorer.create_and_push_frame_manager(ex.exception_call_stack, _pry_)
|
9
10
|
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
10
11
|
PryStackExplorer.frame_manager(_pry_).refresh_frame
|
@@ -15,13 +16,42 @@ PryExceptionExplorer::Commands = Pry::CommandSet.new do
|
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
command_class "exit-exception", "Leave the context of the current exception." do
|
20
|
+
banner <<-BANNER
|
21
|
+
Usage: exit-exception
|
22
|
+
Exit active exception and return to containing context.
|
23
|
+
BANNER
|
24
|
+
|
25
|
+
def process
|
26
|
+
if !in_exception?
|
27
|
+
raise Pry::CommandError, "You are not in an exception!"
|
28
|
+
elsif !prior_context_exists?
|
29
|
+
run "exit-all"
|
30
|
+
else
|
31
|
+
popped_fm = PryStackExplorer.pop_frame_manager(_pry_)
|
32
|
+
if frame_manager
|
33
|
+
frame_manager.refresh_frame
|
34
|
+
else
|
35
|
+
_pry_.binding_stack[-1] = popped_fm.prior_binding
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def frame_manager
|
42
|
+
PryStackExplorer.frame_manager(_pry_)
|
43
|
+
end
|
44
|
+
|
45
|
+
def frame_managers
|
46
|
+
PryStackExplorer.frame_managers(_pry_)
|
47
|
+
end
|
48
|
+
|
49
|
+
def prior_context_exists?
|
50
|
+
frame_managers.count > 1 || frame_manager.prior_binding
|
51
|
+
end
|
52
|
+
|
53
|
+
def in_exception?
|
54
|
+
frame_manager && frame_manager.user[:exception]
|
25
55
|
end
|
26
56
|
end
|
27
57
|
|
@@ -29,8 +59,8 @@ PryExceptionExplorer::Commands = Pry::CommandSet.new do
|
|
29
59
|
fm = PryStackExplorer.frame_manager(_pry_)
|
30
60
|
|
31
61
|
if fm && fm.user[:exception] && fm.user[:inline_exception]
|
32
|
-
_pry_.run_command "exit-all PryExceptionExplorer::CONTINUE_INLINE_EXCEPTION"
|
33
62
|
PryStackExplorer.pop_frame_manager(_pry_)
|
63
|
+
_pry_.run_command "exit-all PryExceptionExplorer::CONTINUE_INLINE_EXCEPTION"
|
34
64
|
elsif fm && fm.user[:exception] && fm.user[:exception].continuation
|
35
65
|
PryStackExplorer.pop_frame_manager(_pry_)
|
36
66
|
fm.user[:exception].continue
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'pry-exception_explorer'
|
2
2
|
|
3
|
-
Pry.config.hooks.delete_hook(:when_started, :save_caller_bindings)
|
3
|
+
#Pry.config.hooks.delete_hook(:when_started, :save_caller_bindings)
|
4
4
|
|
5
5
|
# default is to capture all exceptions that bubble to the top
|
6
6
|
PryExceptionExplorer.intercept { true }
|
@@ -8,22 +8,26 @@ PryExceptionExplorer.intercept { true }
|
|
8
8
|
module PryExceptionExplorer
|
9
9
|
|
10
10
|
def self.wrap
|
11
|
+
old_enabled, old_wrap_active = enabled, wrap_active
|
12
|
+
self.enabled = true
|
11
13
|
self.wrap_active = true
|
12
14
|
yield
|
13
15
|
rescue Exception => ex
|
14
|
-
Pry.config.hooks.add_hook(:when_started, :setup_exception_context) do |binding_stack, _pry_|
|
15
|
-
binding_stack.replace([ex.exception_call_stack.first])
|
16
|
-
PryStackExplorer.create_and_push_frame_manager(ex.exception_call_stack, _pry_)
|
17
|
-
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
18
|
-
end
|
19
|
-
|
20
16
|
if ex.should_capture?
|
21
|
-
|
17
|
+
hooks = Pry.config.hooks.dup.add_hook(:before_session, :set_exception_flag) do |_, _, _pry_|
|
18
|
+
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
19
|
+
|
20
|
+
_pry_.last_exception = ex
|
21
|
+
_pry_.backtrace = ex.backtrace
|
22
|
+
end
|
23
|
+
|
24
|
+
Pry.start self, :call_stack => ex.exception_call_stack, :hooks => hooks
|
22
25
|
else
|
23
26
|
raise ex
|
24
27
|
end
|
25
28
|
ensure
|
26
|
-
self.
|
29
|
+
self.enabled = old_enabled
|
30
|
+
self.wrap_active = old_wrap_active
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
@@ -15,6 +15,10 @@ module PryExceptionExplorer
|
|
15
15
|
CONTINUE_INLINE_EXCEPTION = Object.new
|
16
16
|
|
17
17
|
class << self
|
18
|
+
|
19
|
+
# @return [Boolean] Whether `PryStackExplorer` is enabled.
|
20
|
+
attr_accessor :enabled
|
21
|
+
|
18
22
|
def wrap_active=(v)
|
19
23
|
Thread.current[:__pry_exception_explorer_wrap__] = v
|
20
24
|
end
|
@@ -24,6 +28,7 @@ module PryExceptionExplorer
|
|
24
28
|
end
|
25
29
|
|
26
30
|
alias_method :wrap_active?, :wrap_active
|
31
|
+
alias_method :enabled?, :enabled
|
27
32
|
end
|
28
33
|
|
29
34
|
self.wrap_active = false
|
@@ -32,7 +37,11 @@ module PryExceptionExplorer
|
|
32
37
|
true
|
33
38
|
end
|
34
39
|
|
35
|
-
def self.intercept(&block)
|
40
|
+
def self.intercept(*exceptions, &block)
|
41
|
+
if !exceptions.empty?
|
42
|
+
block = proc { |_, ex| exceptions.any? { |v| v === ex } }
|
43
|
+
end
|
44
|
+
|
36
45
|
Thread.current[:__pry_exception_explorer_intercept_block__] = block
|
37
46
|
end
|
38
47
|
|
@@ -79,6 +88,7 @@ end
|
|
79
88
|
|
80
89
|
class Object
|
81
90
|
def raise(exception = RuntimeError, string = nil, array = caller)
|
91
|
+
|
82
92
|
if exception.is_a?(String)
|
83
93
|
string = exception
|
84
94
|
exception = RuntimeError
|
@@ -87,6 +97,11 @@ class Object
|
|
87
97
|
ex = exception.exception(string)
|
88
98
|
ex.set_backtrace(array)
|
89
99
|
|
100
|
+
# revert to normal exception behaviour if EE not enabled.
|
101
|
+
if !PryExceptionExplorer.enabled?
|
102
|
+
return super(ex)
|
103
|
+
end
|
104
|
+
|
90
105
|
if PryExceptionExplorer.should_capture_exception?(ex, binding.of_caller(1))
|
91
106
|
ex.exception_call_stack = binding.callers.tap(&:shift)
|
92
107
|
ex.should_capture = true
|
@@ -114,3 +129,10 @@ PryExceptionExplorer.wrap_active = true
|
|
114
129
|
PryExceptionExplorer.intercept { true }
|
115
130
|
|
116
131
|
Pry.config.commands.import PryExceptionExplorer::Commands
|
132
|
+
|
133
|
+
# disable by default
|
134
|
+
PryExceptionExplorer.enabled = false
|
135
|
+
|
136
|
+
Pry.config.hooks.add_hook(:when_started, :try_enable_exception_explorer) do
|
137
|
+
PryExceptionExplorer.enabled = true if Pry.cli
|
138
|
+
end
|
@@ -2,19 +2,19 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "pry-exception_explorer"
|
5
|
-
s.version = "0.1.
|
5
|
+
s.version = "0.1.1pre5"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["John Mair (banisterfiend)"]
|
9
|
-
s.date = "2012-01-
|
9
|
+
s.date = "2012-01-12"
|
10
10
|
s.description = "Enter the context of exceptions"
|
11
11
|
s.email = "jrmair@gmail.com"
|
12
|
-
s.files = [".gemtest", ".gitignore", ".travis.yml", ".yardopts", "CHANGELOG", "Gemfile", "LICENSE", "README.md", "Rakefile", "lib/pry-exception_explorer.rb", "lib/pry-exception_explorer/cli.rb", "lib/pry-exception_explorer/commands.rb", "lib/pry-exception_explorer/exception_wrap.rb", "lib/pry-exception_explorer/lazy_frame.rb", "lib/pry-exception_explorer/shim_builder.rb", "lib/pry-exception_explorer/version.rb", "pry-exception_explorer.gemspec", "test/helper.rb", "test/
|
12
|
+
s.files = [".gemtest", ".gitignore", ".travis.yml", ".yardopts", "CHANGELOG", "Gemfile", "LICENSE", "README.md", "Rakefile", "examples/example.rb", "lib/pry-exception_explorer.rb", "lib/pry-exception_explorer/cli.rb", "lib/pry-exception_explorer/commands.rb", "lib/pry-exception_explorer/exception_wrap.rb", "lib/pry-exception_explorer/lazy_frame.rb", "lib/pry-exception_explorer/shim_builder.rb", "lib/pry-exception_explorer/version.rb", "pry-exception_explorer.gemspec", "test/helper.rb", "test/test_exceptions_in_pry.rb", "test/test_inline_exceptions.rb", "test/test_wrapped_exceptions.rb"]
|
13
13
|
s.homepage = "https://github.com/banister/pry-exception_explorer"
|
14
14
|
s.require_paths = ["lib"]
|
15
15
|
s.rubygems_version = "1.8.11"
|
16
16
|
s.summary = "Enter the context of exceptions"
|
17
|
-
s.test_files = ["test/helper.rb", "test/
|
17
|
+
s.test_files = ["test/helper.rb", "test/test_exceptions_in_pry.rb", "test/test_inline_exceptions.rb", "test/test_wrapped_exceptions.rb"]
|
18
18
|
|
19
19
|
if s.respond_to? :specification_version then
|
20
20
|
s.specification_version = 3
|
data/test/helper.rb
CHANGED
@@ -6,10 +6,17 @@ unless Object.const_defined? 'PryExceptionExplorer'
|
|
6
6
|
end
|
7
7
|
|
8
8
|
require 'bacon'
|
9
|
+
require 'ostruct'
|
9
10
|
|
10
11
|
puts "Testing pry-exception_explorer version #{PryExceptionExplorer::VERSION}..."
|
11
12
|
puts "Ruby version: #{RUBY_VERSION}"
|
12
13
|
|
14
|
+
class OpenStruct
|
15
|
+
def clear
|
16
|
+
@table.clear
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
13
20
|
EE = PryExceptionExplorer
|
14
21
|
|
15
22
|
class Ratty
|
@@ -47,6 +54,9 @@ class << Pry
|
|
47
54
|
end
|
48
55
|
end
|
49
56
|
|
57
|
+
AfterSessionHook = Pry.config.hooks.get_hook(:after_session, :delete_frame_manager)
|
58
|
+
WhenStartedHook = Pry.config.hooks.get_hook(:when_started, :save_caller_bindings)
|
59
|
+
|
50
60
|
Pry.reset_defaults
|
51
61
|
|
52
62
|
class InputTester
|
@@ -99,3 +109,4 @@ def mock_pry(*args)
|
|
99
109
|
output.string
|
100
110
|
end
|
101
111
|
|
112
|
+
PryExceptionExplorer.enabled = true
|
@@ -1,13 +1,21 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
+
O = OpenStruct.new
|
4
|
+
|
3
5
|
describe PryExceptionExplorer do
|
4
6
|
|
7
|
+
before do
|
8
|
+
PryExceptionExplorer.intercept { true }
|
9
|
+
PryExceptionExplorer.wrap_active = true
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
O.clear
|
14
|
+
end
|
15
|
+
|
5
16
|
describe "Exceptions caught by Pry" do
|
6
17
|
describe "enter-exception" do
|
7
18
|
it "should be able to enter an exception caught by pry" do
|
8
|
-
|
9
|
-
PryExceptionExplorer.intercept { true }
|
10
|
-
|
11
19
|
# there are 3 types of situations where exception_explorer is invoked:
|
12
20
|
# 1. when 'wrap' is used, i.e only exceptions that bubble to
|
13
21
|
# the top are intercepted.
|
@@ -22,8 +30,67 @@ describe PryExceptionExplorer do
|
|
22
30
|
# `enter-exception` to start the session.
|
23
31
|
#
|
24
32
|
# This test is for type 3.
|
33
|
+
redirect_pry_io(InputTester.new("Ratty.new.ratty",
|
34
|
+
"enter-exception",
|
35
|
+
"O.method_name = __method__",
|
36
|
+
"exit", StringIO.new)) do
|
37
|
+
Pry.start
|
38
|
+
end
|
39
|
+
|
40
|
+
O.method_name.should == :toad
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should have access to exception's caller" do
|
25
44
|
mock_pry("Ratty.new.ratty", "enter-exception", "show-stack", "exit").should =~ /toad.*?weasel.*?ratty/m
|
26
45
|
end
|
46
|
+
|
47
|
+
describe "exit-exception" do
|
48
|
+
it 'should display error message when exit-exception used outside of exception context' do
|
49
|
+
mock_pry("exit-exception").should =~ /You are not in an exception!/
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should exit a nested exception and correctly pop FrameManagers" do
|
53
|
+
redirect_pry_io(InputTester.new("Ratty.new.ratty",
|
54
|
+
"enter-exception",
|
55
|
+
"raise 'yo'",
|
56
|
+
"enter-exception",
|
57
|
+
"O.first_pry = _pry_",
|
58
|
+
"O.first_count = PryStackExplorer.frame_managers(_pry_).count",
|
59
|
+
"exit-exception",
|
60
|
+
"O.second_pry = _pry_",
|
61
|
+
"O.second_count = PryStackExplorer.frame_managers(_pry_).count",
|
62
|
+
"exit-exception",
|
63
|
+
"exit-all", StringIO.new)) do
|
64
|
+
Pry.start(binding)
|
65
|
+
end
|
66
|
+
|
67
|
+
O.first_pry.should == O.second_pry
|
68
|
+
O.first_count.should == 2
|
69
|
+
O.second_count.should == 1
|
70
|
+
PryStackExplorer.frame_managers(O.first_pry).count.should == 0
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should exit an exception and return to initial context" do
|
74
|
+
redirect_pry_io(InputTester.new("Ratty.new.ratty",
|
75
|
+
"O.initial_self = self",
|
76
|
+
"enter-exception",
|
77
|
+
"O.exception_self = self",
|
78
|
+
"exit-exception",
|
79
|
+
"O.return_self = self",
|
80
|
+
"exit-all", StringIO.new)) do
|
81
|
+
Pry.start(binding)
|
82
|
+
end
|
83
|
+
|
84
|
+
O.initial_self.should == self
|
85
|
+
O.initial_self.should == O.return_self
|
86
|
+
|
87
|
+
# actual exception context is Toad, as call chain is:
|
88
|
+
# Ratty -> Weasel -> Toad (raise is here)
|
89
|
+
O.exception_self.is_a?(Toad).should == true
|
90
|
+
end
|
91
|
+
end
|
27
92
|
end
|
28
93
|
end
|
29
94
|
end
|
95
|
+
|
96
|
+
Object.send(:remove_const, :O)
|
@@ -0,0 +1,262 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
# globally accessible state
|
5
|
+
O = OpenStruct.new
|
6
|
+
|
7
|
+
prev_wrap_state = PryExceptionExplorer.wrap_active
|
8
|
+
PryExceptionExplorer.wrap_active = false
|
9
|
+
|
10
|
+
prev_intercept_state = PryExceptionExplorer.intercept_block
|
11
|
+
|
12
|
+
describe PryExceptionExplorer do
|
13
|
+
|
14
|
+
before do
|
15
|
+
PryExceptionExplorer.wrap_active = false
|
16
|
+
O.exception_intercepted = false
|
17
|
+
|
18
|
+
# Ensure that when an exception is intercepted (a pry session
|
19
|
+
# started) that this is registered by setting state on `O`
|
20
|
+
Pry.config.input = StringIO.new("O.exception_intercepted = true\ncontinue-exception")
|
21
|
+
Pry.config.output = StringIO.new
|
22
|
+
end
|
23
|
+
|
24
|
+
after do
|
25
|
+
Pry.config.input.rewind
|
26
|
+
O.clear
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "PryExceptionExplorer.intercept" do
|
30
|
+
describe "special case exception-only syntax" do
|
31
|
+
|
32
|
+
describe "single exception" do
|
33
|
+
it 'should intercept provided exceptions when given parameters (and no block)' do
|
34
|
+
my_error = Class.new(StandardError)
|
35
|
+
EE.intercept(my_error)
|
36
|
+
raise my_error
|
37
|
+
O.exception_intercepted.should == true
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should NOT intercept provided exceptions when not matched' do
|
41
|
+
my_error = Class.new(StandardError)
|
42
|
+
EE.intercept(my_error)
|
43
|
+
|
44
|
+
begin
|
45
|
+
raise RuntimeError
|
46
|
+
rescue => ex
|
47
|
+
ex.is_a?(RuntimeError).should == true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "multiple exceptions" do
|
53
|
+
it 'should intercept provided exceptions when given parameters (and no block)' do
|
54
|
+
errors = Array.new(3) { Class.new(StandardError) }
|
55
|
+
EE.intercept(*errors)
|
56
|
+
|
57
|
+
errors.each do |my_error|
|
58
|
+
raise my_error
|
59
|
+
O.exception_intercepted.should == true
|
60
|
+
O.exception_intercepted = false
|
61
|
+
Pry.config.input.rewind
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should NOT intercept provided exceptions when not matched' do
|
66
|
+
errors = Array.new(3) { Class.new(StandardError) }
|
67
|
+
|
68
|
+
EE.intercept(*errors)
|
69
|
+
|
70
|
+
errors.each do |my_error|
|
71
|
+
begin
|
72
|
+
raise RuntimeError
|
73
|
+
rescue => ex
|
74
|
+
ex.is_a?(RuntimeError).should == true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "class" do
|
83
|
+
describe "first frame" do
|
84
|
+
it "should intercept exception based on first frame's class" do
|
85
|
+
EE.intercept { |frame, ex| frame.klass == Toad }
|
86
|
+
Ratty.new.ratty
|
87
|
+
O.exception_intercepted.should == true
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should NOT intercept exception if class doesn't match" do
|
91
|
+
EE.intercept { |frame, ex| frame.klass == Ratty }
|
92
|
+
begin
|
93
|
+
Ratty.new.ratty
|
94
|
+
rescue Exception => ex
|
95
|
+
ex.is_a?(RuntimeError).should == true
|
96
|
+
end
|
97
|
+
O.exception_intercepted.should == false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "second frame" do
|
102
|
+
it "should intercept exception based on second frame's method name" do
|
103
|
+
EE.intercept { |frame, ex| frame.prev.klass == Weasel }
|
104
|
+
Ratty.new.ratty
|
105
|
+
O.exception_intercepted.should == true
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should NOT intercept exception if method name doesn't match" do
|
109
|
+
EE.intercept { |frame, ex| frame.prev.klass == Toad }
|
110
|
+
begin
|
111
|
+
Ratty.new.ratty
|
112
|
+
rescue Exception => ex
|
113
|
+
ex.is_a?(RuntimeError).should == true
|
114
|
+
end
|
115
|
+
O.exception_intercepted.should == false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "third frame" do
|
120
|
+
it "should intercept exception based on third frame's method name" do
|
121
|
+
EE.intercept { |frame, ex| frame.prev.prev.klass == Ratty }
|
122
|
+
Ratty.new.ratty
|
123
|
+
O.exception_intercepted.should == true
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should NOT intercept exception if method name doesn't match" do
|
127
|
+
EE.intercept { |frame, ex| frame.prev.prev.klass == Toad }
|
128
|
+
begin
|
129
|
+
Ratty.new.ratty
|
130
|
+
rescue Exception => ex
|
131
|
+
ex.is_a?(RuntimeError).should == true
|
132
|
+
end
|
133
|
+
O.exception_intercepted.should == false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "method_name" do
|
140
|
+
describe "first frame" do
|
141
|
+
it "should intercept exception based on first frame's method name" do
|
142
|
+
EE.intercept { |frame, ex| frame.method_name == :toad }
|
143
|
+
Ratty.new.ratty
|
144
|
+
O.exception_intercepted.should == true
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should NOT intercept exception if method name doesn't match" do
|
148
|
+
EE.intercept { |frame, ex| frame.method_name == :ratty }
|
149
|
+
begin
|
150
|
+
Ratty.new.ratty
|
151
|
+
rescue Exception => ex
|
152
|
+
ex.is_a?(RuntimeError).should == true
|
153
|
+
end
|
154
|
+
O.exception_intercepted.should == false
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "second frame" do
|
159
|
+
it "should intercept exception based on second frame's method name" do
|
160
|
+
EE.intercept { |frame, ex| frame.prev.method_name == :weasel }
|
161
|
+
Ratty.new.ratty
|
162
|
+
O.exception_intercepted.should == true
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should NOT intercept exception if method name doesn't match" do
|
166
|
+
EE.intercept { |frame, ex| frame.prev.method_name == :toad }
|
167
|
+
begin
|
168
|
+
Ratty.new.ratty
|
169
|
+
rescue Exception => ex
|
170
|
+
ex.is_a?(RuntimeError).should == true
|
171
|
+
end
|
172
|
+
O.exception_intercepted.should == false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "third frame" do
|
177
|
+
it "should intercept exception based on third frame's method name" do
|
178
|
+
EE.intercept { |frame, ex| frame.prev.prev.method_name == :ratty }
|
179
|
+
Ratty.new.ratty
|
180
|
+
O.exception_intercepted.should == true
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should NOT intercept exception if method name doesn't match" do
|
184
|
+
EE.intercept { |frame, ex| frame.prev.prev.method_name == :toad }
|
185
|
+
begin
|
186
|
+
Ratty.new.ratty
|
187
|
+
rescue Exception => ex
|
188
|
+
ex.is_a?(RuntimeError).should == true
|
189
|
+
end
|
190
|
+
O.exception_intercepted.should == false
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "call-stack management" do
|
200
|
+
it 'should pop the call-stack after session ends (continue)' do
|
201
|
+
EE.intercept { |frame, ex| frame.prev.prev.method_name == :ratty }
|
202
|
+
|
203
|
+
redirect_pry_io(InputTester.new(
|
204
|
+
"O.stack_count = PryStackExplorer.frame_managers(_pry_).count",
|
205
|
+
"O._pry_ = _pry_",
|
206
|
+
"continue-exception"), StringIO.new) do
|
207
|
+
Ratty.new.ratty
|
208
|
+
end
|
209
|
+
O.stack_count.should == 1
|
210
|
+
PryStackExplorer.frame_managers(O._pry_).count.should == 0
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should pop the call-stack after session ends (exit)' do
|
214
|
+
EE.intercept { |frame, ex| frame.prev.prev.method_name == :ratty }
|
215
|
+
|
216
|
+
redirect_pry_io(InputTester.new(
|
217
|
+
"O.stack_count = PryStackExplorer.frame_managers(_pry_).count",
|
218
|
+
"O._pry_ = _pry_",
|
219
|
+
"exit"), StringIO.new) do
|
220
|
+
begin
|
221
|
+
Ratty.new.ratty
|
222
|
+
rescue
|
223
|
+
end
|
224
|
+
end
|
225
|
+
O.stack_count.should == 1
|
226
|
+
PryStackExplorer.frame_managers(O._pry_).count.should == 0
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "nested exceptions" do
|
230
|
+
it 'Each successive exception interception should be managed by its own pry instance and have its own call-stack' do
|
231
|
+
EE.intercept { |frame, ex| frame.prev.prev.method_name == :ratty }
|
232
|
+
|
233
|
+
redirect_pry_io(InputTester.new(
|
234
|
+
"O.first_stack_count = PryStackExplorer.frame_managers(_pry_).count",
|
235
|
+
"O._pry_ = _pry_",
|
236
|
+
"EE.intercept(ArgumentError)",
|
237
|
+
"raise ArgumentError",
|
238
|
+
"O._pry_2 = _pry_",
|
239
|
+
"O.second_stack_count = PryStackExplorer.frame_managers(_pry_).count",
|
240
|
+
"continue-exception",
|
241
|
+
"continue-exception"), StringIO.new) do
|
242
|
+
Ratty.new.ratty
|
243
|
+
end
|
244
|
+
|
245
|
+
O._pry_.should.not == O._pry_2
|
246
|
+
O.first_stack_count.should == 1
|
247
|
+
O.second_stack_count.should == 1
|
248
|
+
PryStackExplorer.frame_managers(O._pry_).count.should == 0
|
249
|
+
PryStackExplorer.frame_managers(O._pry_2).count.should == 0
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
|
258
|
+
# restore to default
|
259
|
+
PryExceptionExplorer.wrap_active = prev_wrap_state
|
260
|
+
PryExceptionExplorer.intercept &prev_intercept_state
|
261
|
+
|
262
|
+
Object.send(:remove_const, :O)
|
@@ -5,19 +5,42 @@ require 'pry-exception_explorer/exception_wrap'
|
|
5
5
|
CaughtException = Class.new(StandardError)
|
6
6
|
UncaughtException = Class.new(StandardError)
|
7
7
|
|
8
|
+
|
8
9
|
describe PryExceptionExplorer do
|
9
10
|
|
11
|
+
|
10
12
|
before do
|
11
13
|
Pry.config.input = StringIO.new("exit :caught\n")
|
12
14
|
Pry.config.output = StringIO.new
|
15
|
+
Pry.config.hooks.add_hook(:when_started, :save_caller_bindings, &WhenStartedHook)
|
16
|
+
Pry.config.hooks.add_hook(:after_session, :delete_frame_manager, &AfterSessionHook)
|
13
17
|
end
|
14
18
|
|
15
19
|
after do
|
16
|
-
Pry.config.hooks.
|
20
|
+
Pry.config.hooks.delete_hook(:when_started, :save_caller_bindings)
|
21
|
+
Pry.config.hooks.delete_hook(:after_session, :delete_frame_manager)
|
17
22
|
end
|
18
23
|
|
19
24
|
describe "PryExceptionExplorer.wrap" do
|
20
25
|
|
26
|
+
# use of exit-exception inside a wrapped exception is weird
|
27
|
+
# (because exit-exception is really designed for pry exceptions)
|
28
|
+
# but when we do receive one, we should exit out of pry
|
29
|
+
# altogether.
|
30
|
+
# This test is weird as we can't use lambda { }.should.not.raise, as we override
|
31
|
+
# 'raise' method ourself, which kills bacon's functionality here.
|
32
|
+
it 'should exit out of Pry session when using exit-exception' do
|
33
|
+
PryExceptionExplorer.intercept { true }
|
34
|
+
|
35
|
+
x = :no_exception_raised
|
36
|
+
redirect_pry_io(InputTester.new("exit-exception"), $stdout) do
|
37
|
+
PryExceptionExplorer.wrap do
|
38
|
+
Ratty.new.ratty
|
39
|
+
end
|
40
|
+
end
|
41
|
+
x.should == :no_exception_raised
|
42
|
+
end
|
43
|
+
|
21
44
|
it 'should default to capturing ALL exceptions' do
|
22
45
|
PryExceptionExplorer.wrap do
|
23
46
|
raise CaughtException, "catch me if u can"
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: pry-exception_explorer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 5
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.1pre5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- John Mair (banisterfiend)
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-01-
|
13
|
+
date: 2012-01-12 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: pry-stack_explorer
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- LICENSE
|
64
64
|
- README.md
|
65
65
|
- Rakefile
|
66
|
+
- examples/example.rb
|
66
67
|
- lib/pry-exception_explorer.rb
|
67
68
|
- lib/pry-exception_explorer/cli.rb
|
68
69
|
- lib/pry-exception_explorer/commands.rb
|
@@ -72,8 +73,8 @@ files:
|
|
72
73
|
- lib/pry-exception_explorer/version.rb
|
73
74
|
- pry-exception_explorer.gemspec
|
74
75
|
- test/helper.rb
|
75
|
-
- test/test_exception_explorer.rb
|
76
76
|
- test/test_exceptions_in_pry.rb
|
77
|
+
- test/test_inline_exceptions.rb
|
77
78
|
- test/test_wrapped_exceptions.rb
|
78
79
|
homepage: https://github.com/banister/pry-exception_explorer
|
79
80
|
licenses: []
|
@@ -104,6 +105,6 @@ specification_version: 3
|
|
104
105
|
summary: Enter the context of exceptions
|
105
106
|
test_files:
|
106
107
|
- test/helper.rb
|
107
|
-
- test/test_exception_explorer.rb
|
108
108
|
- test/test_exceptions_in_pry.rb
|
109
|
+
- test/test_inline_exceptions.rb
|
109
110
|
- test/test_wrapped_exceptions.rb
|
@@ -1,159 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
|
4
|
-
# override enter_exception_inline so we can use it for testing purposes
|
5
|
-
EE.instance_eval do
|
6
|
-
alias original_enter_exception_inline enter_exception_inline
|
7
|
-
end
|
8
|
-
|
9
|
-
def EE.exception_intercepted?
|
10
|
-
@exception_intercepted
|
11
|
-
end
|
12
|
-
|
13
|
-
EE.instance_eval do
|
14
|
-
@exception_intercepted = false
|
15
|
-
end
|
16
|
-
|
17
|
-
def EE.enter_exception_inline(ex)
|
18
|
-
@exception_intercepted = true
|
19
|
-
EE::CONTINUE_INLINE_EXCEPTION
|
20
|
-
end
|
21
|
-
|
22
|
-
prev_wrap_state = PryExceptionExplorer.wrap_active
|
23
|
-
PryExceptionExplorer.wrap_active = false
|
24
|
-
|
25
|
-
describe PryExceptionExplorer do
|
26
|
-
|
27
|
-
before do
|
28
|
-
PryExceptionExplorer.wrap_active = false
|
29
|
-
end
|
30
|
-
|
31
|
-
after do
|
32
|
-
EE.instance_eval do
|
33
|
-
@exception_intercepted = false
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe "PryExceptionExplorer.intercept" do
|
38
|
-
describe "class" do
|
39
|
-
describe "first frame" do
|
40
|
-
it "should intercept exception based on first frame's method name" do
|
41
|
-
EE.intercept { |frame, ex| frame.klass == Toad }
|
42
|
-
Ratty.new.ratty
|
43
|
-
EE.exception_intercepted?.should == true
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should NOT intercept exception if method name doesn't match" do
|
47
|
-
EE.intercept { |frame, ex| frame.klass == Ratty }
|
48
|
-
begin
|
49
|
-
Ratty.new.ratty
|
50
|
-
rescue Exception => ex
|
51
|
-
ex.is_a?(RuntimeError).should == true
|
52
|
-
end
|
53
|
-
EE.exception_intercepted?.should == false
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "second frame" do
|
58
|
-
it "should intercept exception based on second frame's method name" do
|
59
|
-
EE.intercept { |frame, ex| frame.prev.klass == Weasel }
|
60
|
-
Ratty.new.ratty
|
61
|
-
EE.exception_intercepted?.should == true
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should NOT intercept exception if method name doesn't match" do
|
65
|
-
EE.intercept { |frame, ex| frame.prev.klass == Toad }
|
66
|
-
begin
|
67
|
-
Ratty.new.ratty
|
68
|
-
rescue Exception => ex
|
69
|
-
ex.is_a?(RuntimeError).should == true
|
70
|
-
end
|
71
|
-
EE.exception_intercepted?.should == false
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "third frame" do
|
76
|
-
it "should intercept exception based on third frame's method name" do
|
77
|
-
EE.intercept { |frame, ex| frame.prev.prev.klass == Ratty }
|
78
|
-
Ratty.new.ratty
|
79
|
-
EE.exception_intercepted?.should == true
|
80
|
-
end
|
81
|
-
|
82
|
-
it "should NOT intercept exception if method name doesn't match" do
|
83
|
-
EE.intercept { |frame, ex| frame.prev.prev.klass == Toad }
|
84
|
-
begin
|
85
|
-
Ratty.new.ratty
|
86
|
-
rescue Exception => ex
|
87
|
-
ex.is_a?(RuntimeError).should == true
|
88
|
-
end
|
89
|
-
EE.exception_intercepted?.should == false
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
end
|
94
|
-
|
95
|
-
describe "method_name" do
|
96
|
-
describe "first frame" do
|
97
|
-
it "should intercept exception based on first frame's method name" do
|
98
|
-
EE.intercept { |frame, ex| frame.method_name == :toad }
|
99
|
-
Ratty.new.ratty
|
100
|
-
EE.exception_intercepted?.should == true
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should NOT intercept exception if method name doesn't match" do
|
104
|
-
EE.intercept { |frame, ex| frame.method_name == :ratty }
|
105
|
-
begin
|
106
|
-
Ratty.new.ratty
|
107
|
-
rescue Exception => ex
|
108
|
-
ex.is_a?(RuntimeError).should == true
|
109
|
-
end
|
110
|
-
EE.exception_intercepted?.should == false
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
describe "second frame" do
|
115
|
-
it "should intercept exception based on second frame's method name" do
|
116
|
-
EE.intercept { |frame, ex| frame.prev.method_name == :weasel }
|
117
|
-
Ratty.new.ratty
|
118
|
-
EE.exception_intercepted?.should == true
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should NOT intercept exception if method name doesn't match" do
|
122
|
-
EE.intercept { |frame, ex| frame.prev.method_name == :toad }
|
123
|
-
begin
|
124
|
-
Ratty.new.ratty
|
125
|
-
rescue Exception => ex
|
126
|
-
ex.is_a?(RuntimeError).should == true
|
127
|
-
end
|
128
|
-
EE.exception_intercepted?.should == false
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
describe "third frame" do
|
133
|
-
it "should intercept exception based on third frame's method name" do
|
134
|
-
EE.intercept { |frame, ex| frame.prev.prev.method_name == :ratty }
|
135
|
-
Ratty.new.ratty
|
136
|
-
EE.exception_intercepted?.should == true
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should NOT intercept exception if method name doesn't match" do
|
140
|
-
EE.intercept { |frame, ex| frame.prev.prev.method_name == :toad }
|
141
|
-
begin
|
142
|
-
Ratty.new.ratty
|
143
|
-
rescue Exception => ex
|
144
|
-
ex.is_a?(RuntimeError).should == true
|
145
|
-
end
|
146
|
-
EE.exception_intercepted?.should == false
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
EE.instance_eval do
|
156
|
-
alias enter_exception_inline original_enter_exception_inline
|
157
|
-
end
|
158
|
-
|
159
|
-
PryExceptionExplorer.wrap_active = prev_wrap_state
|