pry-exception_explorer 0.1.1pre5 → 0.1.1pre7
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +8 -3
- data/examples/example_inline.rb +27 -0
- data/examples/{example.rb → example_wrap.rb} +0 -1
- data/lib/pry-exception_explorer/cli.rb +0 -2
- data/lib/pry-exception_explorer/commands.rb +81 -54
- data/lib/pry-exception_explorer/core_ext.rb +54 -0
- data/lib/pry-exception_explorer/intercept.rb +43 -0
- data/lib/pry-exception_explorer/lazy_frame.rb +7 -2
- data/lib/pry-exception_explorer/version.rb +1 -1
- data/lib/pry-exception_explorer.rb +144 -88
- data/pry-exception_explorer.gemspec +3 -3
- data/test/helper.rb +1 -3
- data/test/test_exceptions_in_pry.rb +139 -0
- data/test/test_inline_exceptions.rb +113 -3
- data/test/test_wrapped_exceptions.rb +52 -6
- metadata +43 -48
- data/lib/pry-exception_explorer/exception_wrap.rb +0 -33
data/Rakefile
CHANGED
@@ -43,9 +43,14 @@ 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 :
|
48
|
-
sh "ruby -I#{direc}/lib/ #{direc}/examples/
|
46
|
+
desc "Run example wrap"
|
47
|
+
task :example_wrap do
|
48
|
+
sh "ruby -I#{direc}/lib/ #{direc}/examples/example_wrap.rb "
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Run example inline"
|
52
|
+
task :example_inline do
|
53
|
+
sh "ruby -I#{direc}/lib/ #{direc}/examples/example_inline.rb "
|
49
54
|
end
|
50
55
|
|
51
56
|
task :default => :test
|
@@ -0,0 +1,27 @@
|
|
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
|
+
|
8
|
+
PryExceptionExplorer.enabled = true
|
9
|
+
PryExceptionExplorer.intercept(RuntimeError)
|
10
|
+
|
11
|
+
def alpha
|
12
|
+
name = "john"
|
13
|
+
beta
|
14
|
+
puts name
|
15
|
+
end
|
16
|
+
|
17
|
+
def beta
|
18
|
+
x = 20
|
19
|
+
gamma
|
20
|
+
puts x
|
21
|
+
end
|
22
|
+
|
23
|
+
def gamma
|
24
|
+
raise "oh my, an exception"
|
25
|
+
end
|
26
|
+
|
27
|
+
alpha
|
@@ -1,72 +1,99 @@
|
|
1
1
|
require 'pry-stack_explorer'
|
2
2
|
|
3
|
-
PryExceptionExplorer
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
module PryExceptionExplorer
|
4
|
+
module ExceptionHelpers
|
5
|
+
include PryStackExplorer::FrameHelpers
|
6
|
+
|
7
|
+
private
|
8
|
+
def in_exception?
|
9
|
+
frame_manager && frame_manager.user[:exception]
|
10
|
+
end
|
11
|
+
|
12
|
+
def last_exception
|
13
|
+
_pry_.last_exception
|
14
|
+
end
|
15
|
+
|
16
|
+
def enterable_exception?
|
17
|
+
last_exception && last_exception.exception_call_stack
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
21
|
+
Commands = Pry::CommandSet.new do
|
22
|
+
create_command "enter-exception", "Enter the context of the last exception" do
|
23
|
+
include PryExceptionExplorer::ExceptionHelpers
|
24
|
+
|
25
|
+
banner <<-BANNER
|
26
|
+
Usage: enter-exception
|
27
|
+
Enter the context of the last exception
|
28
|
+
BANNER
|
29
|
+
|
30
|
+
def process
|
31
|
+
if enterable_exception?
|
32
|
+
PryStackExplorer.create_and_push_frame_manager(last_exception.exception_call_stack, _pry_)
|
33
|
+
PryExceptionExplorer.setup_exception_context(last_exception, _pry_)
|
34
|
+
|
35
|
+
# have to use _pry_.run_command instead of 'run' here as
|
36
|
+
# 'run' works on the current target which hasnt been updated
|
37
|
+
# yet, whereas _pry_.run_command operates on the newly
|
38
|
+
# updated target (the context of the exception)
|
39
|
+
_pry_.run_command "whereami"
|
40
|
+
elsif last_exception
|
41
|
+
raise Pry::CommandError, "Current exception can't be entered! (perhaps a C exception)"
|
34
42
|
else
|
35
|
-
|
43
|
+
raise Pry::CommandError, "No exception to enter!"
|
36
44
|
end
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
40
|
-
|
41
|
-
|
42
|
-
PryStackExplorer.frame_manager(_pry_)
|
43
|
-
end
|
48
|
+
create_command "exit-exception", "Leave the context of the current exception." do
|
49
|
+
include ExceptionHelpers
|
44
50
|
|
45
|
-
|
46
|
-
|
47
|
-
|
51
|
+
banner <<-BANNER
|
52
|
+
Usage: exit-exception
|
53
|
+
Exit active exception and return to containing context.
|
54
|
+
BANNER
|
48
55
|
|
49
|
-
|
50
|
-
|
56
|
+
def process
|
57
|
+
if !in_exception?
|
58
|
+
raise Pry::CommandError, "You are not in an exception!"
|
59
|
+
elsif !prior_context_exists?
|
60
|
+
run "exit-all"
|
61
|
+
else
|
62
|
+
popped_fm = PryStackExplorer.pop_frame_manager(_pry_)
|
63
|
+
_pry_.last_exception = popped_fm.user[:exception]
|
64
|
+
end
|
65
|
+
end
|
51
66
|
end
|
52
67
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
68
|
+
create_command "continue-exception", "Attempt to continue the current exception." do
|
69
|
+
include ExceptionHelpers
|
70
|
+
|
71
|
+
banner <<-BANNER
|
72
|
+
Usage: continue-exception
|
73
|
+
Attempt to continue the current exception.
|
74
|
+
BANNER
|
57
75
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
76
|
+
def process
|
77
|
+
if inline_exception?
|
78
|
+
PryStackExplorer.pop_frame_manager(_pry_)
|
79
|
+
run "exit-all PryExceptionExplorer::CONTINUE_INLINE_EXCEPTION"
|
80
|
+
elsif normal_exception?
|
81
|
+
popped_fm = PryStackExplorer.pop_frame_manager(_pry_)
|
82
|
+
popped_fm.user[:exception].continue
|
83
|
+
else
|
84
|
+
raise Pry::CommandError, "No exception to continue!"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
def inline_exception?
|
90
|
+
frame_manager && frame_manager.user[:exception] && frame_manager.user[:inline_exception]
|
91
|
+
end
|
92
|
+
|
93
|
+
def normal_exception?
|
94
|
+
frame_manager && frame_manager.user[:exception] && frame_manager.user[:exception].continuation
|
95
|
+
end
|
69
96
|
end
|
70
|
-
end
|
71
97
|
|
98
|
+
end
|
72
99
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# `PryExceptionExplorer` monkey-patches to `Exception`
|
2
|
+
class Exception
|
3
|
+
NoContinuation = Class.new(StandardError)
|
4
|
+
|
5
|
+
attr_accessor :continuation
|
6
|
+
attr_accessor :exception_call_stack
|
7
|
+
attr_accessor :should_intercept
|
8
|
+
|
9
|
+
# This method enables us to continue an exception (using
|
10
|
+
# `callcc` internally)
|
11
|
+
def continue
|
12
|
+
raise NoContinuation unless continuation.respond_to?(:call)
|
13
|
+
continuation.call
|
14
|
+
end
|
15
|
+
|
16
|
+
alias_method :should_intercept?, :should_intercept
|
17
|
+
end
|
18
|
+
|
19
|
+
# `PryExceptionExplorer` monkey-patches to `Object`
|
20
|
+
class Object
|
21
|
+
|
22
|
+
# We monkey-patch the `raise` method so we can intercept exceptions
|
23
|
+
def raise(exception = RuntimeError, string = nil, array = caller)
|
24
|
+
|
25
|
+
if exception.is_a?(String)
|
26
|
+
string = exception
|
27
|
+
exception = RuntimeError
|
28
|
+
end
|
29
|
+
|
30
|
+
ex = exception.exception(string)
|
31
|
+
ex.set_backtrace(array)
|
32
|
+
|
33
|
+
# revert to normal exception behaviour if EE not enabled.
|
34
|
+
if !PryExceptionExplorer.enabled?
|
35
|
+
return super(ex)
|
36
|
+
end
|
37
|
+
|
38
|
+
if PryExceptionExplorer.should_intercept_exception?(binding.of_caller(1), ex)
|
39
|
+
ex.exception_call_stack = binding.callers.tap { |v| v.shift(1 + PryExceptionExplorer.intercept_object.skip) }
|
40
|
+
ex.should_intercept = true
|
41
|
+
|
42
|
+
if !PryExceptionExplorer.wrap_active?
|
43
|
+
retval = PryExceptionExplorer.enter_exception(ex, :inline => true)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if retval != PryExceptionExplorer::CONTINUE_INLINE_EXCEPTION
|
48
|
+
callcc do |cc|
|
49
|
+
ex.continuation = cc
|
50
|
+
super(ex)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module PryExceptionExplorer
|
2
|
+
class Intercept
|
3
|
+
|
4
|
+
# @return [Fixnum] Number of frames to skip when session starts.
|
5
|
+
attr_accessor :skip
|
6
|
+
|
7
|
+
# @return [Boolean] Whether to intercept exceptions raised inside the session.
|
8
|
+
attr_accessor :intercept_recurse
|
9
|
+
alias_method :intercept_recurse?, :intercept_recurse
|
10
|
+
|
11
|
+
# @return [Boolean] Whether this intercept object is active
|
12
|
+
# If it's inactive then calling it will always return `false`
|
13
|
+
# regardless of content inside block.
|
14
|
+
def active?() @active end
|
15
|
+
|
16
|
+
# Disable the intercept object.
|
17
|
+
def disable!() @active = false end
|
18
|
+
|
19
|
+
# Enable if the intercept object.
|
20
|
+
def enable!() @active = true end
|
21
|
+
|
22
|
+
# @return [Proc] The predicate block that determines if
|
23
|
+
# interception takes place.
|
24
|
+
attr_reader :block
|
25
|
+
|
26
|
+
def initialize(block, options={})
|
27
|
+
options = {
|
28
|
+
:skip => 0,
|
29
|
+
:intercept_recurse => false
|
30
|
+
}.merge!(options)
|
31
|
+
|
32
|
+
@block = block
|
33
|
+
@skip = options[:skip]
|
34
|
+
@intercept_recurse = options[:intercept_recurse]
|
35
|
+
|
36
|
+
@active = true
|
37
|
+
end
|
38
|
+
|
39
|
+
def call(*args)
|
40
|
+
active? && @block.call(*args)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -2,29 +2,34 @@ module PryExceptionExplorer
|
|
2
2
|
class LazyFrame
|
3
3
|
|
4
4
|
# we need to jump over a few irrelevant frames to begin with
|
5
|
-
START_FRAME_OFFSET =
|
6
|
-
|
5
|
+
START_FRAME_OFFSET = 6
|
6
|
+
|
7
7
|
def initialize(frame, frame_counter = 0)
|
8
8
|
@frame = frame
|
9
9
|
@frame_counter = frame_counter
|
10
10
|
end
|
11
11
|
|
12
|
+
# @return [Binding] The `Binding` object that represents the frame.
|
12
13
|
def raw_frame
|
13
14
|
@frame
|
14
15
|
end
|
15
16
|
|
17
|
+
# @return [Class] The class of the `self` of the frame.
|
16
18
|
def klass
|
17
19
|
@frame.eval("self.class")
|
18
20
|
end
|
19
21
|
|
22
|
+
# @return [Object] The object context of the frame (the `self`).
|
20
23
|
def self
|
21
24
|
@frame.eval("self")
|
22
25
|
end
|
23
26
|
|
27
|
+
# @return [Symbol, nil] The name of the active method in the frame (or `nil`)
|
24
28
|
def method_name
|
25
29
|
@frame.eval("__method__")
|
26
30
|
end
|
27
31
|
|
32
|
+
# @return [LazyFrame] The caller frame.
|
28
33
|
def prev
|
29
34
|
LazyFrame.new(binding.of_caller(@frame_counter + START_FRAME_OFFSET), @frame_counter + 1)
|
30
35
|
end
|
@@ -1,138 +1,194 @@
|
|
1
1
|
# pry-exception_explorer.rb
|
2
|
-
# (C) John Mair (banisterfiend); MIT license
|
2
|
+
# (C) 2012 John Mair (banisterfiend); MIT license
|
3
3
|
|
4
4
|
require 'pry-stack_explorer'
|
5
5
|
require "pry-exception_explorer/version"
|
6
6
|
require "pry-exception_explorer/lazy_frame"
|
7
7
|
require "pry-exception_explorer/commands"
|
8
|
-
require "pry"
|
8
|
+
require "pry-exception_explorer/core_ext"
|
9
|
+
require "pry-exception_explorer/intercept"
|
9
10
|
|
10
11
|
if RUBY_VERSION =~ /1.9/
|
11
12
|
require 'continuation'
|
12
13
|
end
|
13
14
|
|
14
15
|
module PryExceptionExplorer
|
16
|
+
|
17
|
+
# short-hand for `PryExceptionExplorer`
|
18
|
+
::EE = self
|
19
|
+
|
20
|
+
# special constant
|
15
21
|
CONTINUE_INLINE_EXCEPTION = Object.new
|
16
22
|
|
17
23
|
class << self
|
18
24
|
|
19
|
-
# @return [
|
20
|
-
|
25
|
+
# @return [Hash] A thread-local hash.
|
26
|
+
def local_hash
|
27
|
+
Thread.current[:__pry_exception_explorer_hash__] ||= {}
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [Boolean] v Whether Exception Explorer is enabled.
|
31
|
+
def enabled=(v)
|
32
|
+
local_hash[:enabled] = v
|
33
|
+
end
|
21
34
|
|
35
|
+
# @return [Boolean] Whether Exception Explorer is enabled.
|
36
|
+
def enabled
|
37
|
+
!!local_hash[:enabled]
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param [Boolean] v Whether to intercept only those exceptions that bubble out of
|
41
|
+
# `EE.wrap` block.
|
22
42
|
def wrap_active=(v)
|
23
|
-
|
43
|
+
local_hash[:wrap_active] = v
|
24
44
|
end
|
25
45
|
|
46
|
+
# @return [Boolean] Whether to intercept only those exceptions that bubble out of
|
47
|
+
# `EE.wrap` block.
|
26
48
|
def wrap_active
|
27
|
-
!!
|
49
|
+
!!local_hash[:wrap_active]
|
28
50
|
end
|
29
51
|
|
30
52
|
alias_method :wrap_active?, :wrap_active
|
31
53
|
alias_method :enabled?, :enabled
|
32
|
-
end
|
33
54
|
|
34
|
-
self.wrap_active = false
|
35
55
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
56
|
+
# Wrap the provided block - intercepting all exceptions
|
57
|
+
# that bubble out, provided they satisfy the
|
58
|
+
# assertion in `PryExceptionExplorer.intercept`.
|
59
|
+
# @yield The block to wrap.
|
60
|
+
def wrap
|
61
|
+
old_enabled, old_wrap_active = enabled, wrap_active
|
62
|
+
self.enabled = true
|
63
|
+
self.wrap_active = true
|
64
|
+
yield
|
65
|
+
rescue Exception => ex
|
66
|
+
if ex.should_intercept?
|
67
|
+
enter_exception(ex)
|
68
|
+
else
|
69
|
+
raise ex
|
70
|
+
end
|
71
|
+
ensure
|
72
|
+
self.enabled = old_enabled
|
73
|
+
self.wrap_active = old_wrap_active
|
43
74
|
end
|
44
75
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
76
|
+
# This method allows the user to assert the situations where an
|
77
|
+
# exception interception occurs.
|
78
|
+
# This method can be invoked in two ways. The general form takes a
|
79
|
+
# block, the block is passed both the frame where the exception was
|
80
|
+
# raised, and the exception itself. The user then creates an
|
81
|
+
# assertion (a stack-assertion)
|
82
|
+
# based on these attributes. If the assertion is later satisfied by
|
83
|
+
# a raised exception, that exception will be intercepted.
|
84
|
+
# In the second form, the method simply takes an exception class, or
|
85
|
+
# a number of exception classes. If one of these exceptions is
|
86
|
+
# raised, it will be intercepted.
|
87
|
+
# @param [Array] exceptions The exception classes that will be intercepted.
|
88
|
+
# @yield [lazy_frame, exception] The block that determines whether an exception will be intercepted.
|
89
|
+
# @yieldparam [PryExceptionExplorer::Lazyframe] frame The frame
|
90
|
+
# where the exception was raised.
|
91
|
+
# @yieldparam [Exception] exception The exception that was raised.
|
92
|
+
# @yieldreturn [Boolean] The result of the stack assertion.
|
93
|
+
# @example First form: Assert method name is `toad` and exception is an `ArgumentError`
|
94
|
+
# PryExceptionExplorer.intercept do |frame, ex|
|
95
|
+
# frame.method_name == :toad && ex.is_a?(ArgumentError)
|
96
|
+
# end
|
97
|
+
# @example Second form: Assert exception is either `ArgumentError` or `RuntimeError`
|
98
|
+
# PryExceptionExplorer.intercept(ArgumentError, RuntimeError)
|
99
|
+
def intercept(*exceptions, &block)
|
100
|
+
return if exceptions.empty? && block.nil?
|
101
|
+
|
102
|
+
options = (exceptions.pop if exceptions.last.is_a?(Hash)) || {}
|
103
|
+
|
104
|
+
if !exceptions.empty?
|
105
|
+
block = proc { |_, ex| exceptions.any? { |v| v === ex } }
|
106
|
+
end
|
51
107
|
|
52
|
-
|
53
|
-
if intercept_block
|
54
|
-
intercept_block.call(LazyFrame.new(frame), ex)
|
55
|
-
else
|
56
|
-
false
|
108
|
+
local_hash[:intercept_object] = Intercept.new(block, options)
|
57
109
|
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.enter_exception_inline(ex)
|
61
|
-
_pry_ = Pry.new
|
62
|
-
|
63
|
-
Pry.initial_session_setup
|
64
|
-
PryStackExplorer.create_and_push_frame_manager(ex.exception_call_stack, _pry_)
|
65
|
-
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
66
|
-
PryStackExplorer.frame_manager(_pry_).user[:inline_exception] = true
|
67
|
-
_pry_.repl(ex.exception_call_stack.first)
|
68
|
-
|
69
|
-
ensure
|
70
|
-
PryStackExplorer.clear_frame_managers(_pry_)
|
71
|
-
end
|
72
|
-
end
|
73
110
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
attr_accessor :exception_call_stack
|
79
|
-
attr_accessor :should_capture
|
80
|
-
|
81
|
-
def continue
|
82
|
-
raise NoContinuation unless continuation.respond_to?(:call)
|
83
|
-
continuation.call
|
84
|
-
end
|
111
|
+
# @return [PryExceptionExplorer::Intercept] The object defined earlier by a call to `PryExceptionExplorer.intercept`.
|
112
|
+
def intercept_object=(b)
|
113
|
+
local_hash[:intercept_object] = b
|
114
|
+
end
|
85
115
|
|
86
|
-
|
87
|
-
|
116
|
+
# @return [PryExceptionExplorer::Intercept] The object defined earlier by a call to `PryExceptionExplorer.intercept`.
|
117
|
+
def intercept_object
|
118
|
+
local_hash[:intercept_object]
|
119
|
+
end
|
88
120
|
|
89
|
-
|
90
|
-
|
121
|
+
# This method invokes the `PryExceptionExplorer.intercept_object`,
|
122
|
+
# passing in the exception's frame and the exception object itself.
|
123
|
+
# @param [Binding] frame The stack frame where the exception occurred.
|
124
|
+
# @param [Exception] ex The exception that was raised.
|
125
|
+
# @return [Boolean] Whether the exception should be intercepted.
|
126
|
+
def should_intercept_exception?(frame, ex)
|
127
|
+
if intercept_object
|
128
|
+
intercept_object.call(LazyFrame.new(frame), ex)
|
129
|
+
else
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
91
133
|
|
92
|
-
|
93
|
-
|
94
|
-
|
134
|
+
# Prepare the `Pry` instance and associated call-stack when entering
|
135
|
+
# into an exception context.
|
136
|
+
# @param [Exception] ex The exception.
|
137
|
+
# @param [Pry] _pry_ The relevant `Pry` instance.
|
138
|
+
# @param [Hash] options The optional configuration parameters.
|
139
|
+
# @option options [Boolean] :inline Whether the exception is being
|
140
|
+
# entered inline (i.e within the `raise` method itself)
|
141
|
+
def setup_exception_context(ex, _pry_, options={})
|
142
|
+
_pry_.last_exception = ex
|
143
|
+
_pry_.backtrace = ex.backtrace
|
144
|
+
|
145
|
+
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
146
|
+
PryStackExplorer.frame_manager(_pry_).user[:inline_exception] = !!options[:inline]
|
95
147
|
end
|
96
148
|
|
97
|
-
|
98
|
-
ex.
|
149
|
+
# Enter the exception context.
|
150
|
+
# @param [Exception] ex The exception.
|
151
|
+
# @param [Hash] options The optional configuration parameters.
|
152
|
+
# @option options [Boolean] :inline Whether the exception is being
|
153
|
+
# entered inline (i.e within the `raise` method itself)
|
154
|
+
def enter_exception(ex, options={})
|
155
|
+
hooks = Pry.config.hooks.dup.add_hook(:before_session, :set_exception_flag) do |_, _, _pry_|
|
156
|
+
setup_exception_context(ex, _pry_, options)
|
157
|
+
end.add_hook(:before_session, :manage_intercept_recurse) do
|
158
|
+
PryExceptionExplorer.intercept_object.disable! if !PryExceptionExplorer.intercept_object.intercept_recurse?
|
159
|
+
end.add_hook(:after_session, :manage_intercept_recurse) do
|
160
|
+
PryExceptionExplorer.intercept_object.enable! if !PryExceptionExplorer.intercept_object.active?
|
161
|
+
end
|
99
162
|
|
100
|
-
|
101
|
-
if !PryExceptionExplorer.enabled?
|
102
|
-
return super(ex)
|
163
|
+
Pry.start self, :call_stack => ex.exception_call_stack, :hooks => hooks
|
103
164
|
end
|
104
165
|
|
105
|
-
|
106
|
-
|
107
|
-
|
166
|
+
# Set initial state
|
167
|
+
def init
|
168
|
+
# disable by default (intercept exceptions inline)
|
169
|
+
PryExceptionExplorer.wrap_active = false
|
108
170
|
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
end
|
171
|
+
# default is to capture all exceptions
|
172
|
+
PryExceptionExplorer.intercept { true }
|
113
173
|
|
114
|
-
|
115
|
-
|
116
|
-
ex.continuation = cc
|
117
|
-
super(ex)
|
118
|
-
end
|
174
|
+
# disable by default
|
175
|
+
PryExceptionExplorer.enabled = false
|
119
176
|
end
|
120
177
|
end
|
121
178
|
end
|
122
179
|
|
180
|
+
# Add a hook to enable EE when invoked via `pry` executable
|
181
|
+
Pry.config.hooks.add_hook(:when_started, :try_enable_exception_explorer) do
|
182
|
+
if Pry.cli
|
183
|
+
PryExceptionExplorer.wrap_active = true
|
184
|
+
PryExceptionExplorer.enabled = true
|
185
|
+
end
|
186
|
+
end
|
123
187
|
|
124
|
-
#
|
125
|
-
# immediately at point of 'raise')
|
126
|
-
PryExceptionExplorer.wrap_active = true
|
127
|
-
|
128
|
-
# default is to capture all exceptions that bubble to the top
|
129
|
-
PryExceptionExplorer.intercept { true }
|
130
|
-
|
188
|
+
# Bring in commands
|
131
189
|
Pry.config.commands.import PryExceptionExplorer::Commands
|
132
190
|
|
133
|
-
#
|
134
|
-
PryExceptionExplorer.
|
191
|
+
# Set initial state
|
192
|
+
PryExceptionExplorer.init
|
193
|
+
|
135
194
|
|
136
|
-
Pry.config.hooks.add_hook(:when_started, :try_enable_exception_explorer) do
|
137
|
-
PryExceptionExplorer.enabled = true if Pry.cli
|
138
|
-
end
|
@@ -2,14 +2,14 @@
|
|
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.1pre6"
|
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-28"
|
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", "examples/
|
12
|
+
s.files = [".gemtest", ".gitignore", ".travis.yml", ".yardopts", "CHANGELOG", "Gemfile", "LICENSE", "README.md", "Rakefile", "examples/example_inline.rb", "examples/example_wrap.rb", "lib/pry-exception_explorer.rb", "lib/pry-exception_explorer/cli.rb", "lib/pry-exception_explorer/commands.rb", "lib/pry-exception_explorer/core_ext.rb", "lib/pry-exception_explorer/intercept.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"
|
data/test/helper.rb
CHANGED
@@ -17,8 +17,6 @@ class OpenStruct
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
EE = PryExceptionExplorer
|
21
|
-
|
22
20
|
class Ratty
|
23
21
|
def ratty
|
24
22
|
Weasel.new.weasel
|
@@ -45,7 +43,7 @@ class << Pry
|
|
45
43
|
Pry.color = false
|
46
44
|
Pry.pager = false
|
47
45
|
Pry.config.should_load_rc = false
|
48
|
-
Pry.config.
|
46
|
+
Pry.config.should_load_plugins = false
|
49
47
|
Pry.config.history.should_load = false
|
50
48
|
Pry.config.history.should_save = false
|
51
49
|
Pry.config.auto_indent = false
|
@@ -44,6 +44,36 @@ describe PryExceptionExplorer do
|
|
44
44
|
mock_pry("Ratty.new.ratty", "enter-exception", "show-stack", "exit").should =~ /toad.*?weasel.*?ratty/m
|
45
45
|
end
|
46
46
|
|
47
|
+
describe "enabled = false" do
|
48
|
+
it 'should prevent moving into an exception' do
|
49
|
+
old_e = PryExceptionExplorer.enabled
|
50
|
+
PryExceptionExplorer.enabled = false
|
51
|
+
|
52
|
+
mock_pry("Ratty.new.ratty", "enter-exception", "exit-all").should =~ /can't be entered/
|
53
|
+
|
54
|
+
PryExceptionExplorer.enabled = old_e
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "continue-exception" do
|
59
|
+
it 'should continue the exception' do
|
60
|
+
o = OpenStruct.new
|
61
|
+
def o.test_method
|
62
|
+
raise "baby likes to raise an exception"
|
63
|
+
self.value = 10
|
64
|
+
end
|
65
|
+
|
66
|
+
redirect_pry_io(InputTester.new("test_method",
|
67
|
+
"enter-exception",
|
68
|
+
"continue-exception",
|
69
|
+
"exit-all")) do
|
70
|
+
Pry.start(o)
|
71
|
+
end
|
72
|
+
|
73
|
+
o.value.should == 10
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
47
77
|
describe "exit-exception" do
|
48
78
|
it 'should display error message when exit-exception used outside of exception context' do
|
49
79
|
mock_pry("exit-exception").should =~ /You are not in an exception!/
|
@@ -88,6 +118,115 @@ describe PryExceptionExplorer do
|
|
88
118
|
# Ratty -> Weasel -> Toad (raise is here)
|
89
119
|
O.exception_self.is_a?(Toad).should == true
|
90
120
|
end
|
121
|
+
|
122
|
+
|
123
|
+
describe "_ex_" do
|
124
|
+
it "should correctly update _ex_ to reflect exception context" do
|
125
|
+
o = Object.new
|
126
|
+
class << o
|
127
|
+
attr_accessor :first_backtrace, :actual_first_backtrace
|
128
|
+
attr_accessor :second_backtrace, :actual_second_backtrace
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
redirect_pry_io(InputTester.new("raise ArgumentError, 'yo yo'",
|
133
|
+
"self.first_backtrace = _ex_.backtrace",
|
134
|
+
"enter-exception",
|
135
|
+
"self.actual_first_backtrace = _ex_.backtrace",
|
136
|
+
"raise RuntimeError, 'bing bong'",
|
137
|
+
"self.second_backtrace = _ex_.backtrace",
|
138
|
+
"enter-exception",
|
139
|
+
"self.actual_second_backtrace = _ex_.backtrace",
|
140
|
+
"exit-all", StringIO.new)) do
|
141
|
+
Pry.start(o)
|
142
|
+
end
|
143
|
+
|
144
|
+
o.first_backtrace.should == o.actual_first_backtrace
|
145
|
+
o.second_backtrace.should == o.actual_second_backtrace
|
146
|
+
|
147
|
+
# ensure nothing weird going on
|
148
|
+
o.first_backtrace.should.not == o.second_backtrace
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should correctly restore _ex_ when exiting out of exceptions" do
|
152
|
+
o = Object.new
|
153
|
+
class << o
|
154
|
+
attr_accessor :first_backtrace, :restored_first_backtrace
|
155
|
+
attr_accessor :second_backtrace, :restored_second_backtrace
|
156
|
+
end
|
157
|
+
|
158
|
+
redirect_pry_io(InputTester.new("raise ArgumentError, 'yo yo'",
|
159
|
+
"enter-exception",
|
160
|
+
"self.first_backtrace = _ex_.backtrace",
|
161
|
+
"raise RuntimeError, 'bing bong'",
|
162
|
+
"enter-exception",
|
163
|
+
"self.second_backtrace = _ex_.backtrace",
|
164
|
+
"exit-exception",
|
165
|
+
"exit-exception",
|
166
|
+
"self.restored_first_backtrace = _ex_.backtrace",
|
167
|
+
"exit-all", StringIO.new)) do
|
168
|
+
Pry.start(o)
|
169
|
+
end
|
170
|
+
|
171
|
+
# just ensure nothing weird is happening (probably unnecessary)
|
172
|
+
o.first_backtrace.should.not == o.second_backtrace
|
173
|
+
|
174
|
+
o.first_backtrace.should == o.restored_first_backtrace
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "_pry_.backtrace" do
|
179
|
+
it "should correctly update _pry_.backtrace to reflect exception context" do
|
180
|
+
o = Object.new
|
181
|
+
class << o
|
182
|
+
attr_accessor :first_backtrace, :ex_first_backtrace
|
183
|
+
attr_accessor :second_backtrace, :ex_second_backtrace
|
184
|
+
end
|
185
|
+
|
186
|
+
redirect_pry_io(InputTester.new("raise ArgumentError, 'yo yo'",
|
187
|
+
"enter-exception",
|
188
|
+
"self.first_backtrace = _pry_.backtrace",
|
189
|
+
"self.ex_first_backtrace = _ex_.backtrace",
|
190
|
+
"raise RuntimeError, 'bing bong'",
|
191
|
+
"enter-exception",
|
192
|
+
"self.second_backtrace = _pry_.backtrace",
|
193
|
+
"self.ex_second_backtrace = _ex_.backtrace",
|
194
|
+
"exit-all", StringIO.new)) do
|
195
|
+
Pry.start(o)
|
196
|
+
end
|
197
|
+
|
198
|
+
o.first_backtrace.should == o.ex_first_backtrace
|
199
|
+
o.second_backtrace.should == o.ex_second_backtrace
|
200
|
+
|
201
|
+
o.first_backtrace.should.not == o.second_backtrace
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should correctly restore _pry_.backtrace when exiting out of exceptions" do
|
205
|
+
o = Object.new
|
206
|
+
class << o
|
207
|
+
attr_accessor :first_backtrace, :restored_first_backtrace
|
208
|
+
attr_accessor :second_backtrace, :restored_second_backtrace
|
209
|
+
end
|
210
|
+
|
211
|
+
redirect_pry_io(InputTester.new("raise ArgumentError, 'yo yo'",
|
212
|
+
"enter-exception",
|
213
|
+
"self.first_backtrace = _pry_.backtrace",
|
214
|
+
"raise RuntimeError, 'bing bong'",
|
215
|
+
"enter-exception",
|
216
|
+
"self.second_backtrace = _pry_.backtrace",
|
217
|
+
"exit-exception",
|
218
|
+
"self.restored_first_backtrace = _pry_.backtrace",
|
219
|
+
"exit-all", StringIO.new)) do
|
220
|
+
|
221
|
+
Pry.start(o)
|
222
|
+
end
|
223
|
+
|
224
|
+
o.first_backtrace.should.not == o.second_backtrace
|
225
|
+
o.first_backtrace.should == o.restored_first_backtrace
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
|
91
230
|
end
|
92
231
|
end
|
93
232
|
end
|
@@ -7,7 +7,7 @@ O = OpenStruct.new
|
|
7
7
|
prev_wrap_state = PryExceptionExplorer.wrap_active
|
8
8
|
PryExceptionExplorer.wrap_active = false
|
9
9
|
|
10
|
-
prev_intercept_state = PryExceptionExplorer.
|
10
|
+
prev_intercept_state = PryExceptionExplorer.intercept_object
|
11
11
|
|
12
12
|
describe PryExceptionExplorer do
|
13
13
|
|
@@ -19,14 +19,102 @@ describe PryExceptionExplorer do
|
|
19
19
|
# started) that this is registered by setting state on `O`
|
20
20
|
Pry.config.input = StringIO.new("O.exception_intercepted = true\ncontinue-exception")
|
21
21
|
Pry.config.output = StringIO.new
|
22
|
+
Pry.config.hooks.add_hook(:when_started, :save_caller_bindings, WhenStartedHook)
|
23
|
+
Pry.config.hooks.add_hook(:after_session, :delete_frame_manager, AfterSessionHook)
|
22
24
|
end
|
23
25
|
|
24
26
|
after do
|
25
27
|
Pry.config.input.rewind
|
28
|
+
Pry.config.hooks.delete_hook(:when_started, :save_caller_bindings)
|
29
|
+
Pry.config.hooks.delete_hook(:after_session, :delete_frame_manager)
|
26
30
|
O.clear
|
27
31
|
end
|
28
32
|
|
33
|
+
describe "enabled = false" do
|
34
|
+
it 'should prevent interception of an exception' do
|
35
|
+
old_e = PryExceptionExplorer.enabled
|
36
|
+
PryExceptionExplorer.enabled = false
|
37
|
+
|
38
|
+
my_error = Class.new(StandardError)
|
39
|
+
EE.intercept(my_error)
|
40
|
+
|
41
|
+
begin
|
42
|
+
raise my_error
|
43
|
+
rescue => ex
|
44
|
+
exception = ex
|
45
|
+
end
|
46
|
+
|
47
|
+
exception.is_a?(my_error).should == true
|
48
|
+
|
49
|
+
PryExceptionExplorer.enabled = old_e
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
29
53
|
describe "PryExceptionExplorer.intercept" do
|
54
|
+
it 'should be a no-op when intercept called with no parameters' do
|
55
|
+
b = proc {}
|
56
|
+
old = EE.intercept_object
|
57
|
+
EE.intercept &b
|
58
|
+
EE.intercept
|
59
|
+
EE.intercept_object.block.should == b
|
60
|
+
EE.intercept_object = old
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "intercept_recurse" do
|
64
|
+
it 'should NOT allow recursive (in-session) interceptions by default' do
|
65
|
+
EE.intercept { |frame, ex| frame.klass == Toad }
|
66
|
+
|
67
|
+
redirect_pry_io(InputTester.new("O.before_self = self",
|
68
|
+
"Ratty.new.ratty",
|
69
|
+
"O.after_self = self",
|
70
|
+
"continue-exception",
|
71
|
+
"continue-exception")) do
|
72
|
+
Ratty.new.ratty
|
73
|
+
end
|
74
|
+
|
75
|
+
O.before_self.should == O.after_self
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should allow recursive (in-session) interceptions when :intercept_recurse => true' do
|
79
|
+
EE.intercept(:intercept_recurse => true) { |frame, ex| frame.klass == Toad }
|
80
|
+
|
81
|
+
redirect_pry_io(InputTester.new("O.before_self = self",
|
82
|
+
"Ratty.new.ratty",
|
83
|
+
"O.after_self = self",
|
84
|
+
"continue-exception",
|
85
|
+
"continue-exception")) do
|
86
|
+
Ratty.new.ratty
|
87
|
+
end
|
88
|
+
|
89
|
+
O.before_self.should.not == O.after_self
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "skip" do
|
95
|
+
it 'should skip first frame with :skip => 1' do
|
96
|
+
EE.intercept(:skip => 1) { |frame, ex| frame.klass == Toad }
|
97
|
+
|
98
|
+
redirect_pry_io(InputTester.new("O.method_name = __method__",
|
99
|
+
"continue-exception")) do
|
100
|
+
Ratty.new.ratty
|
101
|
+
end
|
102
|
+
|
103
|
+
O.method_name.should == :weasel
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should skip first two framed with :skip => 2' do
|
107
|
+
EE.intercept(:skip => 2) { |frame, ex| frame.klass == Toad }
|
108
|
+
|
109
|
+
redirect_pry_io(InputTester.new("O.method_name = __method__",
|
110
|
+
"continue-exception")) do
|
111
|
+
Ratty.new.ratty
|
112
|
+
end
|
113
|
+
|
114
|
+
O.method_name.should == :ratty
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
30
118
|
describe "special case exception-only syntax" do
|
31
119
|
|
32
120
|
describe "single exception" do
|
@@ -101,7 +189,12 @@ describe PryExceptionExplorer do
|
|
101
189
|
describe "second frame" do
|
102
190
|
it "should intercept exception based on second frame's method name" do
|
103
191
|
EE.intercept { |frame, ex| frame.prev.klass == Weasel }
|
104
|
-
|
192
|
+
begin
|
193
|
+
Ratty.new.ratty
|
194
|
+
rescue => ex
|
195
|
+
Pry.new(:input => Readline, :output =>
|
196
|
+
$stdout).repl(binding)
|
197
|
+
end
|
105
198
|
O.exception_intercepted.should == true
|
106
199
|
end
|
107
200
|
|
@@ -251,12 +344,29 @@ describe PryExceptionExplorer do
|
|
251
344
|
|
252
345
|
end
|
253
346
|
|
347
|
+
describe "exit-exception" do
|
348
|
+
it 'should exit session and raise exception' do
|
349
|
+
my_error = Class.new(StandardError)
|
350
|
+
EE.intercept(my_error)
|
351
|
+
|
352
|
+
begin
|
353
|
+
redirect_pry_io(InputTester.new("exit-exception")) do
|
354
|
+
raise my_error
|
355
|
+
end
|
356
|
+
rescue => ex
|
357
|
+
exception = ex
|
358
|
+
end
|
359
|
+
|
360
|
+
exception.is_a?(my_error).should == true
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
254
364
|
end
|
255
365
|
|
256
366
|
end
|
257
367
|
|
258
368
|
# restore to default
|
259
369
|
PryExceptionExplorer.wrap_active = prev_wrap_state
|
260
|
-
PryExceptionExplorer.
|
370
|
+
PryExceptionExplorer.intercept_object = prev_intercept_state
|
261
371
|
|
262
372
|
Object.send(:remove_const, :O)
|
@@ -1,19 +1,15 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
|
-
require 'pry-exception_explorer/exception_wrap'
|
4
|
-
|
5
3
|
CaughtException = Class.new(StandardError)
|
6
4
|
UncaughtException = Class.new(StandardError)
|
7
5
|
|
8
|
-
|
9
6
|
describe PryExceptionExplorer do
|
10
7
|
|
11
|
-
|
12
8
|
before do
|
13
9
|
Pry.config.input = StringIO.new("exit :caught\n")
|
14
10
|
Pry.config.output = StringIO.new
|
15
|
-
Pry.config.hooks.add_hook(:when_started, :save_caller_bindings,
|
16
|
-
Pry.config.hooks.add_hook(:after_session, :delete_frame_manager,
|
11
|
+
Pry.config.hooks.add_hook(:when_started, :save_caller_bindings, WhenStartedHook)
|
12
|
+
Pry.config.hooks.add_hook(:after_session, :delete_frame_manager, AfterSessionHook)
|
17
13
|
end
|
18
14
|
|
19
15
|
after do
|
@@ -23,6 +19,56 @@ describe PryExceptionExplorer do
|
|
23
19
|
|
24
20
|
describe "PryExceptionExplorer.wrap" do
|
25
21
|
|
22
|
+
describe "_ex_" do
|
23
|
+
it 'should correctly set _ex_ inside session (set to raised exception)' do
|
24
|
+
ex = Class.new(StandardError)
|
25
|
+
o = Object.new
|
26
|
+
class << o; attr_accessor :ex; self; end.class_eval { define_method(:raze) { raise ex } }
|
27
|
+
|
28
|
+
PryExceptionExplorer.intercept { true }
|
29
|
+
|
30
|
+
redirect_pry_io(InputTester.new("@ex = _ex_", "exit-all")) do
|
31
|
+
PryExceptionExplorer.wrap do
|
32
|
+
o.raze
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
o.ex.is_a?(ex).should == true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "_pry_.backtrace" do
|
41
|
+
it 'should correctly set _pry_ inside session to backtrace of raised exception' do
|
42
|
+
ex = Class.new(StandardError)
|
43
|
+
o = Object.new
|
44
|
+
class << o; attr_accessor :ex, :pry_bt; self; end.class_eval { define_method(:raze) { raise ex } }
|
45
|
+
|
46
|
+
PryExceptionExplorer.intercept { true }
|
47
|
+
|
48
|
+
redirect_pry_io(InputTester.new("@ex = _ex_", "@pry_bt = _pry_.backtrace", "exit-all")) do
|
49
|
+
PryExceptionExplorer.wrap do
|
50
|
+
o.raze
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
o.pry_bt.should == o.ex.backtrace
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "enabled = false" do
|
59
|
+
it 'should have no effect for wrap block (which sets enabled=true internally)' do
|
60
|
+
old_e = PryExceptionExplorer.enabled
|
61
|
+
PryExceptionExplorer.enabled = false
|
62
|
+
|
63
|
+
PryExceptionExplorer.wrap do
|
64
|
+
raise CaughtException, "catch me if u can"
|
65
|
+
end.should == :caught
|
66
|
+
|
67
|
+
PryExceptionExplorer.enabled.should == false
|
68
|
+
PryExceptionExplorer.enabled = old_e
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
26
72
|
# use of exit-exception inside a wrapped exception is weird
|
27
73
|
# (because exit-exception is really designed for pry exceptions)
|
28
74
|
# but when we do receive one, we should exit out of pry
|
metadata
CHANGED
@@ -1,59 +1,55 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: pry-exception_explorer
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1pre7
|
4
5
|
prerelease: 5
|
5
|
-
version: 0.1.1pre5
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- John Mair (banisterfiend)
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-01-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: pry-stack_explorer
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70111600095300 !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
24
22
|
type: :runtime
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: bacon
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: *70111600095300
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bacon
|
27
|
+
requirement: &70111600094500 !ruby/object:Gem::Requirement
|
30
28
|
none: false
|
31
|
-
requirements:
|
29
|
+
requirements:
|
32
30
|
- - ~>
|
33
|
-
- !ruby/object:Gem::Version
|
31
|
+
- !ruby/object:Gem::Version
|
34
32
|
version: 1.1.0
|
35
33
|
type: :development
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: rake
|
39
34
|
prerelease: false
|
40
|
-
|
35
|
+
version_requirements: *70111600094500
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &70111600093540 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
|
-
requirements:
|
40
|
+
requirements:
|
43
41
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version:
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.9'
|
46
44
|
type: :development
|
47
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70111600093540
|
48
47
|
description: Enter the context of exceptions
|
49
48
|
email: jrmair@gmail.com
|
50
49
|
executables: []
|
51
|
-
|
52
50
|
extensions: []
|
53
|
-
|
54
51
|
extra_rdoc_files: []
|
55
|
-
|
56
|
-
files:
|
52
|
+
files:
|
57
53
|
- .gemtest
|
58
54
|
- .gitignore
|
59
55
|
- .travis.yml
|
@@ -63,11 +59,13 @@ files:
|
|
63
59
|
- LICENSE
|
64
60
|
- README.md
|
65
61
|
- Rakefile
|
66
|
-
- examples/
|
62
|
+
- examples/example_inline.rb
|
63
|
+
- examples/example_wrap.rb
|
67
64
|
- lib/pry-exception_explorer.rb
|
68
65
|
- lib/pry-exception_explorer/cli.rb
|
69
66
|
- lib/pry-exception_explorer/commands.rb
|
70
|
-
- lib/pry-exception_explorer/
|
67
|
+
- lib/pry-exception_explorer/core_ext.rb
|
68
|
+
- lib/pry-exception_explorer/intercept.rb
|
71
69
|
- lib/pry-exception_explorer/lazy_frame.rb
|
72
70
|
- lib/pry-exception_explorer/shim_builder.rb
|
73
71
|
- lib/pry-exception_explorer/version.rb
|
@@ -78,32 +76,29 @@ files:
|
|
78
76
|
- test/test_wrapped_exceptions.rb
|
79
77
|
homepage: https://github.com/banister/pry-exception_explorer
|
80
78
|
licenses: []
|
81
|
-
|
82
79
|
post_install_message:
|
83
80
|
rdoc_options: []
|
84
|
-
|
85
|
-
require_paths:
|
81
|
+
require_paths:
|
86
82
|
- lib
|
87
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
84
|
none: false
|
89
|
-
requirements:
|
90
|
-
- -
|
91
|
-
- !ruby/object:Gem::Version
|
92
|
-
version:
|
93
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
90
|
none: false
|
95
|
-
requirements:
|
96
|
-
- -
|
97
|
-
- !ruby/object:Gem::Version
|
91
|
+
requirements:
|
92
|
+
- - ! '>'
|
93
|
+
- !ruby/object:Gem::Version
|
98
94
|
version: 1.3.1
|
99
95
|
requirements: []
|
100
|
-
|
101
96
|
rubyforge_project:
|
102
97
|
rubygems_version: 1.8.11
|
103
98
|
signing_key:
|
104
99
|
specification_version: 3
|
105
100
|
summary: Enter the context of exceptions
|
106
|
-
test_files:
|
101
|
+
test_files:
|
107
102
|
- test/helper.rb
|
108
103
|
- test/test_exceptions_in_pry.rb
|
109
104
|
- test/test_inline_exceptions.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'pry-exception_explorer'
|
2
|
-
|
3
|
-
#Pry.config.hooks.delete_hook(:when_started, :save_caller_bindings)
|
4
|
-
|
5
|
-
# default is to capture all exceptions that bubble to the top
|
6
|
-
PryExceptionExplorer.intercept { true }
|
7
|
-
|
8
|
-
module PryExceptionExplorer
|
9
|
-
|
10
|
-
def self.wrap
|
11
|
-
old_enabled, old_wrap_active = enabled, wrap_active
|
12
|
-
self.enabled = true
|
13
|
-
self.wrap_active = true
|
14
|
-
yield
|
15
|
-
rescue Exception => ex
|
16
|
-
if ex.should_capture?
|
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
|
25
|
-
else
|
26
|
-
raise ex
|
27
|
-
end
|
28
|
-
ensure
|
29
|
-
self.enabled = old_enabled
|
30
|
-
self.wrap_active = old_wrap_active
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|