pry-capture 0.1.pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2012 Conrad Irwin <conrad.irwin@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,94 @@
1
+ pry-capture allows you to start a Pry session on any unhandled exceptions in your code.
2
+
3
+
4
+ Installation
5
+ ============
6
+ Either `gem install pry-capture`, or add it to the development section of your Gemfile:
7
+
8
+ ```ruby
9
+ source :rubygems
10
+ group :development do
11
+ gem 'pry-capture'
12
+ gem 'pry-stack_explorer' # if you're using MRI 1.9 and you want it to be awesome.
13
+ end
14
+ ```
15
+
16
+ Usage
17
+ =====
18
+
19
+ In development, wrap your code in `Pry::capture{ }`; then any exceptions that are raised
20
+ but not rescued will open a pry session.
21
+
22
+ ```ruby
23
+ require 'pry-capture'
24
+
25
+ def test
26
+ raise "foo"
27
+ rescue => e
28
+ raise "bar"
29
+ end
30
+
31
+ Pry.capture do
32
+ test
33
+ end
34
+ ```
35
+
36
+ This will land you in a pry-session:
37
+
38
+ ```
39
+ From: examples/example.rb @ line 4 Object#test:
40
+
41
+ 4: def test
42
+ 5: raise "foo"
43
+ 6: rescue => e
44
+ => 7: raise "bar"
45
+ 8: end
46
+
47
+ RuntimeError: bar
48
+ from examples/example.rb:7:in `rescue in test'
49
+ [1] pry(main)>
50
+ ```
51
+
52
+ If you need to find the reason that the exception happened, you can use the `cd-cause`
53
+ command:
54
+
55
+ ```
56
+ [1] pry(main)> cd-cause
57
+ From: examples/example.rb @ line 4 Object#test:
58
+
59
+ 4: def test
60
+ => 5: raise "foo"
61
+ 6: rescue => e
62
+ 7: raise "bar"
63
+ 8: end
64
+
65
+ RuntimeError: foo
66
+ from examples/example.rb:5:in `test'
67
+ [1] pry(main)>
68
+ ```
69
+
70
+ To get back from `cd-cause` you can either type `<ctrl+d>` or `cd ..`.
71
+
72
+ pry-stack explorer
73
+ ==================
74
+
75
+ If you're running rubinius, or ruby-1.9, then you can use `pry-capture` alongside
76
+ `pry-stack_explorer`. This gives you the ability to move `up` or `down the stack so that
77
+ you can get a better idea of why your function ended up in a bad state. See
78
+ example2.rb](https://github.com/ConradIrwin/pry-capture/blob/master/examples/example2.rb) to get a feel for what this is like.
79
+
80
+ Known bugs
81
+ ==========
82
+
83
+ Occasionally, when using ruby-1.8 or jruby, the value for `self` will be incorrect. You
84
+ will still be able to access local variables, but calling methods will not work as you
85
+ expect.
86
+
87
+ On rbx we are unable to intercept some exceptions thrown from inside the C++ VM, for
88
+ example the ZeroDivisionError in `1 / 0`.
89
+
90
+ Meta-fu
91
+ =======
92
+
93
+ Released under the MIT license, see LICENSE.MIT for details. Contributions and bug-reports
94
+ are welcome.
@@ -0,0 +1,16 @@
1
+ desc "Run example"
2
+ task :example do
3
+ sh "ruby -I./lib/ ./examples/example.rb "
4
+ end
5
+
6
+ desc "Run example 2"
7
+ task :example2 do
8
+ sh "ruby -I./lib/ ./examples/example2.rb "
9
+ end
10
+
11
+ desc "Run tests"
12
+ task :test do
13
+ sh 'rspec spec -r ./spec/spec_helpers.rb'
14
+ end
15
+
16
+
@@ -0,0 +1,21 @@
1
+ $:.unshift File.expand_path '../../lib', __FILE__
2
+ require 'pry-capture'
3
+
4
+ Pry.capture do
5
+
6
+ def a
7
+ begin
8
+ begin
9
+ raise "foo"
10
+
11
+ rescue => e
12
+ raise "bar"
13
+ end
14
+
15
+ rescue => e
16
+ 1 / 0
17
+
18
+ end
19
+ end
20
+ a
21
+ end
@@ -0,0 +1,20 @@
1
+ $:.unshift File.expand_path '../../lib', __FILE__
2
+ require 'pry-capture'
3
+
4
+ def alpha
5
+ x = 1
6
+ beta
7
+ end
8
+
9
+ def beta
10
+ y = 30
11
+ gamma(1, 2)
12
+ end
13
+
14
+ def gamma(x)
15
+ greeting = x
16
+ end
17
+
18
+ Pry.capture do
19
+ alpha
20
+ end
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'interception'
3
+ require 'pry'
4
+
5
+ require File.expand_path('../pry-capture/core_ext', __FILE__)
6
+ require File.expand_path('../pry-capture/commands', __FILE__)
7
+
8
+ begin
9
+ require 'pry-stack_explorer'
10
+ rescue LoadError
11
+ end
12
+
13
+ class PryCapture
14
+ class << self
15
+
16
+ # Start a Pry session in the context of the exception.
17
+ # @param [Exception] exception The exception.
18
+ # @param [Array<Binding>] bindings The call stack.
19
+ def enter_exception_context(raised)
20
+ exception, bindings = raised.last
21
+
22
+ prune_call_stack!(bindings)
23
+
24
+ if defined?(PryStackExplorer)
25
+ pry :call_stack => bindings, :hooks => pry_hooks(exception, raised)
26
+ else
27
+ bindings.first.pry :hooks => pry_hooks(exception, raised)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ # Define the :before_session hook for the Pry instance.
34
+ # This ensures that the `_ex_` and `_raised_` sticky locals are
35
+ # properly set.
36
+ def pry_hooks(ex, raised)
37
+ hooks = Pry.config.hooks.dup
38
+ hooks.add_hook(:before_session, :save_captured_exception) do |_, _, _pry_|
39
+ _pry_.last_exception = ex
40
+ _pry_.backtrace = ex.backtrace
41
+ _pry_.sticky_locals.merge!({ :_raised_ => raised })
42
+ _pry_.exception_handler.call(_pry_.output, ex, _pry_)
43
+ end
44
+
45
+ hooks
46
+ end
47
+
48
+ # Sanitize the call stack.
49
+ # @param [Array<Binding>] bindings The call stack.
50
+ def prune_call_stack!(bindings)
51
+ bindings.delete_if { |b| [Pry, Interception].include?(b.eval("self")) }
52
+ end
53
+ end
54
+ end
@@ -0,0 +1 @@
1
+ require 'pry-capture'
@@ -0,0 +1,44 @@
1
+ Pry::Commands.create_command "cd-cause", "Move to the previously raised exception" do
2
+
3
+ banner <<-BANNER
4
+ Usage: cd-cause
5
+
6
+ Starts a new pry session at the previously raised exception.
7
+
8
+ This is useful if you've caught one exception, and raised another,
9
+ if you need to find out why the original was raised.
10
+
11
+ @example
12
+ 5. def foo
13
+ 6. raise "one"
14
+ 7. rescue
15
+ 8. => raise "two"
16
+ 9. end
17
+
18
+ pry> cd-cause
19
+
20
+ 5. def foo
21
+ 6. => raise "one"
22
+ 7. rescue
23
+ 8. raise "two"
24
+ 9. end
25
+
26
+ Once you have finished with the internal exception type <ctrl+d> or cd .. to
27
+ return to where you were.
28
+
29
+ If you have many layers of exceptions that are rescued and then re-raised, you
30
+ can repeat cd-cause as many times as you need.
31
+ BANNER
32
+
33
+ def process
34
+ raised = target.eval("_raised_ rescue nil")
35
+ raise Pry::CommandError, "cd-cause only works in a pry session created by Pry::capture{}" unless raised
36
+ raised.pop
37
+
38
+ if raised.any?
39
+ PryCapture.enter_exception_context(raised)
40
+ else
41
+ raise Pry::CommandError, "No previous exception detected"
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ class Pry
2
+
3
+ # Start a pry session on any unhandled exceptions within this block.
4
+ #
5
+ # @example
6
+ # Pry::capture do
7
+ # raise "foo"
8
+ # end
9
+ #
10
+ # @return [Object] The return value of the block
11
+ def self.capture(&block)
12
+ raised = []
13
+
14
+ Interception.listen(block) do |exception, binding|
15
+ if defined?(PryStackExplorer)
16
+ raised << [exception, binding.callers]
17
+ else
18
+ raised << [exception, Array(binding)]
19
+ end
20
+ end
21
+
22
+ ensure
23
+ if raised.any?
24
+ PryCapture.enter_exception_context(raised)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ # For packaging Octokey, please use "rake gems; rake pushgems".
2
+ # This gemspec will only generate the correct gem for the current platform.
3
+ Gem::Specification.new do |s|
4
+
5
+ s.name = 'pry-capture'
6
+ s.version = '0.1.pre.1'
7
+ s.summary = 'Open a pry session on any unhandled exceptions'
8
+ s.description = 'Allows you to wrap code in Pry::capture{ } to open a pry session at any unhandled exceptions'
9
+ s.homepage = 'https://github.com/ConradIrwin/pry-capture'
10
+ s.email = ['conrad.irwin@gmail.com', 'jrmair@gmail.com']
11
+ s.authors = ['Conrad Irwin', 'banisterfiend']
12
+ s.files = `git ls-files`.split("\n")
13
+ s.require_paths = ["lib"]
14
+
15
+ s.add_dependency 'pry-stack_explorer'
16
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pry-capture
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.pre.1
5
+ prerelease: 4
6
+ platform: ruby
7
+ authors:
8
+ - Conrad Irwin
9
+ - banisterfiend
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-08-12 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: pry-stack_explorer
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ description: Allows you to wrap code in Pry::capture{ } to open a pry session at any
32
+ unhandled exceptions
33
+ email:
34
+ - conrad.irwin@gmail.com
35
+ - jrmair@gmail.com
36
+ executables: []
37
+ extensions: []
38
+ extra_rdoc_files: []
39
+ files:
40
+ - LICENSE.MIT
41
+ - README.md
42
+ - Rakefile
43
+ - examples/example.rb
44
+ - examples/example2.rb
45
+ - lib/pry-capture.rb
46
+ - lib/pry-capture/cli.rb
47
+ - lib/pry-capture/commands.rb
48
+ - lib/pry-capture/core_ext.rb
49
+ - pry-capture.gemspec
50
+ homepage: https://github.com/ConradIrwin/pry-capture
51
+ licenses: []
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>'
66
+ - !ruby/object:Gem::Version
67
+ version: 1.3.1
68
+ requirements: []
69
+ rubyforge_project:
70
+ rubygems_version: 1.8.24
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Open a pry session on any unhandled exceptions
74
+ test_files: []
75
+ has_rdoc: