pry-rescue 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -11,6 +11,12 @@ task :example2 do
11
11
  sh "ruby -I./lib/ ./examples/example2.rb "
12
12
  end
13
13
 
14
+ desc 'Run syntax-err example'
15
+ task :sintax do
16
+ ENV['RUBYLIB'] = 'lib'
17
+ sh 'bin/rescue examples/syntax-err.rb'
18
+ end
19
+
14
20
  desc "Run tests"
15
21
  task :test do
16
22
  sh 'rspec spec'
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rspec'
3
+ require 'rspec/autorun'
4
+
5
+ $:.unshift File.expand_path '../../lib', __FILE__
6
+ require 'pry-rescue/rspec'
7
+
8
+ require 'capybara/rspec'
9
+
10
+ describe "Google", :type => :feature, :driver => :selenium do
11
+ it "should make a nice bell-like sound" do
12
+ visit 'http://google.com/'
13
+ page.should have_content 'Bing'
14
+ end
15
+ end
@@ -1,8 +1,9 @@
1
+ #!/usr/bin/env ruby
1
2
  require 'rspec'
2
3
  require 'rspec/autorun'
3
4
 
4
5
  $:.unshift File.expand_path '../../lib', __FILE__
5
- require 'pry-rescue'
6
+ require 'pry-rescue/rspec'
6
7
 
7
8
  describe "Float" do
8
9
  it "should be able to add" do
data/examples/loop.rb CHANGED
@@ -5,7 +5,9 @@ require 'pry-rescue'
5
5
  #
6
6
  # rescue --peek example/loop.rb
7
7
  #
8
- # Then hit <ctrl-c>, and be able to see what's going on.
8
+ # Then hit <ctrl-/>, and be able to see what's going on.
9
+ #
10
+ puts "Hit <ctrl-/> to peek with Pry, or <ctrl+c> to quit."
9
11
 
10
12
  def r
11
13
  some_var = 13
@@ -0,0 +1 @@
1
+ def initely not Ruby
@@ -41,19 +41,13 @@ Pry::Commands.create_command "cd-cause", "Move to the exception that caused this
41
41
  def process
42
42
  return Pry.rescued target.eval(args.first) if args.any?
43
43
 
44
- # TODO: better understand why !defined?(_ex_)
45
44
  ex = target.eval("defined?(_ex_) && _ex_")
46
- raised = target.eval("_raised_.dup rescue nil")
47
-
48
- ex_was_raised = raised && raised.last.first == ex
49
- if ex && !ex_was_raised
50
- Pry.rescued(ex)
51
- elsif ex_was_raised && raised.size > 1
52
- raised.pop
53
- PryRescue.enter_exception_context(raised)
54
- else
55
- raise Pry::CommandError, "No previous exception detected"
56
- end
45
+ rescued = target.eval("defined?(_rescued_) && _rescued_")
46
+
47
+ ex = ex.instance_variable_get(:@rescue_cause) if rescued == ex
48
+ raise Pry::CommandError, "No previous exception to cd-cause into" if ex.nil? || ex == rescued
49
+
50
+ Pry.rescued ex
57
51
  end
58
52
  end
59
53
 
@@ -11,7 +11,6 @@ class << Pry
11
11
  def rescue(&block)
12
12
  loop do
13
13
  catch(:try_again) do
14
- @raised = []
15
14
  begin
16
15
  return with_rescuing(&block)
17
16
  rescue Exception => e
@@ -34,8 +33,8 @@ class << Pry
34
33
  # end
35
34
  #
36
35
  def rescued(e=$!)
37
- if i = (@raised || []).index{ |(ee, _)| ee == e }
38
- PryRescue.enter_exception_context(@raised[0..i])
36
+ if e.instance_variable_get(:@rescue_bindings)
37
+ PryRescue.enter_exception_context(e)
39
38
  else
40
39
  stack = ''
41
40
  stack = "\n" + e.backtrace.join("\n") if e.backtrace
@@ -58,8 +57,6 @@ class << Pry
58
57
  end
59
58
  end
60
59
 
61
- ensure
62
- @raised = []
63
60
  end
64
61
 
65
62
  # Allow Pry::rescued(e) to work at any point in your program.
@@ -73,14 +70,12 @@ class << Pry
73
70
  # Pry::rescued(e)
74
71
  # end
75
72
  #
76
- def enable_rescuing!
77
- @raised ||= []
78
- @rescuing = true
79
- Interception.listen do |exception, binding|
80
- if defined?(PryStackExplorer)
81
- @raised << [exception, binding.callers]
82
- else
83
- @raised << [exception, Array(binding)]
73
+ def enable_rescuing!(block=nil)
74
+ Interception.listen(block) do |exception, binding|
75
+ bindings = binding.respond_to?(:callers) ? binding.callers : [binding]
76
+ unless exception.instance_variable_get(:@rescue_bindings)
77
+ exception.instance_variable_set(:@rescue_bindings, bindings)
78
+ exception.instance_variable_set(:@rescue_cause, $!)
84
79
  end
85
80
  end
86
81
  end
@@ -96,13 +91,7 @@ class << Pry
96
91
  else
97
92
  begin
98
93
  @rescuing = true
99
- Interception.listen(block) do |exception, binding|
100
- if defined?(PryStackExplorer)
101
- @raised << [exception, binding.callers]
102
- else
103
- @raised << [exception, Array(binding)]
104
- end
105
- end
94
+ enable_rescuing!(block)
106
95
  ensure
107
96
  @rescuing = false
108
97
  end
@@ -1,12 +1,58 @@
1
1
  require 'pry-rescue'
2
- RSpec.configure do |c|
3
- c.around(:each) do |example|
4
- Pry::rescue do
5
- example.binding.eval('@exception = nil')
6
- example.run
7
- if e = example.binding.eval('@exception')
8
- Pry::rescued(e)
2
+ class PryRescue
3
+ class RSpec
4
+
5
+ # Run an Rspec example within Pry::rescue{ }.
6
+ #
7
+ # Takes care to ensure that `try-again` will work.
8
+ def self.run(example)
9
+ Pry::rescue do
10
+ begin
11
+ before
12
+
13
+ example.binding.eval('@exception = nil')
14
+ example.run
15
+ if e = example.binding.eval('@exception')
16
+ Pry::rescued(e)
17
+ end
18
+
19
+ ensure
20
+ after
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.before
26
+ monkeypatch_capybara if defined?(Capybara)
27
+ end
28
+
29
+ def self.after
30
+ after_filters.each(&:call)
31
+ end
32
+
33
+ # Shunt Capybara's after filter from before Pry::rescued to after.
34
+ #
35
+ # The after filter navigates to 'about:blank', but people debugging
36
+ # tests probably want to see the page that failed.
37
+ def self.monkeypatch_capybara
38
+ unless Capybara.respond_to?(:reset_sessions_after_rescue!)
39
+ class << Capybara
40
+ alias_method :reset_sessions_after_rescue!, :reset_sessions!
41
+ def reset_sessions!; end
42
+ end
43
+
44
+ after_filters << Capybara.method(:reset_sessions_after_rescue!)
9
45
  end
10
46
  end
47
+
48
+ def self.after_filters
49
+ @after_filters ||= []
50
+ end
51
+ end
52
+ end
53
+
54
+ RSpec.configure do |c|
55
+ c.around(:each) do |example|
56
+ PryRescue::RSpec.run example
11
57
  end
12
58
  end
data/lib/pry-rescue.rb CHANGED
@@ -41,25 +41,23 @@ class PryRescue
41
41
 
42
42
  # Start a Pry session in the context of the exception.
43
43
  # @param [Array<Exception, Array<Binding>>] raised The exceptions raised
44
- def enter_exception_context(raised)
44
+ def enter_exception_context(exception)
45
45
  @exception_context_depth ||= 0
46
46
  @exception_context_depth += 1
47
47
 
48
- raised = raised.map do |e, bs|
49
- [e, without_bindings_below_raise(bs)]
50
- end
48
+ exception = exception.instance_variable_get(:@rescue_cause) if phantom_load_raise?(exception)
49
+ bindings = exception.instance_variable_get(:@rescue_bindings)
51
50
 
52
- raised.pop if phantom_load_raise?(*raised.last)
53
- exception, bindings = raised.last
51
+ bindings = without_bindings_below_raise(bindings)
54
52
  bindings = without_duplicates(bindings)
55
53
 
56
54
  with_program_name "#$PROGRAM_NAME [in pry-rescue @ #{Dir.pwd}]" do
57
55
  if defined?(PryStackExplorer)
58
56
  pry :call_stack => bindings,
