pry-rescue 0.8 → 0.9.pre.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- **pry-rescue** super-fast, painless, debugging for the (ruby) masses. (See [Pry to the rescue!](https://cirw.in/blog/pry-to-the-rescue))
2
+ **pry-rescue** super-fast, painless, debugging for the (ruby) masses. (See [Pry to the rescue!](http://cirw.in/blog/pry-to-the-rescue))
3
3
 
4
4
  Usage
5
5
  =====
data/lib/pry-rescue.rb CHANGED
@@ -24,11 +24,12 @@ class PryRescue
24
24
  # Start a Pry session in the context of the exception.
25
25
  # @param [Array<Exception, Array<Binding>>] raised The exceptions raised
26
26
  def enter_exception_context(raised)
27
+ @exception_context_depth ||= 0
28
+ @exception_context_depth += 1
27
29
 
28
30
  raised = raised.map do |e, bs|
29
31
  [e, without_bindings_below_raise(bs)]
30
32
  end
31
- raised = without_gem_reraises(raised)
32
33
 
33
34
  raised.pop if phantom_load_raise?(*raised.last)
34
35
  exception, bindings = raised.last
@@ -41,6 +42,8 @@ class PryRescue
41
42
  else
42
43
  Pry.start bindings.first, :hooks => pry_hooks(exception, raised)
43
44
  end
45
+ ensure
46
+ @exception_context_depth -= 1
44
47
  end
45
48
 
46
49
  # Load a script wrapped in Pry::rescue{ }
@@ -49,6 +52,12 @@ class PryRescue
49
52
  Pry::rescue{ Kernel.load script }
50
53
  end
51
54
 
55
+ # Is the user currently inside pry rescue?
56
+ # @return [Boolean]
57
+ def in_exception_context?
58
+ @exception_context_depth && @exception_context_depth > 0
59
+ end
60
+
52
61
  private
53
62
 
54
63
  # Did this raise happen within pry-rescue?
@@ -81,7 +90,8 @@ class PryRescue
81
90
  # @return [Boolean]
82
91
  def user_path?(file)
83
92
  !file.start_with?(RbConfig::CONFIG['libdir']) &&
84
- !Gem::Specification.any?{ |gem| file.start_with?(gem.full_gem_path) }
93
+ !Gem::Specification.any?{ |gem| file.start_with?(gem.full_gem_path) } &&
94
+ !(file == '<internal:prelude>')
85
95
  end
86
96
 
87
97
  # Remove bindings that are part of Interception/Pry.rescue's internal
@@ -105,28 +115,11 @@ class PryRescue
105
115
  bindings.zip([nil] + bindings).reject do |b, c|
106
116
  # The eval('__method__') is there as a shortcut as loading a method
107
117
  # from a binding is very slow.
108
- c && (b.eval("__method__") == c.eval("__method__")) &&
118
+ c && (b.eval("::Kernel.__method__") == c.eval("::Kernel.__method__")) &&
109
119
  Pry::Method.from_binding(b) == Pry::Method.from_binding(c)
110
120
  end.map(&:first)
111
121
  end
112
122
 
113
- # Remove any re-raises of the exact exception object that happened from within
114
- # a gem, and show you only the raise that happened in your code.
115
- #
116
- # @param [Array<Exception, Array<Binding>>] raised The exceptions raised
117
- def without_gem_reraises(raised)
118
- seen = {}
119
- raised.select do |(e, bindings)|
120
- if seen[e] && !user_path?(bindings.first.eval("__FILE__"))
121
- false
122
- elsif user_path?(bindings.first.eval("__FILE__"))
123
- seen[e] = true
124
- else
125
- true
126
- end
127
- end
128
- end
129
-
130
123
  # Define the :before_session hook for the Pry instance.
131
124
  # This ensures that the `_ex_` and `_raised_` sticky locals are
132
125
  # properly set.
@@ -12,15 +12,15 @@ Pry::Commands.create_command "cd-cause", "Move to the previously raised exceptio
12
12
  5. def foo
13
13
  6. raise "one"
14
14
  7. rescue
15
- 8. => raise "two"
15
+ 8. => raise "two"
16
16
  9. end
17
17
 
18
18
  pry> cd-cause
19
19
 
20
20
  5. def foo
21
- 6. => raise "one"
21
+ 6. => raise "one"
22
22
  7. rescue
23
- 8. raise "two"
23
+ 8. raise "two"
24
24
  9. end
25
25
 
26
26
  Once you have finished with the internal exception type <ctrl+d> or cd .. to
@@ -60,6 +60,7 @@ Pry::Commands.create_command "try-again", "Re-try the code that caused this exce
60
60
  BANNER
61
61
 
62
62
  def process
63
+ raise Pry::CommandError, "try-again only works in a pry session created by Pry::rescue{}" unless PryRescue.in_exception_context?
63
64
  throw :try_again
64
65
  end
65
66
  end
@@ -1,5 +1,5 @@
1
1
  # Additional methods provided by pry-rescue.
2
- class Pry
2
+ class << Pry
3
3
  # Start a pry session on any unhandled exceptions within this block.
4
4
  #
5
5
  # @example
@@ -8,29 +8,18 @@ class Pry
8
8
  # end
9
9
  #
10
10
  # @return [Object] The return value of the block
11
- def self.rescue(&block)
12
- raised = []
13
- (@raised_stack ||= []) << raised
14
-
11
+ def rescue(&block)
15
12
  loop do
16
13
  catch(:try_again) do
17
- raised.clear
14
+ @raised = []
18
15
  begin
19
- return Interception.listen(block) do |exception, binding|
20
- if defined?(PryStackExplorer)
21
- raised << [exception, binding.callers]
22
- else
23
- raised << [exception, Array(binding)]
24
- end
25
- end
16
+ return with_rescuing(&block)
26
17
  rescue Exception => e
27
- PryRescue.enter_exception_context(raised)
18
+ rescued e
28
19
  raise e
29
20
  end
30
21
  end
31
22
  end
32
- ensure
33
- @raised_stack.pop
34
23
  end
35
24
 
36
25
  # Start a pry session on an exception that you rescued within a Pry::rescue{ }.
@@ -44,13 +33,38 @@ class Pry
44
33
  # end
45
34
  # end
46
35
  #
47
- def self.rescued(e=$!)
48
- raise "Tried to inspect rescued exception outside Pry::rescue{ } block" unless @raised_stack.any?
36
+ def rescued(e=$!)
37
+ if i = (@raised || []).index{ |(ee, _)| ee == e }
38
+ PryRescue.enter_exception_context(@raised[0..i])
39
+ else
40
+ raise "Tried to inspect an exception that was not raised in a Pry::rescue{ } block"
41
+ end
42
+
43
+ ensure
44
+ @raised = []
45
+ end
49
46
 
50
- raised = @raised_stack.last.dup
51
- raised.pop until raised.empty? || raised.last.first == e
52
- raise "Tried to inspect an exception that was not raised in this Pry::rescue{ } block" unless raised.any?
47
+ private
53
48
 
54
- PryRescue.enter_exception_context(raised)
49
+ # Ensure that Interception is active while running this block
50
+ #
51
+ # @param [Proc] &block the block
52
+ def with_rescuing(&block)
53
+ if @rescuing
54
+ block.call
55
+ else
56
+ begin
57
+ @rescuing = true
58
+ Interception.listen(block) do |exception, binding|
59
+ if defined?(PryStackExplorer)
60
+ @raised << [exception, binding.callers]
61
+ else
62
+ @raised << [exception, Array(binding)]
63
+ end
64
+ end
65
+ ensure
66
+ @rescuing = false
67
+ end
68
+ end
55
69
  end
56
70
  end
@@ -0,0 +1,33 @@
1
+ require 'pry-rescue'
2
+ class PryRescue
3
+ class Railtie < ::Rails::Railtie
4
+
5
+ initializer "pry_rescue" do |app|
6
+ if Rails.env.development?
7
+ app.config.middleware.use PryRescue::Rack
8
+
9
+ if defined?(::ActionDispatch::DebugExceptions)
10
+ monkeypatch(::ActionDispatch::DebugExceptions)
11
+
12
+ elsif defined?(::ActionDispatch::ShowExceptions)
13
+ monkeypatch(::ActionDispatch::ShowExceptions)
14
+
15
+ else
16
+ raise LoadError, "Sorry, your version of rails is not supported."
17
+ end
18
+ end
19
+ end
20
+
21
+ def monkeypatch(middleware)
22
+ middleware.class_eval do
23
+
24
+ def render_exception_with_pry_rescue(env, exception)
25
+ Pry::rescued(exception)
26
+ render_exception_without_pry_rescue(env, exception)
27
+ end
28
+
29
+ alias_method_chain :render_exception, :pry_rescue
30
+ end
31
+ end
32
+ end
33
+ end
data/pry-rescue.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'pry-rescue'
3
- s.version = '0.8'
3
+ s.version = '0.9.pre.1'
4
4
  s.summary = 'Open a pry session on any unhandled exceptions'
5
5
  s.description = 'Allows you to wrap code in Pry::rescue{ } to open a pry session at any unhandled exceptions'
6
6
  s.homepage = 'https://github.com/ConradIrwin/pry-rescue'
@@ -0,0 +1,60 @@
1
+ describe "pry-rescue commands" do
2
+ describe "try-again" do
3
+ it "should throw try_again" do
4
+ PryRescue.should_receive(:in_exception_context?).and_return{ true }
5
+
6
+ lambda{
7
+ Pry.new.process_command "try-again", '', TOPLEVEL_BINDING
8
+ }.should throw_symbol :try_again
9
+ end
10
+
11
+ it "should raise a CommandError if not in Pry::rescue" do
12
+ PryRescue.should_receive(:in_exception_context?).and_return{ false }
13
+
14
+ lambda{
15
+ Pry.new.process_command "try-again", '', TOPLEVEL_BINDING
16
+ }.should raise_error Pry::CommandError
17
+ end
18
+ end
19
+
20
+ describe "cd-cause" do
21
+ it "should enter the next exception's context" do
22
+ begin
23
+ begin
24
+ b1 = binding
25
+ raise "original"
26
+ rescue => e1
27
+ b2 = binding
28
+ raise
29
+ end
30
+ rescue => e2
31
+ _raised_ = [[e1, [b1]], [e2, [b2]]]
32
+ end
33
+
34
+ PryRescue.should_receive(:enter_exception_context).once.with{ |raised|
35
+ raised.should == [[e1, [b1]]]
36
+ }
37
+
38
+ Pry.new.process_command 'cd-cause', '', binding
39
+ end
40
+
41
+ it "should raise a CommandError if no previous commands" do
42
+ begin
43
+ b1 = binding
44
+ raise "original"
45
+ rescue => e1
46
+ _raised_ = [[e1, [b1]]]
47
+ end
48
+
49
+ lambda{
50
+ Pry.new.process_command 'cd-cause', '', binding
51
+ }.should raise_error Pry::CommandError, /No previous exception/
52
+ end
53
+
54
+ it "should raise a CommandError if not in Pry::rescue" do
55
+ lambda{
56
+ Pry.new.process_command 'cd-cause', '', binding
57
+ }.should raise_error Pry::CommandError, /Pry::rescue/
58
+ end
59
+ end
60
+ end
@@ -46,11 +46,11 @@ describe 'Pry.rescue' do
46
46
  end
47
47
  end
48
48
 
49
- it "should preserve exceptions between retrys at a higher level" do
49
+ it "should clear out exceptions between retrys at a higher level" do
50
50
  @outer = @inner = 0
51
51
  PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
52
52
  PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
53
- PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 3; throw :try_again }
53
+ PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
54
54
  Pry::rescue do
55
55
  @outer += 1
56
56
  Pry::rescue do
@@ -60,6 +60,19 @@ describe 'Pry.rescue' do
60
60
  raise "foops" if @outer == 1
61
61
  end
62
62
  end
63
+
64
+ it "should enter the first occurence of an exception that is re-raised" do
65
+ PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1 }
66
+ lambda do
67
+ Pry::rescue do
68
+ begin
69
+ raise "first_occurance"
70
+ rescue => e
71
+ raise
72
+ end
73
+ end
74
+ end.should raise_error /first_occurance/
75
+ end
63
76
  end
64
77
 
65
78
  describe "Pry.rescued" do
@@ -70,7 +83,7 @@ describe "Pry.rescued" do
70
83
  rescue => e
71
84
  lambda{
72
85
  Pry.rescued(e)
73
- }.should raise_error(/outside Pry::rescue/)
86
+ }.should raise_error(/Pry::rescue/)
74
87
  end
75
88
  end
76
89
 
metadata CHANGED
@@ -1,109 +1,97 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: pry-rescue
3
- version: !ruby/object:Gem::Version
4
- version: '0.8'
5
- prerelease:
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 0
7
+ - 9
8
+ - pre
9
+ - 1
10
+ version: 0.9.pre.1
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Conrad Irwin
9
14
  - banisterfiend
10
15
  - epitron
11
16
  autorequire:
12
17
  bindir: bin
13
18
  cert_chain: []
14
- date: 2012-08-31 00:00:00.000000000 Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
19
+
20
+ date: 2012-09-30 00:00:00 -07:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
17
24
  name: pry
18
- requirement: !ruby/object:Gem::Requirement
19
- none: false
20
- requirements:
21
- - - ! '>='
22
- - !ruby/object:Gem::Version
23
- version: '0'
24
- type: :runtime
25
25
  prerelease: false
26
- version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
- requirements:
29
- - - ! '>='
30
- - !ruby/object:Gem::Version
31
- version: '0'
32
- - !ruby/object:Gem::Dependency
33
- name: interception
34
- requirement: !ruby/object:Gem::Requirement
35
- none: false
36
- requirements:
37
- - - ! '>='
38
- - !ruby/object:Gem::Version
39
- version: '0'
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ segments:
31
+ - 0
32
+ version: "0"
40
33
  type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: interception
41
37
  prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
- requirements:
45
- - - ! '>='
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- - !ruby/object:Gem::Dependency
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ type: :runtime
46
+ version_requirements: *id002
47
+ - !ruby/object:Gem::Dependency
49
48
  name: rspec
50
- requirement: !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ! '>='
54
- - !ruby/object:Gem::Version
55
- version: '0'
56
- type: :development
57
49
  prerelease: false
58
- version_requirements: !ruby/object:Gem::Requirement
59
- none: false
60
- requirements:
61
- - - ! '>='
62
- - !ruby/object:Gem::Version
63
- version: '0'
64
- - !ruby/object:Gem::Dependency
65
- name: yard
66
- requirement: !ruby/object:Gem::Requirement
67
- none: false
68
- requirements:
69
- - - ! '>='
70
- - !ruby/object:Gem::Version
71
- version: '0'
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
72
57
  type: :development
58
+ version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
60
+ name: yard
73
61
  prerelease: false
74
- version_requirements: !ruby/object:Gem::Requirement
75
- none: false
76
- requirements:
77
- - - ! '>='
78
- - !ruby/object:Gem::Version
79
- version: '0'
80
- - !ruby/object:Gem::Dependency
81
- name: redcarpet
82
- requirement: !ruby/object:Gem::Requirement
83
- none: false
84
- requirements:
85
- - - ! '>='
86
- - !ruby/object:Gem::Version
87
- version: '0'
62
+ requirement: &id004 !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
88
69
  type: :development
70
+ version_requirements: *id004
71
+ - !ruby/object:Gem::Dependency
72
+ name: redcarpet
89
73
  prerelease: false
90
- version_requirements: !ruby/object:Gem::Requirement
91
- none: false
92
- requirements:
93
- - - ! '>='
94
- - !ruby/object:Gem::Version
95
- version: '0'
96
- description: Allows you to wrap code in Pry::rescue{ } to open a pry session at any
97
- unhandled exceptions
98
- email:
74
+ requirement: &id005 !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ type: :development
82
+ version_requirements: *id005
83
+ description: Allows you to wrap code in Pry::rescue{ } to open a pry session at any unhandled exceptions
84
+ email:
99
85
  - conrad.irwin@gmail.com
100
86
  - jrmair@gmail.com
101
87
  - chris@ill-logic.com
102
- executables:
88
+ executables:
103
89
  - rescue
104
90
  extensions: []
91
+
105
92
  extra_rdoc_files: []
106
- files:
93
+
94
+ files:
107
95
  - .gitignore
108
96
  - Gemfile
109
97
  - LICENSE.MIT
@@ -118,8 +106,10 @@ files:
118
106
  - lib/pry-rescue/commands.rb
119
107
  - lib/pry-rescue/core_ext.rb
120
108
  - lib/pry-rescue/rack.rb
109
+ - lib/pry-rescue/rails.rb
121
110
  - lib/pry/rescue.rb
122
111
  - pry-rescue.gemspec
112
+ - spec/commands_spec.rb
123
113
  - spec/core_ext_spec.rb
124
114
  - spec/fixtures/coderay.rb
125
115
  - spec/fixtures/initial.rb
@@ -129,29 +119,37 @@ files:
129
119
  - spec/fixtures/super.rb
130
120
  - spec/fixtures/uri.rb
131
121
  - spec/pry_rescue_spec.rb
122
+ has_rdoc: true
132
123
  homepage: https://github.com/ConradIrwin/pry-rescue
133
124
  licenses: []
125
+
134
126
  post_install_message:
135
127
  rdoc_options: []
136
- require_paths:
128
+
129
+ require_paths:
137
130
  - lib
138
- required_ruby_version: !ruby/object:Gem::Requirement
139
- none: false
140
- requirements:
141
- - - ! '>='
142
- - !ruby/object:Gem::Version
143
- version: '0'
144
- required_rubygems_version: !ruby/object:Gem::Requirement
145
- none: false
146
- requirements:
147
- - - ! '>='
148
- - !ruby/object:Gem::Version
149
- version: '0'
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">"
141
+ - !ruby/object:Gem::Version
142
+ segments:
143
+ - 1
144
+ - 3
145
+ - 1
146
+ version: 1.3.1
150
147
  requirements: []
148
+
151
149
  rubyforge_project:
152
- rubygems_version: 1.8.23
150
+ rubygems_version: 1.3.6
153
151
  signing_key:
154
152
  specification_version: 3
155
153
  summary: Open a pry session on any unhandled exceptions
156
154
  test_files: []
157
- has_rdoc:
155
+