iruby 0.6.0 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/iruby/kernel.rb CHANGED
@@ -8,10 +8,26 @@ module IRuby
8
8
  @events = EventManager.new([:initialized])
9
9
 
10
10
  class << self
11
+ # Return the event manager defined in the `IRuby::Kernel` class.
12
+ # This event manager can handle the following event:
13
+ #
14
+ # - `initialized`: The event occurred after the initialization of
15
+ # a `IRuby::Kernel` instance is finished
16
+ #
17
+ # @example Registering initialized event
18
+ # IRuby::Kernel.events.register(:initialized) do |result|
19
+ # STDERR.puts "IRuby kernel has been initialized"
20
+ # end
21
+ #
22
+ # @see IRuby::EventManager
23
+ # @see IRuby::Kernel#events
11
24
  attr_reader :events
25
+
26
+ # Returns the singleton kernel instance
12
27
  attr_accessor :instance
13
28
  end
14
29
 
30
+ # Returns a session object
15
31
  attr_reader :session
16
32
 
17
33
  EVENTS = [
@@ -34,21 +50,77 @@ module IRuby
34
50
 
35
51
  @events = EventManager.new(EVENTS)
36
52
  @execution_count = 0
37
- @backend = create_backend
53
+ @backend = PlainBackend.new
38
54
  @running = true
39
55
 
40
56
  self.class.events.trigger(:initialized, self)
41
57
  end
42
58
 
59
+ # Returns the event manager defined in a `IRuby::Kernel` instance.
60
+ # This event manager can handle the following events:
61
+ #
62
+ # - `pre_execute`: The event occurred before running the code
63
+ #
64
+ # - `pre_run_cell`: The event occurred before running the code and
65
+ # if the code execution is not silent
66
+ #
67
+ # - `post_execute`: The event occurred after running the code
68
+ #
69
+ # - `post_run_cell`: The event occurred after running the code and
70
+ # if the code execution is not silent
71
+ #
72
+ # The callback functions of `pre_run_cell` event must take one argument
73
+ # to get an `ExecutionInfo` object.
74
+ # The callback functions of `post_run_cell` event must take one argument
75
+ # to get the result of the code execution.
76
+ #
77
+ # @example Registering post_run_cell event
78
+ # IRuby::Kernel.instance.events.register(:post_run_cell) do |result|
79
+ # STDERR.puts "The result of the last execution: %p" % result
80
+ # end
81
+ #
82
+ # @see IRuby::EventManager
83
+ # @see IRuby::ExecutionInfo
84
+ # @see IRuby::Kernel.events
43
85
  attr_reader :events
44
86
 
45
- def create_backend
46
- PryBackend.new
47
- rescue Exception => e
48
- IRuby.logger.warn "Could not load PryBackend: #{e.message}\n#{e.backtrace.join("\n")}" unless LoadError === e
49
- PlainBackend.new
87
+ # Switch the backend (interactive shell) system
88
+ #
89
+ # @param backend [:irb,:plain,:pry] Specify the backend name switched to
90
+ #
91
+ # @return [true,false] true if the switching succeeds, otherwise false
92
+ def switch_backend!(backend)
93
+ name = case backend
94
+ when String, Symbol
95
+ name = backend.downcase
96
+ else
97
+ name = backend
98
+ end
99
+
100
+ backend_class = case name
101
+ when :irb, :plain
102
+ PlainBackend
103
+ when :pry
104
+ PryBackend
105
+ else
106
+ raise ArgumentError,
107
+ "Unknown backend name: %p" % backend
108
+ end
109
+
110
+ begin
111
+ new_backend = backend_class.new
112
+ @backend = new_backend
113
+ true
114
+ rescue Exception => e
115
+ unless LoadError === e
116
+ IRuby.logger.warn "Could not load #{backend_class}: " +
117
+ "#{e.message}\n#{e.backtrace.join("\n")}"
118
+ end
119
+ return false
120
+ end
50
121
  end
51
122
 
123
+ # @private
52
124
  def run
53
125
  send_status :starting
54
126
  while @running
@@ -56,6 +128,7 @@ module IRuby
56
128
  end
57
129
  end
58
130
 
131
+ # @private
59
132
  def dispatch
60
133
  msg = @session.recv(:reply)
61
134
  IRuby.logger.debug "Kernel#dispatch: msg = #{msg}"
@@ -72,6 +145,7 @@ module IRuby
72
145
  @session.send(:publish, :error, error_content(e))
73
146
  end
74
147
 
148
+ # @private
75
149
  def kernel_info_request(msg)
76
150
  @session.send(:reply, :kernel_info_reply,
77
151
  protocol_version: '5.0',
@@ -93,11 +167,13 @@ module IRuby
93
167
  status: :ok)
94
168
  end
95
169
 
170
+ # @private
96
171
  def send_status(status)
97
172
  IRuby.logger.debug "Send status: #{status}"
98
173
  @session.send(:publish, :status, execution_state: status)
99
174
  end
100
175
 
176
+ # @private
101
177
  def execute_request(msg)
102
178
  code = msg[:content]['code']
103
179
  store_history = msg[:content]['store_history']
@@ -134,16 +210,20 @@ module IRuby
134
210
  content[:execution_count] = @execution_count
135
211
  end
136
212
 
213
+ unless result.nil? || silent
214
+ @session.send(:publish, :execute_result,
215
+ data: Display.display(result),
216
+ metadata: {},
217
+ execution_count: @execution_count)
218
+ end
219
+
137
220
  events.trigger(:post_execute)
138
221
  events.trigger(:post_run_cell, result) unless silent
139
222
 
140
223
  @session.send(:reply, :execute_reply, content)
141
- @session.send(:publish, :execute_result,
142
- data: Display.display(result),
143
- metadata: {},
144
- execution_count: @execution_count) unless result.nil? || msg[:content]['silent']
145
224
  end
146
225
 
226
+ # @private
147
227
  def error_content(e)
148
228
  rindex = e.backtrace.rindex{|line| line.start_with?(@backend.eval_path)} || -1
149
229
  backtrace = SyntaxError === e && rindex == -1 ? [] : e.backtrace[0..rindex]
@@ -152,12 +232,14 @@ module IRuby
152
232
  traceback: ["#{RED}#{e.class}#{RESET}: #{e.message}", *backtrace] }
