pry-em 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/pry-em.rb +88 -38
  2. metadata +12 -10
data/lib/pry-em.rb CHANGED
@@ -1,45 +1,84 @@
1
1
  EmCommands = Pry::CommandSet.new do
2
2
 
3
- EM_DESCRIPTION = "Wait for a deferrable for a length of time (default 3 seconds). `em 3: EM::HttpRequest.new(url).get`"
4
- EM_CONFIG = {
5
- :keep_retval => true,
6
- :interpolate => false,
7
- :listing => "em",
8
- :requires_gem => 'eventmachine'
9
- }
10
-
11
- command /\s*em\s*([0-9\.]*)\s*:(.*)/, EM_DESCRIPTION, EM_CONFIG do |timeout, source|
12
-
13
- # Boot EM before eval'ing the source as it's likely to depend on the reactor.
14
- run_em_if_necessary!
15
-
16
- # This can happen for example if you do:
17
- # em: EM::HttpRequest.new("http://www.google.com/").get.callback{ binding.pry }
18
- # There ought to be a solution, but it will involve shunting either Pry or EM
19
- # onto a new thread.
20
- if EM.reactor_thread == Thread.current
21
- raise "Could not wait for deferrable, you're in the EM thread!
22
- If you don't know what to do, try `cd ..`, or just hit ctrl-C until it dies."
23
- end
3
+ create_command /\s*em\s*([0-9\.]*)\s*:(.*)/ do
24
4
 
25
- deferrable = target.eval(source)
5
+ description "Wait for a deferrable for a length of time (default 3 seconds). `em 3: EM::HttpRequest.new(url).get`"
6
+ options(
7
+ :keep_retval => true,
8
+ :interpolate => false,
9
+ :listing => "em",
10
+ :requires_gem => 'eventmachine'
11
+ )
26
12
 
27
- # TODO: Allow the user to configure the default timeout
28
- timeout = timeout == "" ? 3 : Float(timeout)
13
+ def process(timeout, source)
14
+ # We store the retval and the em-state in globals so that we can catch exceptions
15
+ # raised in the event loop and pass them back pretending to the user that the
16
+ # exception was caused by their currently executing command.
17
+ #
18
+ # We don't want to keep turning the reactor on and off, as that would limit some
19
+ # of the things the user might want to do.
20
+ @@retval, @@em_state = [nil, :waiting]
29
21
 
30
- wait_for_deferrable(deferrable, timeout) unless deferrable.nil?
31
- end
22
+ # Boot EM before eval'ing the source as it's likely to depend on the reactor.
23
+ run_em_if_necessary!
24
+
25
+ # This can happen for example if you do:
26
+ # em: EM::HttpRequest.new("http://www.google.com/").get.callback{ binding.pry }
27
+ # There ought to be a solution, but it will involve shunting either Pry or EM
28
+ # onto a new thread.
29
+ if EM.reactor_thread == Thread.current
30
+ raise "Could not wait for deferrable, you're in the EM thread!
31
+ If you don't know what to do, try `cd ..`, or just hit ctrl-C until it dies."
32
+ end
33
+
34
+ deferrable = target.eval(source)
35
+
36
+ # TODO: Allow the user to configure the default timeout
37
+ timeout = timeout == "" ? 3 : Float(timeout)
38
+
39
+ wait_for_deferrable(deferrable, timeout) unless deferrable.nil?
40
+ end
32
41
 
33
- helpers do
34
42
  # Boot a new EventMachine reactor into another thread.
35
43
  # This allows us to continue to interact with the user on the front-end thread,
36
44
  # while they run event-machine commands in the background.
37
45
  def run_em_if_necessary!
38
46
  require 'eventmachine' unless defined?(EM)
39
- Thread.new{ EM.run } unless EM.reactor_running?
47
+ unless EM.reactor_running?
48
+ Thread.new do
49
+ EM.error_handler{ |e| handle_unexpected_error(e) }
50
+ begin
51
+ EM.run
52
+ rescue Pry::RescuableException => e
53
+ handle_unexpected_error(e)
54
+ end
55
+ end
56
+ end
40
57
  sleep 0.01 until EM.reactor_running?
