pry-exception_explorer 0.1.1pre1 → 0.1.1pre3
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/.gemtest +0 -0
- data/.gitignore +7 -0
- data/.travis.yml +15 -0
- data/.yardopts +1 -0
- data/Gemfile +2 -0
- data/LICENSE +25 -0
- data/Rakefile +89 -74
- data/lib/pry-exception_explorer/commands.rb +42 -0
- data/lib/pry-exception_explorer/exception_wrap.rb +14 -2
- data/lib/pry-exception_explorer/lazy_frame.rb +32 -0
- data/lib/pry-exception_explorer/version.rb +1 -1
- data/lib/pry-exception_explorer.rb +73 -37
- data/pry-exception_explorer.gemspec +36 -0
- data/test/helper.rb +101 -0
- data/test/test_exception_explorer.rb +159 -0
- data/test/test_exceptions_in_pry.rb +29 -0
- data/test/test_wrapped_exceptions.rb +160 -0
- metadata +48 -11
- data/test/test.rb +0 -12
data/.gemtest
ADDED
File without changes
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
License
|
2
|
+
-------
|
3
|
+
|
4
|
+
(The MIT License)
|
5
|
+
|
6
|
+
Copyright (c) 2011 John Mair (banisterfiend)
|
7
|
+
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
a copy of this software and associated documentation files (the
|
10
|
+
'Software'), to deal in the Software without restriction, including
|
11
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be
|
17
|
+
included in all copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
25
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,76 +1,91 @@
|
|
1
|
-
$:.unshift 'lib'
|
2
|
-
|
3
|
-
dlext =
|
4
|
-
direc = File.dirname(__FILE__)
|
5
|
-
|
6
|
-
PROJECT_NAME = "pry-exception_explorer"
|
7
|
-
|
8
|
-
require 'rake/clean'
|
9
|
-
require 'rake/gempackagetask'
|
10
|
-
require "#{PROJECT_NAME}/version"
|
11
|
-
|
12
|
-
CLOBBER.include("**/*~", "**/*#*", "**/*.log")
|
13
|
-
CLEAN.include("**/*#*", "**/*#*.*", "**/*_flymake*.*", "**/*_flymake",
|
14
|
-
"**/*.rbc", "**/.#*.*")
|
15
|
-
|
16
|
-
def apply_spec_defaults(s)
|
17
|
-
s.name = PROJECT_NAME
|
18
|
-
s.summary = "
|
19
|
-
s.version = PryExceptionExplorer::VERSION
|
20
|
-
s.date = Time.now.strftime '%Y-%m-%d'
|
21
|
-
s.author = "John Mair (banisterfiend)"
|
22
|
-
s.email = 'jrmair@gmail.com'
|
23
|
-
s.description = s.summary
|
24
|
-
s.require_path = 'lib'
|
25
|
-
s.homepage = "https://github.com/banister/pry-exception_explorer"
|
26
|
-
|
27
|
-
s.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
1
|
+
$:.unshift 'lib'
|
2
|
+
|
3
|
+
dlext = RbConfig::CONFIG['DLEXT']
|
4
|
+
direc = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
PROJECT_NAME = "pry-exception_explorer"
|
7
|
+
|
8
|
+
require 'rake/clean'
|
9
|
+
require 'rake/gempackagetask'
|
10
|
+
require "#{PROJECT_NAME}/version"
|
11
|
+
|
12
|
+
CLOBBER.include("**/*~", "**/*#*", "**/*.log")
|
13
|
+
CLEAN.include("**/*#*", "**/*#*.*", "**/*_flymake*.*", "**/*_flymake",
|
14
|
+
"**/*.rbc", "**/.#*.*")
|
15
|
+
|
16
|
+
def apply_spec_defaults(s)
|
17
|
+
s.name = PROJECT_NAME
|
18
|
+
s.summary = "Enter the context of exceptions"
|
19
|
+
s.version = PryExceptionExplorer::VERSION
|
20
|
+
s.date = Time.now.strftime '%Y-%m-%d'
|
21
|
+
s.author = "John Mair (banisterfiend)"
|
22
|
+
s.email = 'jrmair@gmail.com'
|
23
|
+
s.description = s.summary
|
24
|
+
s.require_path = 'lib'
|
25
|
+
s.homepage = "https://github.com/banister/pry-exception_explorer"
|
26
|
+
s.add_dependency('pry-stack_explorer')
|
27
|
+
s.add_development_dependency("bacon","~>1.1.0")
|
28
|
+
s.add_development_dependency('rake', '~> 0.9')
|
29
|
+
|
30
|
+
s.files = `git ls-files`.split("\n")
|
31
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "run pry with plugin enabled"
|
35
|
+
task :pry do
|
36
|
+
exec("pry -I#{direc}/lib/ -r #{direc}/lib/#{PROJECT_NAME}")
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "reinstall gem"
|
40
|
+
task :reinstall => :gems do
|
41
|
+
sh "rm -rf ~/.pry-exception_explorer"
|
37
42
|
sh "gem uninstall pry-exception_explorer" rescue nil
|
38
|
-
sh "gem install #{direc}/pkg/pry-exception_explorer-#{PryExceptionExplorer::VERSION}.gem"
|
43
|
+
sh "gem install #{direc}/pkg/pry-exception_explorer-#{PryExceptionExplorer::VERSION}.gem"
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "run tests"
|
47
|
+
task :test do
|
48
|
+
sh "bacon -Itest -rubygems -a"
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Build gemspec"
|
52
|
+
task :gemspec => "ruby:gemspec"
|
53
|
+
|
54
|
+
namespace :ruby do
|
55
|
+
spec = Gem::Specification.new do |s|
|
56
|
+
apply_spec_defaults(s)
|
57
|
+
s.platform = Gem::Platform::RUBY
|
58
|
+
end
|
59
|
+
|
60
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
61
|
+
pkg.need_zip = false
|
62
|
+
pkg.need_tar = false
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Generate gemspec file"
|
66
|
+
task :gemspec do
|
67
|
+
File.open("#{spec.name}.gemspec", "w") do |f|
|
68
|
+
f << spec.to_ruby
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "shorthand for :gems task"
|
74
|
+
task :gem => :gems
|
75
|
+
|
76
|
+
desc "build all platform gems at once"
|
77
|
+
task :gems => [:clean, :rmgems, "ruby:gem"]
|
78
|
+
|
79
|
+
desc "remove all platform gems"
|
80
|
+
task :rmgems => ["ruby:clobber_package"]
|
81
|
+
|
82
|
+
desc "build and push latest gems"
|
83
|
+
task :pushgems => :gems do
|
84
|
+
chdir("#{File.dirname(__FILE__)}/pkg") do
|
85
|
+
Dir["*.gem"].each do |gemfile|
|
86
|
+
sh "gem push #{gemfile}"
|
87
|
+
end
|
88
|
+
end
|
39
89
|
end
|
40
|
-
|
41
|
-
|
42
|
-
task :test do
|
43
|
-
sh "bacon -Itest -rubygems -a"
|
44
|
-
end
|
45
|
-
|
46
|
-
namespace :ruby do
|
47
|
-
spec = Gem::Specification.new do |s|
|
48
|
-
apply_spec_defaults(s)
|
49
|
-
s.platform = Gem::Platform::RUBY
|
50
|
-
end
|
51
|
-
|
52
|
-
Rake::GemPackageTask.new(spec) do |pkg|
|
53
|
-
pkg.need_zip = false
|
54
|
-
pkg.need_tar = false
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
desc "shorthand for :gems task"
|
59
|
-
task :gem => :gems
|
60
|
-
|
61
|
-
desc "build all platform gems at once"
|
62
|
-
task :gems => [:clean, :rmgems, "ruby:gem"]
|
63
|
-
|
64
|
-
desc "remove all platform gems"
|
65
|
-
task :rmgems => ["ruby:clobber_package"]
|
66
|
-
|
67
|
-
desc "build and push latest gems"
|
68
|
-
task :pushgems => :gems do
|
69
|
-
chdir("#{File.dirname(__FILE__)}/pkg") do
|
70
|
-
Dir["*.gem"].each do |gemfile|
|
71
|
-
sh "gem push #{gemfile}"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
|
90
|
+
|
91
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'pry-stack_explorer'
|
2
|
+
|
3
|
+
PryExceptionExplorer::Commands = Pry::CommandSet.new do
|
4
|
+
|
5
|
+
command "enter-exception", "Enter the context of the last exception" do
|
6
|
+
ex = _pry_.last_exception
|
7
|
+
if ex && ex.exception_call_stack
|
8
|
+
PryStackExplorer.create_and_push_frame_manager(ex.exception_call_stack, _pry_)
|
9
|
+
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
10
|
+
PryStackExplorer.frame_manager(_pry_).refresh_frame
|
11
|
+
elsif ex
|
12
|
+
output.puts "Current exception can't be entered! (perhaps a C exception)"
|
13
|
+
else
|
14
|
+
output.puts "No exception to enter!"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
command "exit-exception", "Leave the context of the current exception." do
|
19
|
+
fm = PryStackExplorer.frame_manager(_pry_)
|
20
|
+
if fm && fm.user[:exception]
|
21
|
+
PryStackExplorer.pop_frame_manager(_pry_)
|
22
|
+
PryStackExplorer.frame_manager(_pry_).refresh_frame
|
23
|
+
else
|
24
|
+
output.puts "You are not in an exception!"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
command "continue-exception", "Attempt to continue the current exception." do
|
29
|
+
fm = PryStackExplorer.frame_manager(_pry_)
|
30
|
+
|
31
|
+
if fm && fm.user[:exception] && fm.user[:inline_exception]
|
32
|
+
_pry_.run_command "exit-all PryExceptionExplorer::CONTINUE_INLINE_EXCEPTION"
|
33
|
+
PryStackExplorer.pop_frame_manager(_pry_)
|
34
|
+
elsif fm && fm.user[:exception] && fm.user[:exception].continuation
|
35
|
+
PryStackExplorer.pop_frame_manager(_pry_)
|
36
|
+
fm.user[:exception].continue
|
37
|
+
else
|
38
|
+
output.puts "No exception to continue!"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -1,9 +1,14 @@
|
|
1
|
-
require '
|
1
|
+
require 'pry-exception_explorer'
|
2
2
|
|
3
3
|
Pry.config.hooks.delete_hook(:when_started, :save_caller_bindings)
|
4
4
|
|
5
|
+
# default is to capture all exceptions that bubble to the top
|
6
|
+
PryExceptionExplorer.intercept { true }
|
7
|
+
|
5
8
|
module PryExceptionExplorer
|
9
|
+
|
6
10
|
def self.wrap
|
11
|
+
self.wrap_active = true
|
7
12
|
yield
|
8
13
|
rescue Exception => ex
|
9
14
|
Pry.config.hooks.add_hook(:when_started, :setup_exception_context) do |binding_stack, _pry_|
|
@@ -12,6 +17,13 @@ module PryExceptionExplorer
|
|
12
17
|
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
13
18
|
end
|
14
19
|
|
15
|
-
|
20
|
+
if ex.should_capture?
|
21
|
+
pry
|
22
|
+
else
|
23
|
+
raise ex
|
24
|
+
end
|
25
|
+
ensure
|
26
|
+
self.wrap_active = false
|
16
27
|
end
|
17
28
|
end
|
29
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module PryExceptionExplorer
|
2
|
+
class LazyFrame
|
3
|
+
|
4
|
+
# we need to jump over a few irrelevant frames to begin with
|
5
|
+
START_FRAME_OFFSET = 5
|
6
|
+
|
7
|
+
def initialize(frame, frame_counter = 0)
|
8
|
+
@frame = frame
|
9
|
+
@frame_counter = frame_counter
|
10
|
+
end
|
11
|
+
|
12
|
+
def raw_frame
|
13
|
+
@frame
|
14
|
+
end
|
15
|
+
|
16
|
+
def klass
|
17
|
+
@frame.eval("self.class")
|
18
|
+
end
|
19
|
+
|
20
|
+
def self
|
21
|
+
@frame.eval("self")
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_name
|
25
|
+
@frame.eval("__method__")
|
26
|
+
end
|
27
|
+
|
28
|
+
def prev
|
29
|
+
LazyFrame.new(binding.of_caller(@frame_counter + START_FRAME_OFFSET), @frame_counter + 1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -3,22 +3,78 @@
|
|
3
3
|
|
4
4
|
require 'pry-stack_explorer'
|
5
5
|
require "pry-exception_explorer/version"
|
6
|
+
require "pry-exception_explorer/lazy_frame"
|
7
|
+
require "pry-exception_explorer/commands"
|
6
8
|
require "pry"
|
7
9
|
|
8
10
|
if RUBY_VERSION =~ /1.9/
|
9
11
|
require 'continuation'
|
10
12
|
end
|
11
13
|
|
14
|
+
module PryExceptionExplorer
|
15
|
+
CONTINUE_INLINE_EXCEPTION = Object.new
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def wrap_active=(v)
|
19
|
+
Thread.current[:__pry_exception_explorer_wrap__] = v
|
20
|
+
end
|
21
|
+
|
22
|
+
def wrap_active
|
23
|
+
!!Thread.current[:__pry_exception_explorer_wrap__]
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :wrap_active?, :wrap_active
|
27
|
+
end
|
28
|
+
|
29
|
+
self.wrap_active = false
|
30
|
+
|
31
|
+
def self.should_capture_exception?(ex)
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.intercept(&block)
|
36
|
+
Thread.current[:__pry_exception_explorer_intercept_block__] = block
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.intercept_block
|
40
|
+
Thread.current[:__pry_exception_explorer_intercept_block__]
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.should_capture_exception?(ex, frame)
|
44
|
+
if intercept_block
|
45
|
+
intercept_block.call(LazyFrame.new(frame), ex)
|
46
|
+
else
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.enter_exception_inline(ex)
|
52
|
+
_pry_ = Pry.new
|
53
|
+
|
54
|
+
Pry.initial_session_setup
|
55
|
+
PryStackExplorer.create_and_push_frame_manager(ex.exception_call_stack, _pry_)
|
56
|
+
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
57
|
+
PryStackExplorer.frame_manager(_pry_).user[:inline_exception] = true
|
58
|
+
_pry_.repl(ex.exception_call_stack.first)
|
59
|
+
|
60
|
+
ensure
|
61
|
+
PryStackExplorer.clear_frame_managers(_pry_)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
12
65
|
class Exception
|
13
66
|
NoContinuation = Class.new(StandardError)
|
14
67
|
|
15
68
|
attr_accessor :continuation
|
16
69
|
attr_accessor :exception_call_stack
|
70
|
+
attr_accessor :should_capture
|
17
71
|
|
18
72
|
def continue
|
19
73
|
raise NoContinuation unless continuation.respond_to?(:call)
|
20
74
|
continuation.call
|
21
75
|
end
|
76
|
+
|
77
|
+
alias_method :should_capture?, :should_capture
|
22
78
|
end
|
23
79
|
|
24
80
|
class Object
|
@@ -30,51 +86,31 @@ class Object
|
|
30
86
|
|
31
87
|
ex = exception.exception(string)
|
32
88
|
ex.set_backtrace(array)
|
33
|
-
ex.exception_call_stack = binding.callers.tap(&:shift)
|
34
|
-
|
35
|
-
callcc do |cc|
|
36
|
-
ex.continuation = cc
|
37
|
-
super(ex)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
89
|
|
42
|
-
PryExceptionExplorer
|
90
|
+
if PryExceptionExplorer.should_capture_exception?(ex, binding.of_caller(1))
|
91
|
+
ex.exception_call_stack = binding.callers.tap(&:shift)
|
92
|
+
ex.should_capture = true
|
43
93
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
PryStackExplorer.create_and_push_frame_manager(ex.exception_call_stack, _pry_)
|
48
|
-
PryStackExplorer.frame_manager(_pry_).user[:exception] = ex
|
49
|
-
PryStackExplorer.frame_manager(_pry_).refresh_frame
|
50
|
-
elsif ex
|
51
|
-
output.puts "Current exception can't be entered! (perhaps a C exception)"
|
52
|
-
else
|
53
|
-
output.puts "No exception to enter!"
|
94
|
+
if !PryExceptionExplorer.wrap_active?
|
95
|
+
retval = PryExceptionExplorer.enter_exception_inline(ex)
|
96
|
+
end
|
54
97
|
end
|
55
|
-
end
|
56
98
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
else
|
63
|
-
output.puts "You are not in an exception!"
|
99
|
+
if retval != PryExceptionExplorer::CONTINUE_INLINE_EXCEPTION
|
100
|
+
callcc do |cc|
|
101
|
+
ex.continuation = cc
|
102
|
+
super(ex)
|
103
|
+
end
|
64
104
|
end
|
65
105
|
end
|
106
|
+
end
|
66
107
|
|
67
|
-
command "continue-exception", "Attempt to continue the current exception." do
|
68
|
-
fm = PryStackExplorer.frame_manager(_pry_)
|
69
108
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
else
|
74
|
-
output.puts "No exception to continue!"
|
75
|
-
end
|
76
|
-
end
|
109
|
+
# Let exceptions get caught by Pry REPL loop (i.e dont catch
|
110
|
+
# immediately at point of 'raise')
|
111
|
+
PryExceptionExplorer.wrap_active = true
|
77
112
|
|
78
|
-
|
113
|
+
# default is to capture all exceptions that bubble to the top
|
114
|
+
PryExceptionExplorer.intercept { true }
|
79
115
|
|
80
116
|
Pry.config.commands.import PryExceptionExplorer::Commands
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "pry-exception_explorer"
|
5
|
+
s.version = "0.1.1pre3"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["John Mair (banisterfiend)"]
|
9
|
+
s.date = "2012-01-05"
|
10
|
+
s.description = "Enter the context of exceptions"
|
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/test_exception_explorer.rb", "test/test_exceptions_in_pry.rb", "test/test_wrapped_exceptions.rb"]
|
13
|
+
s.homepage = "https://github.com/banister/pry-exception_explorer"
|
14
|
+
s.require_paths = ["lib"]
|
15
|
+
s.rubygems_version = "1.8.11"
|
16
|
+
s.summary = "Enter the context of exceptions"
|
17
|
+
s.test_files = ["test/helper.rb", "test/test_exception_explorer.rb", "test/test_exceptions_in_pry.rb", "test/test_wrapped_exceptions.rb"]
|
18
|
+
|
19
|
+
if s.respond_to? :specification_version then
|
20
|
+
s.specification_version = 3
|
21
|
+
|
22
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
23
|
+
s.add_runtime_dependency(%q<pry-stack_explorer>, [">= 0"])
|
24
|
+
s.add_development_dependency(%q<bacon>, ["~> 1.1.0"])
|
25
|
+
s.add_development_dependency(%q<rake>, ["~> 0.9"])
|
26
|
+
else
|
27
|
+
s.add_dependency(%q<pry-stack_explorer>, [">= 0"])
|
28
|
+
s.add_dependency(%q<bacon>, ["~> 1.1.0"])
|
29
|
+
s.add_dependency(%q<rake>, ["~> 0.9"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<pry-stack_explorer>, [">= 0"])
|
33
|
+
s.add_dependency(%q<bacon>, ["~> 1.1.0"])
|
34
|
+
s.add_dependency(%q<rake>, ["~> 0.9"])
|
35
|
+
end
|
36
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
unless Object.const_defined? 'PryExceptionExplorer'
|
4
|
+
$:.unshift File.expand_path '../../lib', __FILE__
|
5
|
+
require 'pry-exception_explorer'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'bacon'
|
9
|
+
|
10
|
+
puts "Testing pry-exception_explorer version #{PryExceptionExplorer::VERSION}..."
|
11
|
+
puts "Ruby version: #{RUBY_VERSION}"
|
12
|
+
|
13
|
+
EE = PryExceptionExplorer
|
14
|
+
|
15
|
+
class Ratty
|
16
|
+
def ratty
|
17
|
+
Weasel.new.weasel
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Weasel
|
22
|
+
def weasel
|
23
|
+
Toad.new.toad
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Toad
|
28
|
+
def toad
|
29
|
+
raise "toad hall"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class << Pry
|
34
|
+
alias_method :orig_reset_defaults, :reset_defaults
|
35
|
+
def reset_defaults
|
36
|
+
orig_reset_defaults
|
37
|
+
|
38
|
+
Pry.color = false
|
39
|
+
Pry.pager = false
|
40
|
+
Pry.config.should_load_rc = false
|
41
|
+
Pry.config.plugins.enabled = false
|
42
|
+
Pry.config.history.should_load = false
|
43
|
+
Pry.config.history.should_save = false
|
44
|
+
Pry.config.auto_indent = false
|
45
|
+
Pry.config.hooks = Pry::Hooks.new
|
46
|
+
Pry.config.collision_warning = false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Pry.reset_defaults
|
51
|
+
|
52
|
+
class InputTester
|
53
|
+
def initialize(*actions)
|
54
|
+
if actions.last.is_a?(Hash) && actions.last.keys == [:history]
|
55
|
+
@hist = actions.pop[:history]
|
56
|
+
end
|
57
|
+
@orig_actions = actions.dup
|
58
|
+
@actions = actions
|
59
|
+
end
|
60
|
+
|
61
|
+
def readline(*)
|
62
|
+
@actions.shift.tap{ |line| @hist << line if @hist }
|
63
|
+
end
|
64
|
+
|
65
|
+
def rewind
|
66
|
+
@actions = @orig_actions.dup
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Set I/O streams.
|
71
|
+
#
|
72
|
+
# Out defaults to an anonymous StringIO.
|
73
|
+
#
|
74
|
+
def redirect_pry_io(new_in, new_out = StringIO.new)
|
75
|
+
old_in = Pry.input
|
76
|
+
old_out = Pry.output
|
77
|
+
|
78
|
+
Pry.input = new_in
|
79
|
+
Pry.output = new_out
|
80
|
+
begin
|
81
|
+
yield
|
82
|
+
ensure
|
83
|
+
Pry.input = old_in
|
84
|
+
Pry.output = old_out
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def mock_pry(*args)
|
89
|
+
|
90
|
+
binding = args.first.is_a?(Binding) ? args.shift : binding()
|
91
|
+
|
92
|
+
input = InputTester.new(*args)
|
93
|
+
output = StringIO.new
|
94
|
+
|
95
|
+
redirect_pry_io(input, output) do
|
96
|
+
binding.pry
|
97
|
+
end
|
98
|
+
|
99
|
+
output.string
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,159 @@
|
|
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
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe PryExceptionExplorer do
|
4
|
+
|
5
|
+
describe "Exceptions caught by Pry" do
|
6
|
+
describe "enter-exception" do
|
7
|
+
it "should be able to enter an exception caught by pry" do
|
8
|
+
|
9
|
+
PryExceptionExplorer.intercept { true }
|
10
|
+
|
11
|
+
# there are 3 types of situations where exception_explorer is invoked:
|
12
|
+
# 1. when 'wrap' is used, i.e only exceptions that bubble to
|
13
|
+
# the top are intercepted.
|
14
|
+
# 2. when exceptions are intercepted 'inline' (i.e dropped
|
15
|
+
# into pry directly from `raise` itself)
|
16
|
+
# 3. exceptions are caught by pry and entered into by using
|
17
|
+
# the 'enter-exception' command
|
18
|
+
# The case of 1. and 3. are actually very similar, but in
|
19
|
+
# 3. the exception never bubbles to the top as it's caught by
|
20
|
+
# pry instead; also in 3. a pry session is not started
|
21
|
+
# automatically, the user must explicitly type
|
22
|
+
# `enter-exception` to start the session.
|
23
|
+
#
|
24
|
+
# This test is for type 3.
|
25
|
+
mock_pry("Ratty.new.ratty", "enter-exception", "show-stack", "exit").should =~ /toad.*?weasel.*?ratty/m
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
require 'pry-exception_explorer/exception_wrap'
|
4
|
+
|
5
|
+
CaughtException = Class.new(StandardError)
|
6
|
+
UncaughtException = Class.new(StandardError)
|
7
|
+
|
8
|
+
describe PryExceptionExplorer do
|
9
|
+
|
10
|
+
before do
|
11
|
+
Pry.config.input = StringIO.new("exit :caught\n")
|
12
|
+
Pry.config.output = StringIO.new
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
Pry.config.hooks.clear(:when_started)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "PryExceptionExplorer.wrap" do
|
20
|
+
|
21
|
+
it 'should default to capturing ALL exceptions' do
|
22
|
+
PryExceptionExplorer.wrap do
|
23
|
+
raise CaughtException, "catch me if u can"
|
24
|
+
end.should == :caught
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should NOT capture rescued exceptions' do
|
28
|
+
o = Object.new
|
29
|
+
def o.evil_fish
|
30
|
+
Ratty.new.ratty
|
31
|
+
rescue Exception
|
32
|
+
end
|
33
|
+
|
34
|
+
PryExceptionExplorer.intercept { true }
|
35
|
+
|
36
|
+
PryExceptionExplorer.wrap do
|
37
|
+
o.evil_fish
|
38
|
+
end.should.not == :caught
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should have the full callstack attached to exception' do
|
42
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.method_name == :toad }
|
43
|
+
|
44
|
+
PryExceptionExplorer.wrap do
|
45
|
+
begin
|
46
|
+
Ratty.new.ratty
|
47
|
+
rescue Exception => ex
|
48
|
+
ex.exception_call_stack[0..2].map { |b| b.eval("__method__") }.should == [:toad, :weasel, :ratty]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should NOT have callstack attached if exception not matched' do
|
54
|
+
PryExceptionExplorer.intercept { |frame, ex| false }
|
55
|
+
|
56
|
+
begin
|
57
|
+
PryExceptionExplorer.wrap do
|
58
|
+
raise UncaughtException, "Catch me if you can't.."
|
59
|
+
end
|
60
|
+
rescue UncaughtException => ex
|
61
|
+
ex.exception_call_stack.should == nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "PryExceptionExplorer.intercept with wrapped exceptions" do
|
66
|
+
describe "klass" do
|
67
|
+
describe "first frame" do
|
68
|
+
it 'should catch a matched exception based on klass' do
|
69
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.klass == Toad }
|
70
|
+
|
71
|
+
PryExceptionExplorer.wrap do
|
72
|
+
Ratty.new.ratty
|
73
|
+
end.should == :caught
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should NOT catch an unmatched exception' do
|
77
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.klass == Weasel }
|
78
|
+
|
79
|
+
begin
|
80
|
+
PryExceptionExplorer.wrap do
|
81
|
+
raise UncaughtException, "Catch me if you can't.."
|
82
|
+
end
|
83
|
+
rescue Exception => ex
|
84
|
+
ex.is_a?(UncaughtException).should == true
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "third frame" do
|
90
|
+
it 'should catch a matched exception' do
|
91
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.prev.prev.klass == Ratty }
|
92
|
+
|
93
|
+
PryExceptionExplorer.wrap do
|
94
|
+
Ratty.new.ratty
|
95
|
+
end.should == :caught
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should NOT catch an unmatched exception' do
|
99
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.prev.prev.klass == Weasel }
|
100
|
+
|
101
|
+
begin
|
102
|
+
PryExceptionExplorer.wrap do
|
103
|
+
raise UncaughtException, "Catch me if you can't.."
|
104
|
+
end
|
105
|
+
rescue Exception => ex
|
106
|
+
ex.is_a?(UncaughtException).should == true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "method_name" do
|
113
|
+
describe "first frame" do
|
114
|
+
it 'should catch a matched exception' do
|
115
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.method_name == :toad }
|
116
|
+
|
117
|
+
PryExceptionExplorer.wrap do
|
118
|
+
Ratty.new.ratty
|
119
|
+
end.should == :caught
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should NOT catch an unmatched exception' do
|
123
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.method_name == :weasel }
|
124
|
+
|
125
|
+
begin
|
126
|
+
PryExceptionExplorer.wrap do
|
127
|
+
raise UncaughtException, "Catch me if you can't.."
|
128
|
+
end
|
129
|
+
rescue Exception => ex
|
130
|
+
ex.is_a?(UncaughtException).should == true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "third frame" do
|
136
|
+
it 'should catch a matched exception' do
|
137
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.prev.prev.method_name == :ratty }
|
138
|
+
|
139
|
+
PryExceptionExplorer.wrap do
|
140
|
+
Ratty.new.ratty
|
141
|
+
end.should == :caught
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should NOT catch an unmatched exception' do
|
145
|
+
PryExceptionExplorer.intercept { |frame, ex| frame.prev.prev.method_name == :weasel }
|
146
|
+
|
147
|
+
begin
|
148
|
+
PryExceptionExplorer.wrap do
|
149
|
+
raise UncaughtException, "Catch me if you can't.."
|
150
|
+
end
|
151
|
+
rescue Exception => ex
|
152
|
+
ex.is_a?(UncaughtException).should == true
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
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.1pre3
|
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:
|
13
|
+
date: 2012-01-05 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: pry-stack_explorer
|
@@ -23,7 +23,29 @@ dependencies:
|
|
23
23
|
version: "0"
|
24
24
|
type: :runtime
|
25
25
|
version_requirements: *id001
|
26
|
-
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bacon
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.1.0
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rake
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0.9"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
description: Enter the context of exceptions
|
27
49
|
email: jrmair@gmail.com
|
28
50
|
executables: []
|
29
51
|
|
@@ -32,15 +54,27 @@ extensions: []
|
|
32
54
|
extra_rdoc_files: []
|
33
55
|
|
34
56
|
files:
|
57
|
+
- .gemtest
|
58
|
+
- .gitignore
|
59
|
+
- .travis.yml
|
60
|
+
- .yardopts
|
61
|
+
- CHANGELOG
|
62
|
+
- Gemfile
|
63
|
+
- LICENSE
|
64
|
+
- README.md
|
65
|
+
- Rakefile
|
66
|
+
- lib/pry-exception_explorer.rb
|
35
67
|
- lib/pry-exception_explorer/cli.rb
|
68
|
+
- lib/pry-exception_explorer/commands.rb
|
36
69
|
- lib/pry-exception_explorer/exception_wrap.rb
|
70
|
+
- lib/pry-exception_explorer/lazy_frame.rb
|
37
71
|
- lib/pry-exception_explorer/shim_builder.rb
|
38
72
|
- lib/pry-exception_explorer/version.rb
|
39
|
-
-
|
40
|
-
- test/
|
41
|
-
-
|
42
|
-
-
|
43
|
-
-
|
73
|
+
- pry-exception_explorer.gemspec
|
74
|
+
- test/helper.rb
|
75
|
+
- test/test_exception_explorer.rb
|
76
|
+
- test/test_exceptions_in_pry.rb
|
77
|
+
- test/test_wrapped_exceptions.rb
|
44
78
|
homepage: https://github.com/banister/pry-exception_explorer
|
45
79
|
licenses: []
|
46
80
|
|
@@ -67,6 +101,9 @@ rubyforge_project:
|
|
67
101
|
rubygems_version: 1.8.11
|
68
102
|
signing_key:
|
69
103
|
specification_version: 3
|
70
|
-
summary:
|
71
|
-
test_files:
|
72
|
-
|
104
|
+
summary: Enter the context of exceptions
|
105
|
+
test_files:
|
106
|
+
- test/helper.rb
|
107
|
+
- test/test_exception_explorer.rb
|
108
|
+
- test/test_exceptions_in_pry.rb
|
109
|
+
- test/test_wrapped_exceptions.rb
|
data/test/test.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
direc = File.dirname(__FILE__)
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require "#{direc}/../lib/pry-exception_explorer"
|
5
|
-
require 'bacon'
|
6
|
-
|
7
|
-
puts "Testing pry-exception_explorer version #{PryExceptionExplorer::VERSION}..."
|
8
|
-
puts "Ruby version: #{RUBY_VERSION}"
|
9
|
-
|
10
|
-
describe PryExceptionExplorer do
|
11
|
-
end
|
12
|
-
|