153
233
  end
154
234
 
235
+ # @private
155
236
  def is_complete_request(msg)
156
237
  # FIXME: the code completeness should be judged by using ripper or other Ruby parser
157
238
  @session.send(:reply, :is_complete_reply,
158
239
  status: :unknown)
159
240
  end
160
241
 
242
+ # @private
161
243
  def complete_request(msg)
162
244
  # HACK for #26, only complete last line
163
245
  code = msg[:content]['code']
@@ -173,36 +255,43 @@ module IRuby
173
255
  status: :ok)
174
256
  end
175
257
 
258
+ # @private
176
259
  def connect_request(msg)
177
260
  @session.send(:reply, :connect_reply, Hash[%w(shell_port iopub_port stdin_port hb_port).map {|k| [k, @config[k]] }])
178
261
  end
179
262
 
263
+ # @private
180
264
  def shutdown_request(msg)
181
265
  @session.send(:reply, :shutdown_reply, msg[:content])
182
266
  @running = false
183
267
  end
184
268
 
269
+ # @private
185
270
  def history_request(msg)
186
271
  # we will just send back empty history for now, pending clarification
187
272
  # as requested in ipython/ipython#3806
188
273
  @session.send(:reply, :history_reply, history: [])
189
274
  end
190
275
 
276
+ # @private
191
277
  def inspect_request(msg)
192
278
  # not yet implemented. See (#119).
193
279
  @session.send(:reply, :inspect_reply, status: :ok, found: false, data: {}, metadata: {})
194
280
  end
195
281
 
282
+ # @private
196
283
  def comm_open(msg)
197
284
  comm_id = msg[:content]['comm_id']
198
285
  target_name = msg[:content]['target_name']
199
286
  Comm.comm[comm_id] = Comm.target[target_name].new(target_name, comm_id)
200
287
  end
201
288
 
289
+ # @private
202
290
  def comm_msg(msg)
203
291
  Comm.comm[msg[:content]['comm_id']].handle_msg(msg[:content]['data'])
204
292
  end
205
293
 
294
+ # @private
206
295
  def comm_close(msg)
207
296
  comm_id = msg[:content]['comm_id']
208
297
  Comm.comm[comm_id].handle_close(msg[:content]['data'])
data/lib/iruby/session.rb CHANGED
@@ -10,6 +10,7 @@ module IRuby
10
10
  def initialize(config, adapter_name=nil)
11
11
  @config = config
12
12
  @adapter = create_session_adapter(config, adapter_name)
13
+ @last_recvd_msg = nil
13
14
 
14
15
  setup
15
16
  setup_sockets
data/lib/iruby/utils.rb CHANGED
@@ -4,37 +4,48 @@ module IRuby
4
4
  Display.convert(object, options)
5
5
  end
6
6
 
7
+ # Display the object
7
8
  def display(obj, options = {})
8
9
  Kernel.instance.session.send(:publish, :display_data,
9
10
  data: Display.display(obj, options),
10
11
  metadata: {}) unless obj.nil?
12
+ # The next `nil` is necessary to prevent unintentional displaying
13
+ # the result of Session#send
14
+ nil
11
15
  end
12
16
 
17
+ # Clear the output area
13
18
  def clear_output(wait=false)
14
19
  Display.clear_output(wait)
15
20
  end
16
21
 
22
+ # Format the given object into HTML table
17
23
  def table(s, **options)
18
- html(HTML.table(s, options))
24
+ html(HTML.table(s, **options))
19
25
  end
20
26
 
27
+ # Treat the given string as LaTeX text
21
28
  def latex(s)
22
29
  convert(s, mime: 'text/latex')
23
30
  end
24
31
  alias tex latex
25
32
 
33
+ # Format the given string of TeX equation into LaTeX text
26
34
  def math(s)
27
35
  convert("$$#{s}$$", mime: 'text/latex')
28
36
  end
29
37
 
38
+ # Treat the given string as HTML
30
39
  def html(s)
31
40
  convert(s, mime: 'text/html')
32
41
  end
33
42
 
43
+ # Treat the given string as JavaScript code
34
44
  def javascript(s)
35
45
  convert(s, mime: 'application/javascript')
36
46
  end
37
47
 
48
+ # Treat the given string as SVG text
38
49
  def svg(s)
39
50
  convert(s, mime: 'image/svg+xml')
40
51
  end
data/lib/iruby/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module IRuby
2
- VERSION = '0.6.0'
2
+ VERSION = '0.7.3'
3
3
  end
data/test/helper.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require "iruby"
2
- require "iruby/logger"
3
2
  require "json"
4
3
  require 'multi_json'
5
4
  require "pathname"
@@ -38,10 +37,14 @@ module IRubyTest
38
37
  @__config_path.to_s
39
38
  end
40
39
 
41
- def teardown
40
+ def self.restore_kernel
42
41
  IRuby::Kernel.instance = @__original_kernel_instance
43
42
  end
44
43
 
44
+ def teardown
45
+ self.class.restore_kernel
46
+ end
47
+
45
48
  def with_session_adapter(session_adapter_name)
46
49
  IRuby::Kernel.new(self.class.test_config_filename, session_adapter_name)
47
50
  $stdout = STDOUT
@@ -8,6 +8,12 @@ module IRubyTest
8
8
  assert_equal 3, @plainbackend.eval('1+2', false)
9
9
  end
10
10
 
11
+ def test_include_module
12
+ assert_nothing_raised do
13
+ @plainbackend.eval("include Math, Comparable", false)
14
+ end
15
+ end
16
+
11
17
  def test_complete_req
12
18
  assert_includes @plainbackend.complete('req'), 'require'
13
19
  end
@@ -26,6 +32,12 @@ module IRubyTest
26
32
  assert_equal 3, @prybackend.eval('1+2', false)
27
33
  end
28
34
 
35
+ def test_include_module
36
+ assert_nothing_raised do
37
+ @prybackend.eval("include Math, Comparable", false)
38
+ end
39
+ end
40
+
29
41
  def test_complete_req
30
42
  assert_includes @prybackend.complete('req'), 'require'
31
43
  end
