summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Gleeson <rob@flowof.info>2014-03-10 01:28:12 +0100
committerRobert Gleeson <rob@flowof.info>2014-03-10 02:59:11 +0100
commit24bbe12dc2e4bb395a8c6a7504e1ca2d7bef4272 (patch)
tree8316e00af26950b140353c41fe24c8f74d15bdd9
parent90dacb8f2551d5828d9173e28c81d290ad8e70e6 (diff)
downloadpry-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.rb1
-rw-r--r--lib/pry/last_exception.rb35
-rw-r--r--lib/pry/pry_instance.rb28
-rw-r--r--spec/pry_spec.rb22
4 files changed, 67 insertions, 19 deletions
diff --git a/lib/pry.rb b/lib/pry.rb
index f5cccff6..2089e6d7 100644
--- a/lib/pry.rb
+++ b/lib/pry.rb
@@ -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