41
58
  end
42
59
 
60
+ # If we were the ones to start the EM reactor, we want to catch
61
+ # any exceptions that are raised therein and tell the user about
62
+ # them.
63
+ #
64
+ # If they are still waiting for an async event, assume that this
65
+ # was in relation to that.
66
+ #
67
+ # If not, just print out the error and hope they don't get too
68
+ # confused.
69
+ def handle_unexpected_error(e)
70
+ if waiting?
71
+ @@em_state = :em_error
72
+ @@retval = e
73
+ else
74
+ output.puts "Unexpected exception from EventMachine reactor"
75
+ _pry_.last_exception = e
76
+ _pry_.show_result(e)
77
+ end
78
+ rescue => e
79
+ puts e
80
+ end
81
+
43
82
  # Run a deferrable on an EM reactor in a different thread,
44
83
  # sleep until it has finished, and then return the result.
45
84
  #
@@ -50,29 +89,40 @@ EmCommands = Pry::CommandSet.new do
50
89
  #
51
90
  def wait_for_deferrable(deferrable, timeout)
52
91
 
53
- retval, finished = nil
54
-
55
- EM::Timer.new(timeout) { finished ||= :timeout }
92
+ EM::Timer.new(timeout) { @@em_state = :timeout if waiting? }
56
93
 
57
94
  [:callback, :errback].each do |method|
58
95
  begin
59
96
  deferrable.__send__ method do |*result|
60
- finished = method
61
- retval = result.size > 1 ? result : result.first
97
+ @@em_state = method
98
+ @@retval = result.size > 1 ? result : result.first
62
99
  end
63
100
  rescue NoMethodError
64
- output.warn "WARNING: is not deferrable? #{deferrable}"
101
+ output.puts "WARNING: is not deferrable? #{deferrable}"
65
102
  break
66
103
  end
67
104
  end
68
105
 
69
- sleep 0.01 until finished
106
+ sleep 0.01 until @@em_state != :waiting
107
+
108
+ raise "Timeout after #{timeout} seconds" if @@em_state == :timeout
70
109
 
71
- raise "Timeout after #{timeout} seconds" if finished == :timeout
110
+ # Use Pry's (admittedly nascent) handling for exceptions where possible.
111
+ raise @@retval if @@em_state != :callback && Exception === @@retval
72
112
 
73
113
  # TODO: This doesn't interact well with the pager.
74
- output.print "#{finished} " #=>
75
- retval
114
+ output.print "#{@@em_state} " #=>
115
+ @@retval
116
+
117
+ # If the main thread is interrupted we must ensure that the @@em_state
118
+ # is no-longer :waiting so that handle_unexpected_error can do the
119
+ # right thing.
120
+ ensure
121
+ @@em_state = :interrupted if waiting?
122
+ end
123
+
124
+ def waiting?
125
+ @@em_state == :waiting
76
126
  end
77
127
  end
78
128
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-em
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease:
4
+ hash: 23
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Conrad Irwin
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-07-24 00:00:00 -07:00
18
+ date: 2012-02-24 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -24,12 +24,14 @@ dependencies:
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ">="
27
+ - - ">"
28
28
  - !ruby/object:Gem::Version
29
- hash: 3
29
+ hash: 43
30
30
  segments:
31
31
  - 0
32
- version: "0"
32
+ - 9
33
+ - 8
34
+ version: 0.9.8
33
35
  type: :runtime
34
36
  version_requirements: *id001
35
37
  - !ruby/object:Gem::Dependency
@@ -88,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
90
  requirements: []
89
91
 
90
92
  rubyforge_project:
91
- rubygems_version: 1.6.2
93
+ rubygems_version: 1.3.7
92
94
  signing_key:
93
95
  specification_version: 3
94
96
  summary: Provides an em! function that can be used to play with deferrable more easily.