@@ -0,0 +1,185 @@
1
+ module IRubyTest
2
+ class DisplayTest < TestBase
3
+ def setup
4
+ @object = Object.new
5
+ @object.instance_variable_set(:@to_html_called, false)
6
+ @object.instance_variable_set(:@to_markdown_called, false)
7
+ @object.instance_variable_set(:@to_iruby_called, false)
8
+ @object.instance_variable_set(:@to_iruby_mimebundle_called, false)
9
+
10
+ class << @object
11
+ attr_reader :to_html_called
12
+ attr_reader :to_markdown_called
13
+ attr_reader :to_iruby_called
14
+ attr_reader :to_iruby_mimebundle_called
15
+
16
+ def html
17
+ "<b>html</b>"
18
+ end
19
+
20
+ def markdown
21
+ "*markdown*"
22
+ end
23
+
24
+ def inspect
25
+ "!!! inspect !!!"
26
+ end
27
+ end
28
+ end
29
+
30
+ def define_to_html
31
+ class << @object
32
+ def to_html
33
+ @to_html_called = true
34
+ html
35
+ end
36
+ end
37
+ end
38
+
39
+ def define_to_markdown
40
+ class << @object
41
+ def to_markdown
42
+ @to_markdown_called = true
43
+ markdown
44
+ end
45
+ end
46
+ end
47
+
48
+ def define_to_iruby
49
+ class << @object
50
+ def to_iruby
51
+ @to_iruby_called = true
52
+ ["text/html", "<b>to_iruby</b>"]
53
+ end
54
+ end
55
+ end
56
+
57
+ def define_to_iruby_mimebundle
58
+ class << @object
59
+ def to_iruby_mimebundle(include: [])
60
+ @to_iruby_mimebundle_called = true
61
+ mimes = if include.empty?
62
+ ["text/markdown", "application/json"]
63
+ else
64
+ include
65
+ end
66
+ formats = mimes.map { |mime|
67
+ result = case mime
68
+ when "text/markdown"
69
+ "**markdown**"
70
+ when "application/json"
71
+ %Q[{"mimebundle": "json"}]
72
+ end
73
+ [mime, result]
74
+ }.to_h
75
+ metadata = {}
76
+ return formats, metadata
77
+ end
78
+ end
79
+ end
80
+
81
+ def assert_iruby_display(expected)
82
+ assert_equal(expected,
83
+ {
84
+ result: IRuby::Display.display(@object),
85
+ to_html_called: @object.to_html_called,
86
+ to_markdown_called: @object.to_markdown_called,
87
+ to_iruby_called: @object.to_iruby_called,
88
+ to_iruby_mimebundle_called: @object.to_iruby_mimebundle_called
89
+ })
90
+ end
91
+
92
+ sub_test_case("the object cannot handle all the mime types") do
93
+ def test_display
94
+ assert_iruby_display({
95
+ result: {"text/plain" => "!!! inspect !!!"},
96
+ to_html_called: false,
97
+ to_markdown_called: false,
98
+ to_iruby_called: false,
99
+ to_iruby_mimebundle_called: false
100
+ })
101
+ end
102
+ end
103
+
104
+ sub_test_case("the object can respond to to_iruby") do
105
+ def setup
106
+ super
107
+ define_to_iruby
108
+ end
109
+
110
+ def test_display
111
+ assert_iruby_display({
112
+ result: {
113
+ "text/html" => "<b>to_iruby</b>",
114
+ "text/plain" => "!!! inspect !!!"
115
+ },
116
+ to_html_called: false,
117
+ to_markdown_called: false,
118
+ to_iruby_called: true,
119
+ to_iruby_mimebundle_called: false
120
+ })
121
+ end
122
+
123
+ sub_test_case("the object can respond to to_markdown") do
124
+ def setup
125
+ super
126
+ define_to_markdown
127
+ end
128
+
129
+ def test_display
130
+ assert_iruby_display({
131
+ result: {
132
+ "text/markdown" => "*markdown*",
133
+ "text/plain" => "!!! inspect !!!"
134
+ },
135
+ to_html_called: false,
136
+ to_markdown_called: true,
137
+ to_iruby_called: false,
138
+ to_iruby_mimebundle_called: false
139
+ })
140
+ end
141
+ end
142
+
143
+ sub_test_case("the object can respond to to_html") do
144
+ def setup
145
+ super
146
+ define_to_html
147
+ end
148
+
149
+ def test_display
150
+ assert_iruby_display({
151
+ result: {
152
+ "text/html" => "<b>html</b>",
153
+ "text/plain" => "!!! inspect !!!"
154
+ },
155
+ to_html_called: true,
156
+ to_markdown_called: false,
157
+ to_iruby_called: false,
158
+ to_iruby_mimebundle_called: false
159
+ })
160
+ end
161
+
162
+ sub_test_case("the object can respond to to_iruby_mimebundle") do
163
+ def setup
164
+ super
165
+ define_to_iruby_mimebundle
166
+ end
167
+
168
+ def test_display
169
+ assert_iruby_display({
170
+ result: {
171
+ "text/markdown" => "**markdown**",
172
+ "application/json" => %Q[{"mimebundle": "json"}],
173
+ "text/plain" => "!!! inspect !!!"
174
+ },
175
+ to_html_called: false,
176
+ to_markdown_called: false,
177
+ to_iruby_called: false,
178
+ to_iruby_mimebundle_called: true
179
+ })
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end