pry-exception_explorer 0.1.1pre5 → 0.1.1pre7
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 +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
|
-
|