diff options
author | Robert Gleeson <rob@flowof.info> | 2014-03-10 01:28:12 +0100 |
---|---|---|
committer | Robert Gleeson <rob@flowof.info> | 2014-03-10 02:59:11 +0100 |
commit | 24bbe12dc2e4bb395a8c6a7504e1ca2d7bef4272 (patch) | |
tree | 8316e00af26950b140353c41fe24c8f74d15bdd9 | |
parent | 90dacb8f2551d5828d9173e28c81d290ad8e70e6 (diff) | |
download | pry-24bbe12dc2e4bb395a8c6a7504e1ca2d7bef4272.tar.gz |
add Pry::LastException.
pry adds behavior(methods) to the exception it returns at _pry_.last_exception
in a repl but when the exception has been passed along as a frozen object ruby
will raise an exception and pry fails to function as usual.
the commit changes that behavior so that the exception is wrapped in an instance of
Pry::LastException who is a subclass of BasicObject. Pry::LastException is a copy&paste
of what was defined dynamically in pry_instance.rb but it allows for frozen exceptions
to remain frozen and still provides the methods pry dynamically defined on an exception
object before. through a wrapper class pry also no longer modifies an exception object
that it doesn't own.
-rw-r--r-- | lib/pry.rb | 1 | ||||
-rw-r--r-- | lib/pry/last_exception.rb | 35 | ||||
-rw-r--r-- | lib/pry/pry_instance.rb | 28 | ||||
-rw-r--r-- | spec/pry_spec.rb | 22 |
4 files changed, 67 insertions, 19 deletions
@@ -184,3 +184,4 @@ require 'pry/terminal' require 'pry/editor' require 'pry/rubygem' require "pry/indent" +require "pry/last_exception" diff --git a/lib/pry/last_exception.rb b/lib/pry/last_exception.rb new file mode 100644 index 00000000..a59306c6 --- /dev/null +++ b/lib/pry/last_exception.rb @@ -0,0 +1,35 @@ +class Pry::LastException < BasicObject + attr_reader :file, :line + attr_accessor :bt_index + + def initialize(e) + @e = e + @bt_index = 0 + @file, @line = bt_source_location_for(0) + end + + def method_missing(name, *args, &block) + if @e.respond_to?(name) + @e.public_send(name, *args, &block) + else + super + end + end + + def respond_to_missing?(name, boolean=false) + @e.respond_to?(name) + end + + def pry? + true + end + + def bt_source_location_for(index) + backtrace[index] =~ /(.*):(\d+)/ + [$1, $2.to_i] + end + + def inc_bt_index + @bt_index = (@bt_index + 1) % backtrace.size + end +end diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb index bd6abacc..5eb64753 100644 --- a/lib/pry/pry_instance.rb +++ b/lib/pry/pry_instance.rb @@ -467,27 +467,17 @@ class Pry self.last_result = result unless code =~ /\A\s*\z/ end + # # Set the last exception for a session. - # @param [Exception] ex - def last_exception=(ex) - class << ex - attr_accessor :file, :line, :bt_index - def bt_source_location_for(index) - backtrace[index] =~ /(.*):(\d+)/ - [$1, $2.to_i] - end - - def inc_bt_index - @bt_index = (@bt_index + 1) % backtrace.size - end - end - - ex.bt_index = 0 - ex.file, ex.line = ex.bt_source_location_for(0) - + # + # @param [Exception] e + # the last exception. + # + def last_exception=(e) + last_exception = Pry::LastException.new(e) @last_result_is_exception = true - @output_array << ex - @last_exception = ex + @output_array << last_exception + @last_exception = last_exception end # Update Pry's internal state after evalling code. diff --git a/spec/pry_spec.rb b/spec/pry_spec.rb index b12a0423..7e3a7f62 100644 --- a/spec/pry_spec.rb +++ b/spec/pry_spec.rb @@ -67,6 +67,28 @@ describe Pry do end end + describe "#last_exception=" do + before do + @pry = Pry.new binding: binding + @e = mock_exception "foo.rb:1" + end + + it "returns an instance of Pry::LastException" do + @pry.last_exception = @e + should.satisfy { @pry.last_exception.pry? == true } + end + + it "returns a frozen exception" do + @pry.last_exception = @e.freeze + @pry.last_exception.should.be.frozen? + end + + it "returns an object who mirrors itself as the wrapped exception" do + @pry.last_exception = @e.freeze + @pry.last_exception.should.be.instance_of?(StandardError) + end + end + describe "open a Pry session on an object" do describe "rep" do before do |