59
- :hooks => pry_hooks(exception, raised),
57
+ :hooks => pry_hooks(exception),
60
58
  :initial_frame => initial_frame(bindings)
61
59
  else
62
- Pry.start bindings.first, :hooks => pry_hooks(exception, raised)
60
+ Pry.start bindings.first, :hooks => pry_hooks(exception)
63
61
  end
64
62
  end
65
63
  ensure
@@ -87,7 +85,8 @@ class PryRescue
87
85
  #
88
86
  # @param [Exception] e The raised exception
89
87
  # @param [Array<Binding>] bindings The call stack
90
- def phantom_load_raise?(e, bindings)
88
+ def phantom_load_raise?(e)
89
+ bindings = e.instance_variable_get(:@rescue_bindings)
91
90
  bindings.any? && bindings.first.eval("__FILE__") == __FILE__
92
91
  end
93
92
 
@@ -180,12 +179,12 @@ class PryRescue
180
179
  #
181
180
  # @param [Exception] ex The exception we're currently looking at
182
181
  # @param [Array<Exception, Array<Binding>>] raised The exceptions raised
183
- def pry_hooks(ex, raised)
182
+ def pry_hooks(ex)
184
183
  hooks = Pry.config.hooks.dup
185
184
  hooks.add_hook(:before_session, :save_captured_exception) do |_, _, _pry_|
186
185
  _pry_.last_exception = ex
187
186
  _pry_.backtrace = ex.backtrace
188
- _pry_.sticky_locals.merge!({ :_raised_ => raised })
187
+ _pry_.sticky_locals.merge!(:_rescued_ => ex)
189
188
  _pry_.exception_handler.call(_pry_.output, ex, _pry_)
190
189
  end
191
190
 
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 = '1.0.0'
3
+ s.version = '1.1.0'
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'
@@ -18,4 +18,5 @@ Gem::Specification.new do |s|
18
18
  s.add_development_dependency 'rspec'
19
19
  s.add_development_dependency 'yard'
20
20
  s.add_development_dependency 'redcarpet'
21
+ s.add_development_dependency 'capybara'
21
22
  end
@@ -36,40 +36,44 @@ describe "pry-rescue commands" do
36
36
  end
37
37
 
38
38
  it "should enter the context of _ex_ if no exception is given" do
39
- begin
40
- b1 = binding
41
- raise "original"
42
- rescue => _ex_
43
- b2 = binding
39
+ b2 = nil
40
+ _ex_ = nil
41
+ Pry::rescue do
42
+ begin
43
+ b1 = binding
44
+ raise "original"
45
+ rescue => _ex_
46
+ b2 = binding
47
+ end
44
48
  end
45
49
 
46
50
  Pry.should_receive(:rescued).once.with{ |raised|
47
51
  raised.should == _ex_
48
52
  }
49
53
 
50
- Pry.new.process_command 'cd-cause', '', binding
54
+ Pry.new.process_command 'cd-cause', '', b2
51
55
  end
52
56
  end
53
57
 
54
58
  describe "cd-cause" do
55
59
  it "should enter the next exception's context" do
56
- begin
60
+ _ex_ = nil
61
+ e1 = nil
62
+ Pry::rescue do
57
63
  begin
58
- b1 = binding
59
- raise "original"
60
- rescue => e1
61
- b2 = binding
62
- raise # similar to dubious re-raises you'll find in the wild
64
+ begin
65
+ b1 = binding
66
+ raise "original"
67
+ rescue => e1
68
+ b2 = binding
69
+ raise # similar to dubious re-raises you'll find in the wild
70
+ end
71
+ rescue => e2
72
+ _ex_ = e2
63
73
  end
64
- rescue => e2
65
- # Hacks due to us not really entering a pry session here
66
- _raised_ = [[e1, [b1]], [e2, [b2]]]
67
- _ex_ = e2
68
74
  end
69
75
 
70
- PryRescue.should_receive(:enter_exception_context).once.with{ |raised|
71
- raised.should == [[e1, [b1]]]
72
- }
76
+ PryRescue.should_receive(:enter_exception_context).once.with(e1)
73
77
 
74
78
  Pry.new.process_command 'cd-cause', '', binding
75
79
  end
@@ -80,7 +84,7 @@ describe "pry-rescue commands" do
80
84
  raise "original"
81
85
  rescue => e1
82
86
  # Hacks due to us not really entering a pry session here
83
- _raised_ = [[e1, [b1]]]
87
+ _rescued_ = e1
84
88
  _ex_ = e1
85
89
  end
86
90
 
@@ -89,6 +93,25 @@ describe "pry-rescue commands" do
89
93
  }.should raise_error Pry::CommandError, /No previous exception/
90
94
  end
91
95
 
96
+ it "should raise a CommandError on a re-raise" do
97
+ _ex_ = nil
98
+ Pry::rescue do
99
+ begin
100
+ begin
101
+ raise "oops"
102
+ rescue => e
103
+ raise e
104
+ end
105
+ rescue => _ex_
106
+ end
107
+ end
108
+ _rescued_ = _ex_
109
+
110
+ lambda{
111
+ Pry.new.process_command 'cd-cause', '', binding
112
+ }.should raise_error Pry::CommandError, /No previous exception/
113
+ end
114
+
92
115
  it "should raise a CommandError if not in Pry::rescue" do
93
116
  lambda{
94
117
  Pry.new.process_command 'cd-cause', '', binding
@@ -33,34 +33,6 @@ describe 'Pry.rescue' do
33
33
  @inner.should == 2
34
34
  end
35
35
 
36
- it "should clear out exceptions between retrys at the same level" do
37
- @outer = @inner = 0
38
- PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
39
- PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
40
- Pry::rescue do
41
- @outer += 1
42
- Pry::rescue do
43
- @inner += 1
44
- raise "oops" if @inner <= 2
45
- end
46
- end
47
- end
48
-
49
- it "should clear out exceptions between retrys at a higher level" do
50
- @outer = @inner = 0
51
- PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1; throw :try_again }
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 == 1; throw :try_again }
54
- Pry::rescue do
55
- @outer += 1
56
- Pry::rescue do
57
- @inner += 1
58
- raise "oops" if @inner <= 2
59
- end
60
- raise "foops" if @outer == 1
61
- end
62
- end
63
-
64
36
  it "should enter the first occurence of an exception that is re-raised" do
65
37
  PryRescue.should_receive(:enter_exception_context).once{ |raised| raised.size.should == 1 }
66
38
  lambda do
@@ -71,7 +43,7 @@ describe 'Pry.rescue' do
71
43
  raise
72
44
  end
73
45
  end
74
- end.should raise_error /first_occurance/
46
+ end.should raise_error(/first_occurance/)
75
47
  end
76
48
 
77
49
  it "should not catch SystemExit" do
@@ -95,6 +95,12 @@ describe "PryRescue.load" do
95
95
  PryRescue.load("spec/fixtures/raiseother.rb")
96
96
  }.should raise_error(/raiseother_exception/)
97
97
  end
98
+
99
+ it "should output a warning if the exception was not raised" do
100
+ PryRescue.should_not_receive(:enter_exception_context)
101
+ Pry.should_receive(:warn).once
102
+ Pry.rescued(RuntimeError.new("foo"))
103
+ end
98
104
  else
99
105
  it "should open at the correct point" do
