iruby 0.6.0 → 0.7.3

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.
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