Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 13 commits
  • 12 files changed
  • 0 commit comments
  • 2 contributors
View
31 README.md
@@ -30,6 +30,13 @@ include it in development!)
use PryRescue::Rack
```
+If you're using rspec, you should add `pry-rescue` to your Gemfile and then you can
+enable rescuing on failed tests by running:
+
+```
+rescue rspec
+```
+
If you want more fine-grained control over which parts of your code are rescued, you can
also use the block form:
@@ -75,6 +82,30 @@ end
Pry::rescue{ test }
```
+cd-raise
+========
+
+If you've run some code in Pry, and an exception was raised, you can use the `cd-raise`
+command:
+
+```
+[1] pry(main)> foo
+RuntimeError: two
+from a.rb:4:in `rescue in foo'
+[2] pry(main)> cd-raise
+From: a.rb @ line 4 Object#foo:
+
+ 1: def foo
+ 2: raise "one"
+ 3: rescue => e
+ => 4: raise "two"
+ 5: end
+
+[1] pry(main)>
+```
+
+To get back from `cd-raise` you can either type `<ctrl+d>` or `cd ..`.
+
cd-cause
========
View
5 Rakefile
@@ -1,3 +1,6 @@
+task :default => :test
+task :spec => :test
+
desc "Run example"
task :example do
sh "ruby -I./lib/ ./examples/example.rb "
@@ -10,7 +13,7 @@ end
desc "Run tests"
task :test do
- sh 'rspec spec -r ./spec/spec_helpers.rb'
+ sh 'rspec spec'
end
task :build do
View
37 bin/kill-pry-rescue
@@ -0,0 +1,37 @@
+#!/usr/bin/env ruby
+
+def find_pry_rescuers extra_id = ''
+ pattern = 'pry-rescue @.*' + extra_id
+ pids = nil
+ IO.popen ['pgrep', '-f', pattern] do |io|
+ pids = io.readlines.map &:to_i
+ end
+ pids
+end
+
+if %w(-h --help').include? ARGV[0]
+ warn %{
+#$0 - Stops a pry-rescuer
+
+By default gets all of them, but if you provide an arg, it can filter by the
+directory name.
+
+Uses SIGINT by default, unless you supply the -9 option.
+
+Currently running pry-rescue pids: #{find_pry_rescuers.join ' '}}
+ exit 1
+end
+
+signal =
+ if ARGV.delete '-9'
+ :KILL
+ else
+ :INT
+ end
+
+pids = find_pry_rescuers(ARGV.join ' ')
+warn '(No processes found.)' if pids.size.zero?
+pids.each do |pid|
+ warn "Killing #{pid} with SIG#{signal}."
+ Process.kill signal, pid
+end
View
8 bin/rescue
@@ -29,8 +29,12 @@ when /\A-/
exit
end
-if ARGV[0] == 'rails'
- ENV['PRY_RESCUE_RAILS'] = 'true'
+case ARGV[0]
+when 'rails'
+ ENV['PRY_RESCUE'] = 'rails'
+ exec(*ARGV)
+when 'rspec'
+ ENV['SPEC_OPTS'] = "#{ENV['SPEC_OPTS']} -r pry-rescue/rspec"
exec(*ARGV)
end
View
55 lib/pry-rescue.rb
@@ -24,6 +24,11 @@
rescue LoadError
end
+# Ensure that any exceptions raised within pry are available
+Pry.config.hooks.add_hook :before_session, :enable_rescuing do
+ Pry.enable_rescuing!
+end
+
# PryRescue provides the ability to open a Pry shell whenever an unhandled exception is
# raised in your code.
#
@@ -48,12 +53,14 @@ def enter_exception_context(raised)
exception, bindings = raised.last
bindings = without_duplicates(bindings)
- if defined?(PryStackExplorer)
- pry :call_stack => bindings,
- :hooks => pry_hooks(exception, raised),
- :initial_frame => initial_frame(bindings)
- else
- Pry.start bindings.first, :hooks => pry_hooks(exception, raised)
+ with_program_name "#$PROGRAM_NAME [in pry-rescue @ #{Dir.pwd}]" do
+ if defined?(PryStackExplorer)
+ pry :call_stack => bindings,
+ :hooks => pry_hooks(exception, raised),
+ :initial_frame => initial_frame(bindings)
+ else
+ Pry.start bindings.first, :hooks => pry_hooks(exception, raised)
+ end
end
ensure
@exception_context_depth -= 1
@@ -102,9 +109,21 @@ def initial_frame(bindings)
# @param [String] file the absolute path
# @return [Boolean]
def user_path?(file)
- !file.start_with?(RbConfig::CONFIG['libdir']) &&
- !gem_path?(file) &&
- !%w( (eval) <internal:prelude> ).include?(file)
+ return true if current_path?(file)
+ return false if stdlib_path?(file) || gem_path?(file)
+ true
+ end
+
+ # Is this file definitely part of the codebase the user is working on?
+ #
+ # This function exists because sometimes Dir.pwd can be a gem_path?,
+ # and the user expects to be able to debug a gem when they're cd'd
+ # into it.
+ #
+ # @param [String] file the absolute path
+ # @return [Boolean]
+ def current_path?(file)
+ file.start_with?(Dir.pwd) && !file.match(%r(/vendor/))
end
# Is this path included in a gem?
@@ -121,6 +140,14 @@ def gem_path?(file)
end
end
+ # Is this path in the ruby standard library?
+ #
+ # @param [String] file the absolute path
+ # @return [Boolean]
+ def stdlib_path?(file)
+ file.start_with?(RbConfig::CONFIG['libdir']) || %w( (eval) <internal:prelude> ).include?(file)
+ end
+
# Remove bindings that are part of Interception/Pry.rescue's internal
# event handling that happens as part of the exception hooking process.
#
@@ -130,7 +157,7 @@ def without_bindings_below_raise(bindings)
bindings.drop_while do |b|
b.eval("__FILE__") == File.expand_path("../pry-rescue/core_ext.rb", __FILE__)
end.drop_while do |b|
- b.eval("self") == Interception
+ Interception == b.eval("self")
end
end
@@ -164,5 +191,13 @@ def pry_hooks(ex, raised)
hooks
end
+
+ def with_program_name name
+ before = $PROGRAM_NAME
+ $PROGRAM_NAME = name
+ yield
+ ensure
+ $PROGRAM_NAME = before
+ end
end
end
View
32 lib/pry-rescue/commands.rb
@@ -1,4 +1,4 @@
-Pry::Commands.create_command "cd-cause", "Move to the previously raised exception" do
+Pry::Commands.create_command "cd-cause", "Move to the exception that caused this exception to happen" do
banner <<-BANNER
Usage: cd-cause
@@ -43,6 +43,36 @@ def process
end
end
+Pry::Commands.create_command "cd-raise", "Move to the point at which an exception was raised" do
+ banner <<-BANNER
+ Usage: cd-raise [_ex_]
+
+ Starts a new pry session at the point that the given exception was raised.
+
+ If no exception is given, defaults to _ex_, the most recent exception that
+ was raised by code you ran from within pry.
+
+ @example
+
+ [2] pry(main)> foo
+ RuntimeError: two
+ from /home/conrad/0/ruby/pry-rescue/a.rb:4:in `rescue in foo'
+ [3] pry(main)> cd-raise
+
+ 1: def foo
+ 2: raise "one"
+ 3: rescue => e
+ => 4: raise "two"
+ 5: end
+ BANNER
+
+ def process
+ ex = target.eval(args.first || "_ex_")
+ raise Pry::CommandError, "No most recent exception" unless ex
+ Pry.rescued(ex)
+ end
+end
+
Pry::Commands.create_command "try-again", "Re-try the code that caused this exception" do
banner <<-BANNER
View
5 lib/pry-rescue/core_ext.rb
@@ -37,7 +37,8 @@ def rescued(e=$!)
if i = (@raised || []).index{ |(ee, _)| ee == e }
PryRescue.enter_exception_context(@raised[0..i])
else
- stack = "\n" + e.backtrace.join("\n")
+ stack = ''
+ stack = "\n" + e.backtrace.join("\n") if e.backtrace
case e
when SystemStackError
# Interception cannot reliably interept SystemStackErrors as it needs
@@ -73,7 +74,7 @@ def rescued(e=$!)
# end
#
def enable_rescuing!
- @raised = []
+ @raised ||= []
@rescuing = true
Interception.listen do |exception, binding|
if defined?(PryStackExplorer)
View
2  lib/pry-rescue/rspec.rb
@@ -1,4 +1,4 @@
-require 'pry'
+require 'pry-rescue'
RSpec.configure do |c|
c.around(:each) do |example|
Pry::rescue do
View
4 pry-rescue.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'pry-rescue'
- s.version = '0.13'
+ s.version = '0.18.1'
s.summary = 'Open a pry session on any unhandled exceptions'
s.description = 'Allows you to wrap code in Pry::rescue{ } to open a pry session at any unhandled exceptions'
s.homepage = 'https://github.com/ConradIrwin/pry-rescue'
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
s.authors = ['Conrad Irwin', 'banisterfiend', 'epitron']
s.files = `git ls-files`.split("\n")
s.require_paths = ['lib']
- s.executables = ['rescue']
+ s.executables = s.files.grep(%r{^bin/}).map{|f| File.basename f}
s.add_dependency 'pry'
s.add_dependency 'interception', '>= 0.3'
View
32 spec/commands_spec.rb
@@ -17,6 +17,38 @@
end
end
+ describe "cd-raise" do
+ it "should enter the context of an explicit exception" do
+ begin
+ b1 = binding
+ raise "original"
+ rescue => e1
+ b2 = binding
+ end
+
+ Pry.should_receive(:rescued).once.with{ |raised|
+ raised.should == e1
+ }
+
+ Pry.new.process_command 'cd-raise e1', '', binding
+ end
+
+ it "should enter the context of _ex_ if no exception is given" do
+ begin
+ b1 = binding
+ raise "original"
+ rescue => _ex_
+ b2 = binding
+ end
+
+ Pry.should_receive(:rescued).once.with{ |raised|
+ raised.should == _ex_
+ }
+
+ Pry.new.process_command 'cd-raise', '', binding
+ end
+ end
+
describe "cd-cause" do
it "should enter the next exception's context" do
begin
View
4 spec/core_ext_spec.rb
@@ -107,7 +107,9 @@
it "should raise an error if used on an exception not raised" do
Pry::rescue do
- Pry.should_receive(:warn).with("WARNING: Tried to inspect an exception that was not raised within Pry::rescue{ }")
+ Pry.should_receive(:warn) do |message|
+ message.should =~ /^WARNING: Tried to inspect exception outside of Pry::rescue/
+ end
Pry.rescued(RuntimeError.new("foo").exception)
end
end
View
6 spec/pry_rescue_spec.rb
@@ -52,6 +52,12 @@
}.should raise_error(ArgumentError)
end
+ it "should skip pwd, even if it is a gem (but not vendor stuff)" do
+ Gem::Specification.stub :any? do true end
+ PryRescue.send(:user_path?, Dir.pwd + '/asdf.rb').should be_true
+ PryRescue.send(:user_path?, Dir.pwd + '/vendor/asdf.rb').should be_false
+ end
+
it "should filter out duplicate stack frames" do
PryRescue.should_receive(:pry).once do |opts|
opts[:call_stack][0].eval("__LINE__").should == 4

No commit comments for this range

Something went wrong with that request. Please try again.