100
106
  Pry.should_receive(:start).once{ |binding, h|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-rescue
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,104 +11,120 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-02-17 00:00:00.000000000 Z
14
+ date: 2013-03-21 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
- type: :runtime
17
+ name: pry
18
18
  requirement: !ruby/object:Gem::Requirement
19
+ none: false
19
20
  requirements:
20
21
  - - ! '>='
21
22
  - !ruby/object:Gem::Version
22
23
  version: '0'
23
- none: false
24
+ type: :runtime
25
+ prerelease: false
24
26
  version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
25
28
  requirements:
26
29
  - - ! '>='
27
30
  - !ruby/object:Gem::Version
28
31
  version: '0'
29
- none: false
30
- prerelease: false
31
- name: pry
32
32
  - !ruby/object:Gem::Dependency
33
- type: :runtime
33
+ name: interception
34
34
  requirement: !ruby/object:Gem::Requirement
35
+ none: false
35
36
  requirements:
36
37
  - - ! '>='
37
38
  - !ruby/object:Gem::Version
38
39
  version: '0.3'
39
- none: false
40
+ type: :runtime
41
+ prerelease: false
40
42
  version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
41
44
  requirements:
42
45
  - - ! '>='
43
46
  - !ruby/object:Gem::Version
44
47
  version: '0.3'
45
- none: false
46
- prerelease: false
47
- name: interception
48
48
  - !ruby/object:Gem::Dependency
49
- type: :development
49
+ name: pry-stack_explorer
50
50
  requirement: !ruby/object:Gem::Requirement
51
+ none: false
51
52
  requirements:
52
53
  - - ! '>='
53
54
  - !ruby/object:Gem::Version
54
55
  version: '0'
55
- none: false
56
+ type: :development
57
+ prerelease: false
56
58
  version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
57
60
  requirements:
58
61
  - - ! '>='
59
62
  - !ruby/object:Gem::Version
60
63
  version: '0'
61
- none: false
62
- prerelease: false
63
- name: pry-stack_explorer
64
64
  - !ruby/object:Gem::Dependency
65
- type: :development
65
+ name: rspec
66
66
  requirement: !ruby/object:Gem::Requirement
67
+ none: false
67
68
  requirements:
68
69
  - - ! '>='
69
70
  - !ruby/object:Gem::Version
70
71
  version: '0'
71
- none: false
72
+ type: :development
73
+ prerelease: false
72
74
  version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
73
76
  requirements:
74
77
  - - ! '>='
75
78
  - !ruby/object:Gem::Version
76
79
  version: '0'
77
- none: false
78
- prerelease: false
79
- name: rspec
80
80
  - !ruby/object:Gem::Dependency
81
- type: :development
81
+ name: yard
82
82
  requirement: !ruby/object:Gem::Requirement
83
+ none: false
83
84
  requirements:
84
85
  - - ! '>='
85
86
  - !ruby/object:Gem::Version
86
87
  version: '0'
87
- none: false
88
+ type: :development
89
+ prerelease: false
88
90
  version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
89
92
  requirements:
90
93
  - - ! '>='
91
94
  - !ruby/object:Gem::Version
92
95
  version: '0'
93
- none: false
94
- prerelease: false
95
- name: yard
96
96
  - !ruby/object:Gem::Dependency
97
- type: :development
97
+ name: redcarpet
98
98
  requirement: !ruby/object:Gem::Requirement
99
+ none: false
99
100
  requirements:
100
101
  - - ! '>='
101
102
  - !ruby/object:Gem::Version
102
103
  version: '0'
103
- none: false
104
+ type: :development
105
+ prerelease: false
104
106
  version_requirements: !ruby/object:Gem::Requirement
107
+ none: false
105
108
  requirements:
106
109
  - - ! '>='
107
110
  - !ruby/object:Gem::Version
108
111
  version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: capybara
114
+ requirement: !ruby/object:Gem::Requirement
109
115
  none: false
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
110
121
  prerelease: false
111
- name: redcarpet
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
112
128
  description: Allows you to wrap code in Pry::rescue{ } to open a pry session at any
113
129
  unhandled exceptions
114
130
  email:
@@ -128,6 +144,7 @@ files:
128
144
  - Rakefile
129
145
  - bin/kill-pry-rescue
130
146
  - bin/rescue
147
+ - examples/capybara_spec.rb
131
148
  - examples/example.rb
132
149
  - examples/example2.rb
133
150
  - examples/example_spec.rb
@@ -135,6 +152,7 @@ files:
135
152
  - examples/random-exit.rb
136
153
  - examples/rescue.rb
137
154
  - examples/sigsegv.rb
155
+ - examples/syntax-err.rb
138
156
  - lib/pry-rescue.rb
139
157
  - lib/pry-rescue/cli.rb
140
158
  - lib/pry-rescue/commands.rb
@@ -170,20 +188,20 @@ rdoc_options: []
170
188
  require_paths:
171
189
  - lib
172
190
  required_ruby_version: !ruby/object:Gem::Requirement
191
+ none: false
173
192
  requirements:
174
193
  - - ! '>='
175
194
  - !ruby/object:Gem::Version
176
195
  version: '0'
177
- none: false
178
196
  required_rubygems_version: !ruby/object:Gem::Requirement
197
+ none: false
179
198
  requirements:
180
199
  - - ! '>='
181
200
  - !ruby/object:Gem::Version
182
201
  version: '0'
183
- none: false
184
202
  requirements: []
185
203
  rubyforge_project:
186
- rubygems_version: 1.8.25
204
+ rubygems_version: 1.8.23
187
205
  signing_key:
188
206
  specification_version: 3
189
207
  summary: Open a pry session on any unhandled exceptions