pry-rescue 0.9.1 → 0.10.pre.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -119,6 +119,104 @@ From: examples/example.rb @ line 4 Object#test:
119
119
  foo
120
120
  ```
121
121
 
122
+ <a name="peeking"/>
123
+ Peeking
124
+ =======
125
+
126
+ Someones bugs in your program don't cause exceptions. Instead your program just gets
127
+ stuck. Examples include infinite loops, slow network calls, or badly backtracking
128
+ parsers.
129
+
130
+ In this case it's useful to be able to open a pry console when you notice that your
131
+ program is not going anywhere. To enable this feature you need to run:
132
+
133
+ ```
134
+ rescue --peek <script.rb>
135
+ ```
136
+
137
+ Then hit `<ctrl+c>` at any time to stop your program and have a peek at what it's actually
138
+ doing. Hitting `<ctrl-c>` a second time will quit your program, if that's what you were
139
+ trying to do.
140
+
141
+ Automatic peeking
142
+ =================
143
+
144
+ Remembering to run your program with `rescue --peek` manually is a bit frustrating (as you
145
+ don't know you need to peek, until you need to peek) and so pry-rescue also allows you to
146
+ peek into any program at any time by sending it a `SIGUSR2` signal.
147
+
148
+ The easiest way to do this is to hit `<ctrl-z>` to interrupt your program, then type
149
+ `kill -SIGUSR2 %1 && fg` into bash. For example:
150
+
151
+ <!-- TODO syntax highlighting! -->
152
+ ```
153
+ cirwin@localhost:/tmp/pry $ ruby examples/loop.rb
154
+ ^Z
155
+ cirwin@localhost:/tmp/pry $ kill -SIGUSR2 %1 && fg
156
+ [1] + continued ./examples/loop.rb
157
+ Preparing to peek via pry!
158
+ Frame number: 0/4
159
+
160
+ From: ./examples/loop.rb @ line 10 Object#r
161
+ 10: def r
162
+ 11: some_var = 13
163
+ 12: loop do
164
+ => 13: x = File.readlines('lib/pry-rescue.rb')
165
+ 14: end
166
+ 15: end
167
+ pry (main)>
168
+ ```
169
+
170
+ If you find that that's a bit hard to remember (I know I do), then you can make it easier
171
+ by adding the following alias to your `~/.bashrc` or similar:
172
+
173
+ ```
174
+ alias peek='kill -SIGUSR2 %1 && fg'
175
+ ```
176
+
177
+ Then you can just type `peek` instead of `kill -SIGUSR2 %1 && fg`
178
+
179
+ Advanced peeking
180
+ ================
181
+
182
+ You can configure which signal pry-rescue listens for by default by exporting the PRY_PEEK
183
+ environment variable that suits your use-case best:
184
+
185
+ ```
186
+ export PRY_PEEK="" # don't autopeek at all
187
+ export PRY_PEEK=INT # peek on SIGINT (<ctrl+c>)
188
+ export PRY_PEEK=USR1 # peek on SIGUSR1
189
+ export PRY_PEEK=USR2 # peek on SIGUSR2
190
+ export PRY_PEEK=EXIT # peek on program exit
191
+ ```
192
+
193
+ If it's only important for one program, then you can also set the environment variable in
194
+ ruby before requiring pry-rescue
195
+
196
+ ```ruby
197
+ ENV['PRY_PEEK'] = '' # disable SIGUSR2 handler
198
+ require "pry-rescue"
199
+ ```
200
+
201
+ Finally, you can enable peeking into programs that do not include pry-rescue by
202
+ configuring ruby to always load one (or several) of these files:
203
+
204
+ ```
205
+ export RUBYOPT=-rpry-rescue/peek/int # peek on SIGINT (<ctrl-c>)
206
+ export RUBYOPT=-rpry-rescue/peek/usr1 # peek on SIGUSR1
207
+ export RUBYOPT=-rpry-rescue/peek/usr2 # peek on SIGUSR2
208
+ export RUBYOPT=-rpry-rescue/peek/exit # peek on program exit
209
+ ```
210
+
211
+ These last examples relies on having pry-rescue in the load path (i.e. at least in the
212
+ gemset, or Gemfile of the program). If that is not true, you can use absolute paths. The
213
+ hook files do not require the whole of pry-rescue, nor is any of pry itself loaded until
214
+ you trigger the signal.
215
+
216
+ ```
217
+ export RUBYOPT=-r/home/cirwin/src/pry-rescue/lib/pry-rescue/peek/usr2
218
+ ```
219
+
122
220
  pry-stack explorer
123
221
  ==================
124
222
 
data/bin/rescue CHANGED
@@ -4,7 +4,7 @@ USAGE = %{
4
4
  rescue (pry-rescue wrapper)
5
5
 
6
6
  Usage:
7
- rescue <script.rb> [arguments...]
7
+ rescue [--peek] <script.rb> [arguments...]
8
8
 
9
9
  What it does:
10
10
  Runs <script.rb>, and if an uncaught exception is raised,
@@ -13,9 +13,25 @@ What it does:
13
13
 
14
14
  You can then poke around to figure out why your code broke!
15
15
 
16
- (Not yet available: fixing the problem and continuing your program.)
16
+ If --peek is specified, then you can hit <Ctrl+C> to interrupt
17
+ your program and open a pry session at any time you need.
17
18
 
19
+ See the README (http://bitly.com/pry-rescue) for more.
18
20
  }
21
+ case ARGV[0]
22
+ when '-h', '--help'
23
+ puts USAGE
24
+ exit
25
+ when /\A--peek\z/
26
+ ARGV.shift
27
+ ENV['PRY_PEEK'] = 'INT'
28
+ require "pry-rescue/peek/int"
29
+ when '--'
30
+ ARGV.shift
31
+ when /\A-/
32
+ puts USAGE
33
+ exit
34
+ end
19
35
 
20
36
  if ARGV[0] == 'rails'
21
37
  ENV['PRY_RESCUE_RAILS'] = 'true'
data/examples/example.rb CHANGED
@@ -1,3 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # cd-cause example
4
+ #
5
+ # Try running with: ./examples/example.rb
6
+ #
7
+ # When pry opens you can `cd-cause` a few times to see which exception
8
+ # triggered all these buggy rescue blocks!
1
9
  $:.unshift File.expand_path '../../lib', __FILE__
2
10
  require 'pry-rescue'
3
11
 
data/examples/example2.rb CHANGED
@@ -1,3 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # pry-stack_explorer example
3
+ #
4
+ # Run with ./examples/example2.rb
5
+ #
6
+ # When pry opens you'll be able to move "up" and "down" the stack and see
7
+ # what's happening at all levels.
8
+
1
9
  $:.unshift File.expand_path '../../lib', __FILE__
2
10
  require 'pry-rescue'
3
11
 
data/examples/loop.rb ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pry-rescue'
3
+
4
+ # Peeking example! Try running this example with:
5
+ #
6
+ # rescue --peek example/loop.rb
7
+ #
8
+ # Then hit <ctrl-c>, and be able to see what's going on.
9
+
10
+ def r
11
+ some_var = 13
12
+ loop do
13
+ x = File.readlines('lib/pry-rescue.rb')
14
+ end
15
+ end
16
+ r
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # Advanced peeking example, showing how to catch the EXIT signal
3
+ #
4
+ # Try running with:
5
+ #
6
+ # RUBYOPT=-rpry-rescue/peek/exit examples/random-exit.rb
7
+ #
8
+ def haywire arg
9
+ # TODO: Figure out how to pry at the "arg" value
10
+ if 3 == arg
11
+ exit 1
12
+ end
13
+ end
14
+
15
+ def dangerous
16
+ choice = rand 55
17
+ haywire choice
18
+ end
19
+
20
+ loop do
21
+ dangerous
22
+ end
data/examples/rescue.rb CHANGED
@@ -1,5 +1,12 @@
1
+ #!/usr/bin/env ruby
1
2
  # Slightly silly example written for http://cirw.in/blog/pry-to-the-rescue
2
3
  # (NOTE: the solution in the blog post only works on ruby-1.9)
4
+ #
5
+ # try running this with: rescue ./examples/rescue.rb
6
+ #
7
+ # When pry opens, see if you can use edit-method and try-again to fix the
8
+ # code and test that your code works.
9
+ #
3
10
  def find_capitalized(a)
4
11
  a.select do |name|
5
12
  name.chars.first == name.chars.first.upcase
data/lib/pry-rescue.rb CHANGED
@@ -5,10 +5,19 @@ require 'pry'
5
5
  require File.expand_path('../pry-rescue/core_ext', __FILE__)
6
6
  require File.expand_path('../pry-rescue/commands', __FILE__)
7
7
  require File.expand_path('../pry-rescue/rack', __FILE__)
8
+ require File.expand_path('../pry-rescue/peek.rb', __FILE__)
8
9
 
9
10
  if ENV['PRY_RESCUE_RAILS']
10
11
  require File.expand_path('../pry-rescue/rails', __FILE__)
11
12
  end
13
+ case ENV['PRY_PEEK']
14
+ when nil
15
+ PryRescue.peek_on_signal('USR2')
16
+ when ''
17
+ # explicitly disable USR2.
18
+ else
19
+ PryRescue.peek_on_signal(ENV['PRY_PEEK'])
20
+ end
12
21
 
13
22
  begin
14
23
  require 'pry-stack_explorer'
@@ -94,10 +103,24 @@ class PryRescue
94
103
  # @return [Boolean]
95
104
  def user_path?(file)
96
105
  !file.start_with?(RbConfig::CONFIG['libdir']) &&
97
- !Gem::Specification.any?{ |gem| file.start_with?(gem.full_gem_path) } &&
106
+ !gem_path?(file) &&
98
107
  !(file == '<internal:prelude>')
99
108
  end
100
109
 
110
+ # Is this path included in a gem?
111
+ #
112
+ # @param [String] file the absolute path
113
+ # @return [Boolean]
114
+ def gem_path?(file)
115
+ # rubygems 1.8
116
+ if Gem::Specification.respond_to?(:any?)
117
+ Gem::Specification.any?{ |gem| file.start_with?(gem.full_gem_path) }
118
+ # rubygems 1.6
119
+ else
120
+ Gem.all_load_paths.any?{ |path| file.start_with?(path) }
121
+ end
122
+ end
123
+
101
124
  # Remove bindings that are part of Interception/Pry.rescue's internal
102
125
  # event handling that happens as part of the exception hooking process.
103
126
  #
@@ -0,0 +1,18 @@
1
+ class PryRescue
2
+ def self.peek_on_signal signal
3
+ trap signal, &method(:peek!)
4
+ end
5
+
6
+ # Called when rescue --peek is used and the user hits <Ctrl+C>
7
+ # or sends whichever signal is configured.
8
+ def self.peek!(*)
9
+ puts 'Preparing to peek via pry!' unless ENV['NO_PEEK_STARTUP_MESSAGE']
10
+ require 'pry'
11
+ unless binding.respond_to?(:of_caller)
12
+ raise "pry-stack_explorer is not installed"
13
+ end
14
+ throw :raise_up, Interrupt if Pry === binding.of_caller(1).eval('self')
15
+ binding.of_caller(1).pry
16
+ # TODO pry :call_stack => binding.of_callers, :initial_frame => 1
17
+ end
18
+ end
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__)
2
+ PryRescue.peek_on_signal 'EXIT'
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__)
2
+ PryRescue.peek_on_signal 'INT'
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__)
2
+ PryRescue.peek_on_signal 'USR1'
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__)
2
+ PryRescue.peek_on_signal 'USR2'
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 = '0.9.1'
3
+ s.version = '0.10.pre.1'
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'
data/spec/peek_spec.rb ADDED
@@ -0,0 +1,29 @@
1
+ ENV['NO_PEEK_STARTUP_MESSAGE'] = 'true'
2
+
3
+ describe "PryRescue.peek!" do
4
+ it "should open a pry in the binding of caller" do
5
+ Pry.config.input = StringIO.new("foo = 6\nexit\n")
6
+ Pry.config.output = StringIO.new
7
+ foo = 5
8
+
9
+ lambda do
10
+ PryRescue.peek!
11
+ end.should change{ foo }.from(5).to(6)
12
+ end
13
+
14
+ # this will fail, or not?
15
+ it 'should include the entire call stack' do
16
+ Pry.config.input = StringIO.new("up\nfoo = 6\nexit\n")
17
+ Pry.config.output = StringIO.new
18
+
19
+ def example_method
20
+ PryRescue.peek!
21
+ end
22
+
23
+ foo = 5
24
+
25
+ lambda do
26
+ PryRescue.peek!
27
+ end.should change{ foo }.from(5).to(6)
28
+ end
29
+ end
@@ -41,7 +41,11 @@ describe "PryRescue.load" do
41
41
 
42
42
  it "should open above gems" do
43
43
  PryRescue.should_receive(:pry).once do |opts|
44
- opts[:call_stack].first.eval("__FILE__").should start_with(Gem::Specification.detect{|x| x.name == 'coderay' }.full_gem_path)
44
+ coderay_path = Gem::Specification.respond_to?(:detect) ?
45
+ Gem::Specification.detect{|x| x.name == 'coderay' }.full_gem_path :
46
+ Gem.all_load_paths.grep(/coderay/).last
47
+
48
+ opts[:call_stack].first.eval("__FILE__").should start_with(coderay_path)
45
49
  end
46
50
  lambda{
47
51
  PryRescue.load("spec/fixtures/coderay.rb")
metadata CHANGED
@@ -1,97 +1,109 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: pry-rescue
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 9
8
- - 1
9
- version: 0.9.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.10.pre.1
5
+ prerelease: 5
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Conrad Irwin
13
9
  - banisterfiend
14
10
  - epitron
15
11
  autorequire:
16
12
  bindir: bin
17
13
  cert_chain: []
18
-
19
- date: 2012-09-30 00:00:00 -07:00
20
- default_executable:
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
14
+ date: 2012-10-03 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
23
17
  name: pry
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- segments:
30
- - 0
31
- version: "0"
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
32
24
  type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: interception
36
25
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- - 3
44
- version: "0.3"
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: interception
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0.3'
45
40
  type: :runtime
46
- version_requirements: *id002
47
- - !ruby/object:Gem::Dependency
48
- name: rspec
49
41
  prerelease: false
50
- requirement: &id003 !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- segments:
55
- - 0
56
- version: "0"
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0.3'
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
57
56
  type: :development
58
- version_requirements: *id003
59
- - !ruby/object:Gem::Dependency
60
- name: yard
61
57
  prerelease: false
62
- requirement: &id004 !ruby/object:Gem::Requirement
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- segments:
67
- - 0
68
- version: "0"
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ - !ruby/object:Gem::Dependency
65
+ name: yard
66
+ requirement: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
69
72
  type: :development
70
- version_requirements: *id004
71
- - !ruby/object:Gem::Dependency
72
- name: redcarpet
73
73
  prerelease: false
74
- requirement: &id005 !ruby/object:Gem::Requirement
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- segments:
79
- - 0
80
- version: "0"
74
+ version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ - !ruby/object:Gem::Dependency
81
+ name: redcarpet
82
+ requirement: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
81
88
  type: :development
82
- version_requirements: *id005
83
- description: Allows you to wrap code in Pry::rescue{ } to open a pry session at any unhandled exceptions
84
- email:
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ description: Allows you to wrap code in Pry::rescue{ } to open a pry session at any
97
+ unhandled exceptions
98
+ email:
85
99
  - conrad.irwin@gmail.com
86
100
  - jrmair@gmail.com
87
101
  - chris@ill-logic.com
88
- executables:
102
+ executables:
89
103
  - rescue
90
104
  extensions: []
91
-
92
105
  extra_rdoc_files: []
93
-
94
- files:
106
+ files:
95
107
  - .gitignore
96
108
  - Gemfile
97
109
  - LICENSE.MIT
@@ -100,11 +112,18 @@ files:
100
112
  - bin/rescue
101
113
  - examples/example.rb
102
114
  - examples/example2.rb
115
+ - examples/loop.rb
116
+ - examples/random-exit.rb
103
117
  - examples/rescue.rb
104
118
  - lib/pry-rescue.rb
105
119
  - lib/pry-rescue/cli.rb
106
120
  - lib/pry-rescue/commands.rb
107
121
  - lib/pry-rescue/core_ext.rb
122
+ - lib/pry-rescue/peek.rb
123
+ - lib/pry-rescue/peek/exit.rb
124
+ - lib/pry-rescue/peek/int.rb
125
+ - lib/pry-rescue/peek/usr1.rb
126
+ - lib/pry-rescue/peek/usr2.rb
108
127
  - lib/pry-rescue/rack.rb
109
128
  - lib/pry-rescue/rails.rb
110
129
  - lib/pry/rescue.rb
@@ -118,36 +137,31 @@ files:
118
137
  - spec/fixtures/simple.rb
119
138
  - spec/fixtures/super.rb
120
139
  - spec/fixtures/uri.rb
140
+ - spec/peek_spec.rb
121
141
  - spec/pry_rescue_spec.rb
122
- has_rdoc: true
123
142
  homepage: https://github.com/ConradIrwin/pry-rescue
124
143
  licenses: []
125
-
126
144
  post_install_message:
127
145
  rdoc_options: []
128
-
129
- require_paths:
146
+ require_paths:
130
147
  - lib
131
- required_ruby_version: !ruby/object:Gem::Requirement
132
- requirements:
133
- - - ">="
134
- - !ruby/object:Gem::Version
135
- segments:
136
- - 0
137
- version: "0"
138
- required_rubygems_version: !ruby/object:Gem::Requirement
139
- requirements:
140
- - - ">="
141
- - !ruby/object:Gem::Version
142
- segments:
143
- - 0
144
- version: "0"
148
+ required_ruby_version: !ruby/object:Gem::Requirement
149
+ none: false
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - ! '>'
158
+ - !ruby/object:Gem::Version
159
+ version: 1.3.1
145
160
  requirements: []
146
-
147
161
  rubyforge_project:
148
- rubygems_version: 1.3.6
162
+ rubygems_version: 1.8.23
149
163
  signing_key:
150
164
  specification_version: 3
151
165
  summary: Open a pry session on any unhandled exceptions
152
166
  test_files: []
153
-
167
+ has_rdoc: