iruby 0.7.4 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,380 @@
1
+ require "fileutils"
2
+ require "json"
3
+ require "optparse"
4
+ require "rbconfig"
5
+ require "singleton"
6
+
7
+ require_relative "error"
8
+ require_relative "kernel_app"
9
+
10
+ module IRuby
11
+ class Application
12
+ include Singleton
13
+
14
+ # Set the application instance up.
15
+ def setup(argv=nil)
16
+ @iruby_executable = File.expand_path($PROGRAM_NAME)
17
+ parse_command_line(argv)
18
+ end
19
+
20
+ # Parse the command line arguments
21
+ #
22
+ # @param argv [Array<String>, nil] The array of arguments.
23
+ private def parse_command_line(argv)
24
+ argv = ARGV.dup if argv.nil?
25
+ @argv = argv # save the original
26
+
27
+ case argv[0]
28
+ when "help"
29
+ # turn `iruby help notebook` into `iruby notebook -h`
30
+ argv = [*argv[1..-1], "-h"]
31
+ when "version"
32
+ # turn `iruby version` into `iruby -v`
33
+ argv = ["-v", *argv[1..-1]]
34
+ else
35
+ argv = argv.dup # prevent to break @argv
36
+ end
37
+
38
+ opts = OptionParser.new
39
+ opts.program_name = "IRuby"
40
+ opts.version = ::IRuby::VERSION
41
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options] [subcommand] [options]"
42
+
43
+ opts.on_tail("-h", "--help") do
44
+ print_help(opts)
45
+ exit
46
+ end
47
+
48
+ opts.on_tail("-v", "--version") do
49
+ puts opts.ver
50
+ exit
51
+ end
52
+
53
+ opts.order!(argv)
54
+
55
+ if argv.length == 0 || argv[0].start_with?("-")
56
+ # If no subcommand is given, we use the console
57
+ argv = ["console", *argv]
58
+ end
59
+
60
+ begin
61
+ parse_sub_command(argv) if argv.length > 0
62
+ rescue InvalidSubcommandError => err
63
+ $stderr.puts err.message
64
+ print_help(opts, $stderr)
65
+ abort
66
+ end
67
+ end
68
+
69
+ SUB_COMMANDS = {
70
+ "register" => "Register IRuby kernel.",
71
+ "unregister" => "Unregister the existing IRuby kernel.",
72
+ "kernel" => "Launch IRuby kernel",
73
+ "console" => "Launch jupyter console with IRuby kernel"
74
+ }.freeze.each_value(&:freeze)
75
+
76
+ private_constant :SUB_COMMANDS
77
+
78
+ private def parse_sub_command(argv)
79
+ sub_cmd, *sub_argv = argv
80
+ case sub_cmd
81
+ when *SUB_COMMANDS.keys
82
+ @sub_cmd = sub_cmd.to_sym
83
+ @sub_argv = sub_argv
84
+ else
85
+ raise InvalidSubcommandError.new(sub_cmd, sub_argv)
86
+ end
87
+ end
88
+
89
+ private def print_help(opts, out=$stdout)
90
+ out.puts opts.help
91
+ out.puts
92
+ out.puts "Subcommands"
93
+ out.puts "==========="
94
+ SUB_COMMANDS.each do |name, description|
95
+ out.puts "#{name}"
96
+ out.puts " #{description}"
97
+ end
98
+ end
99
+
100
+ def run
101
+ case @sub_cmd
102
+ when :register
103
+ register_kernel(@sub_argv)
104
+ when :unregister
105
+ unregister_kernel(@sub_argv)
106
+ when :console
107
+ exec_jupyter(@sub_cmd.to_s, @sub_argv)
108
+ when :kernel
109
+ @sub_app = KernelApplication.new(@sub_argv)
110
+ @sub_app.run
111
+ else
112
+ raise "[IRuby][BUG] Unknown subcommand: #{@sub_cmd}; this must be treated in parse_command_line."
113
+ end
114
+ end
115
+
116
+ ruby_version_info = RUBY_VERSION.split('.')
117
+ DEFAULT_KERNEL_NAME = "ruby#{ruby_version_info[0]}".freeze
118
+ DEFAULT_DISPLAY_NAME = "Ruby #{ruby_version_info[0]} (iruby kernel)"
119
+
120
+ RegisterParams = Struct.new(
121
+ :name,
122
+ :display_name,
123
+ :profile,
124
+ :env,
125
+ :user,
126
+ :prefix,
127
+ :sys_prefix,
128
+ :force,
129
+ :ipython_dir
130
+ ) do
131
+ def initialize(*args)
132
+ super
133
+ self.name ||= DEFAULT_KERNEL_NAME
134
+ self.force = false
135
+ self.user = true
136
+ end
137
+ end
138
+
139
+ def register_kernel(argv)
140
+ params = parse_register_command_line(argv)
141
+
142
+ if params.name != DEFAULT_KERNEL_NAME
143
+ # `--name` is specified and `--display-name` is not
144
+ # default `params.display_name` to `params.name`
145
+ params.display_name ||= params.name
146
+ end
147
+
148
+ check_and_warn_kernel_in_default_ipython_directory(params)
149
+
150
+ if installed_kernel_exist?(params.name, params.ipython_dir)
151
+ unless params.force
152
+ $stderr.puts "IRuby kernel named `#{params.name}` already exists!"
153
+ $stderr.puts "Use --force to force register the new kernel."
154
+ exit 1
155
+ end
156
+ end
157
+
158
+ Dir.mktmpdir("iruby_kernel") do |tmpdir|
159
+ path = File.join(tmpdir, DEFAULT_KERNEL_NAME)
160
+ FileUtils.mkdir_p(path)
161
+
162
+ # Stage assets
163
+ assets_dir = File.expand_path("../assets", __FILE__)
164
+ FileUtils.cp_r(Dir.glob(File.join(assets_dir, "*")), path)
165
+
166
+ kernel_dict = {
167
+ "argv" => make_iruby_cmd(),
168
+ "display_name" => params.display_name || DEFAULT_DISPLAY_NAME,
169
+ "language" => "ruby",
170
+ "metadata" => {"debugger": false}
171
+ }
172
+
173
+ # TODO: Support params.profile
174
+ # TODO: Support params.env
175
+
176
+ kernel_content = JSON.pretty_generate(kernel_dict)
177
+ File.write(File.join(path, "kernel.json"), kernel_content)
178
+
179
+ args = ["--name=#{params.name}"]
180
+ args << "--user" if params.user
181
+ args << path
182
+
183
+ # TODO: Support params.prefix
184
+ # TODO: Support params.sys_prefix
185
+
186
+ system("jupyter", "kernelspec", "install", *args)
187
+ end
188
+ end
189
+
190
+ # Warn the existence of the IRuby kernel in the default IPython's kernels directory
191
+ private def check_and_warn_kernel_in_default_ipython_directory(params)
192
+ default_ipython_kernels_dir = File.expand_path("~/.ipython/kernels")
193
+ [params.name, "ruby"].each do |name|
194
+ if File.exist?(File.join(default_ipython_kernels_dir, name, "kernel.json"))
195
+ warn "IRuby kernel `#{name}` already exists in the deprecated IPython's data directory."
196
+ end
197
+ end
198
+ end
199
+
200
+ alias __system__ system
201
+
202
+ private def system(*cmdline, dry_run: false)
203
+ $stderr.puts "EXECUTE: #{cmdline.map {|x| x.include?(' ') ? x.inspect : x}.join(' ')}"
204
+ __system__(*cmdline) unless dry_run
205
+ end
206
+
207
+ private def installed_kernel_exist?(name, ipython_dir)
208
+ kernels_dir = resolve_kernelspec_dir(ipython_dir)
209
+ kernel_dir = File.join(kernels_dir, name)
210
+ File.file?(File.join(kernel_dir, "kernel.json"))
211
+ end
212
+
213
+ private def resolve_kernelspec_dir(ipython_dir)
214
+ if ENV.has_key?("JUPYTER_DATA_DIR")
215
+ if ENV.has_key?("IPYTHONDIR")
216
+ warn "both JUPYTER_DATA_DIR and IPYTHONDIR are supplied; IPYTHONDIR is ignored."
217
+ end
218
+ jupyter_data_dir = ENV["JUPYTER_DATA_DIR"]
219
+ return File.join(jupyter_data_dir, "kernels")
220
+ end
221
+
222
+ if ipython_dir.nil? && ENV.key?("IPYTHONDIR")
223
+ warn 'IPYTHONDIR is deprecated. Use JUPYTER_DATA_DIR instead.'
224
+ ipython_dir = ENV["IPYTHONDIR"]
225
+ end
226
+
227
+ if ipython_dir
228
+ File.join(ipython_dir, 'kerenels')
229
+ else
230
+ Jupyter.kernelspec_dir
231
+ end
232
+ end
233
+
234
+ private def make_iruby_cmd(executable: nil, extra_arguments: nil)
235
+ executable ||= default_executable
236
+ extra_arguments ||= []
237
+ [*Array(executable), "kernel", "-f", "{connection_file}", *extra_arguments]
238
+ end
239
+
240
+ private def default_executable
241
+ [RbConfig.ruby, @iruby_executable]
242
+ end
243
+
244
+ private def parse_register_command_line(argv)
245
+ opts = OptionParser.new
246
+ opts.banner = "Usage: #{$PROGRAM_NAME} register [options]"
247
+
248
+ params = RegisterParams.new
249
+
250
+ opts.on(
251
+ "--force",
252
+ "Force register a new kernel spec. The existing kernel spec will be removed."
253
+ ) { params.force = true }
254
+
255
+ opts.on(
256
+ "--user",
257
+ "Register for the current user instead of system-wide."
258
+ ) { params.user = true }
259
+
260
+ opts.on(
261
+ "--name=VALUE", String,
262
+ "Specify a name for the kernelspec. This is needed to have multiple IRuby kernels at the same time."
263
+ ) {|v| params.name = v }
264
+
265
+ opts.on(
266
+ "--display-name=VALUE", String,
267
+ "Specify the display name for the kernelspec. This is helpful when you have multiple IRuby kernels."
268
+ ) {|v| kernel_display_name = v }
269
+
270
+ # TODO: --profile
271
+ # TODO: --prefix
272
+ # TODO: --sys-prefix
273
+ # TODO: --env
274
+
275
+ define_ipython_dir_option(opts, params)
276
+
277
+ opts.order!(argv)
278
+
279
+ params
280
+ end
281
+
282
+ UnregisterParams = Struct.new(
283
+ :names,
284
+ #:profile,
285
+ #:user,
286
+ #:prefix,
287
+ #:sys_prefix,
288
+ :ipython_dir,
289
+ :force,
290
+ :yes
291
+ ) do
292
+ def initialize(*args, **kw)
293
+ super
294
+ self.names = []
295
+ # self.user = true
296
+ self.force = false
297
+ self.yes = false
298
+ end
299
+ end
300
+
301
+ def unregister_kernel(argv)
302
+ params = parse_unregister_command_line(argv)
303
+ opts = []
304
+ opts << "-y" if params.yes
305
+ opts << "-f" if params.force
306
+ system("jupyter", "kernelspec", "uninstall", *opts, *params.names)
307
+ end
308
+
309
+ private def parse_unregister_command_line(argv)
310
+ opts = OptionParser.new
311
+ opts.banner = "Usage: #{$PROGRAM_NAME} unregister [options] NAME [NAME ...]"
312
+
313
+ params = UnregisterParams.new
314
+
315
+ opts.on(
316
+ "-f", "--force",
317
+ "Force removal, don't prompt for confirmation."
318
+ ) { params.force = true}
319
+
320
+ opts.on(
321
+ "-y", "--yes",
322
+ "Answer yes to any prompts."
323
+ ) { params.yes = true }
324
+
325
+ # TODO: --user
326
+ # TODO: --profile
327
+ # TODO: --prefix
328
+ # TODO: --sys-prefix
329
+
330
+ define_ipython_dir_option(opts, params)
331
+
332
+ opts.order!(argv)
333
+
334
+ params.names = argv.dup
335
+
336
+ params
337
+ end
338
+
339
+ def exec_jupyter(sub_cmd, argv)
340
+ opts = OptionParser.new
341
+ opts.banner = "Usage: #{$PROGRAM_NAME} unregister [options]"
342
+
343
+ kernel_name = resolve_installed_kernel_name(DEFAULT_KERNEL_NAME)
344
+ opts.on(
345
+ "--kernel=NAME", String,
346
+ "The name of the default kernel to start."
347
+ ) {|v| kernel_name = v }
348
+
349
+ opts.order!(argv)
350
+
351
+ opts = ["--kernel=#{kernel_name}"]
352
+ exec("jupyter", "console", *opts)
353
+ end
354
+
355
+ private def resolve_installed_kernel_name(default_name)
356
+ kernels = IO.popen(["jupyter", "kernelspec", "list", "--json"], "r", err: File::NULL) do |jupyter_out|
357
+ JSON.load(jupyter_out.read)
358
+ end
359
+ unless kernels["kernelspecs"].key?(default_name)
360
+ return "ruby" if kernels["kernelspecs"].key?("ruby")
361
+ end
362
+ default_name
363
+ end
364
+
365
+ private def define_ipython_dir_option(opts, params)
366
+ opts.on(
367
+ "--ipython-dir=DIR", String,
368
+ "Specify the IPython's data directory (DEPRECATED)."
369
+ ) do |v|
370
+ if ENV.key?("JUPYTER_DATA_DIR")
371
+ warn 'Both JUPYTER_DATA_DIR and --ipython-dir are supplied; --ipython-dir is ignored.'
372
+ else
373
+ warn '--ipython-dir is deprecated. Use JUPYTER_DATA_DIR environment variable instead.'
374
+ end
375
+
376
+ params.ipython_dir = v
377
+ end
378
+ end
379
+ end
380
+ end
data/lib/iruby/backend.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  module IRuby
2
2
  In, Out = [nil], [nil]
3
3
 
4
+ class << self
5
+ attr_accessor :silent_assignment
6
+ end
7
+ self.silent_assignment = false
8
+
4
9
  module History
5
10
  def eval(code, store_history)
6
11
  b = eval_binding
@@ -52,8 +57,8 @@ module IRuby
52
57
  end
53
58
 
54
59
  def eval(code, store_history)
55
- @irb.context.evaluate(code, 0)
56
- @irb.context.last_value
60
+ @irb.context.evaluate(@irb.build_statement(code), 0)
61
+ @irb.context.last_value unless IRuby.silent_assignment && assignment_expression?(code)
57
62
  end
58
63
 
59
64
  def complete(code)
@@ -69,6 +74,10 @@ module IRuby
69
74
  wrapper_module.include(*args)
70
75
  end
71
76
  end
77
+
78
+ def assignment_expression?(code)
79
+ @irb.respond_to?(:assignment_expression?) && @irb.assignment_expression?(code)
80
+ end
72
81
  end
73
82
 
74
83
  class PryBackend
@@ -0,0 +1,12 @@
1
+ module IRuby
2
+ class Error < StandardError
3
+ end
4
+
5
+ class InvalidSubcommandError < Error
6
+ def initialize(name, argv)
7
+ @name = name
8
+ @argv = argv
9
+ super("Invalid subcommand name: #{@name}")
10
+ end
11
+ end
12
+ end
data/lib/iruby/jupyter.rb CHANGED
@@ -2,8 +2,11 @@ module IRuby
2
2
  module Jupyter
3
3
  class << self
4
4
  # User's default kernelspec directory is described here:
5
- # https://jupyter.readthedocs.io/en/latest/projects/jupyter-directories.html
5
+ # https://docs.jupyter.org/en/latest/use/jupyter-directories.html
6
6
  def default_data_dir
7
+ data_dir = ENV["JUPYTER_DATA_DIR"]
8
+ return data_dir if data_dir
9
+
7
10
  case
8
11
  when windows?
9
12
  appdata = windows_user_appdata
data/lib/iruby/kernel.rb CHANGED
@@ -176,8 +176,9 @@ module IRuby
176
176
  # @private
177
177
  def execute_request(msg)
178
178
  code = msg[:content]['code']
179
- store_history = msg[:content]['store_history']
180
179
  silent = msg[:content]['silent']
180
+ # https://jupyter-client.readthedocs.io/en/stable/messaging.html#execute
181
+ store_history = silent ? false : msg[:content].fetch('store_history', true)
181
182
 
182
183
  @execution_count += 1 if store_history
183
184
 
@@ -218,7 +219,8 @@ module IRuby
218
219
  end
219
220
 
220
221
  events.trigger(:post_execute)
221
- events.trigger(:post_run_cell, result) unless silent
222
+ # **{} is for Ruby2.7. Gnuplot#to_hash returns an Array.
223
+ events.trigger(:post_run_cell, result, **{}) unless silent
222
224
 
223
225
  @session.send(:reply, :execute_reply, content)
224
226
  end
@@ -0,0 +1,108 @@
1
+ module IRuby
2
+ class KernelApplication
3
+ def initialize(argv)
4
+ parse_command_line(argv)
5
+ end
6
+
7
+ def run
8
+ if @test_mode
9
+ dump_connection_file
10
+ return
11
+ end
12
+
13
+ run_kernel
14
+ end
15
+
16
+ DEFAULT_CONNECTION_FILE = "kernel-#{Process.pid}.json".freeze
17
+
18
+ private def parse_command_line(argv)
19
+ opts = OptionParser.new
20
+ opts.banner = "Usage: #{$PROGRAM_NAME} [options] [subcommand] [options]"
21
+
22
+ @connection_file = nil
23
+ opts.on(
24
+ "-f CONNECTION_FILE", String,
25
+ "JSON file in which to store connection info (default: kernel-<pid>.json)"
26
+ ) {|v| @connection_file = v }
27
+
28
+ @test_mode = false
29
+ opts.on(
30
+ "--test",
31
+ "Run as test mode; dump the connection file and exit."
32
+ ) { @test_mode = true }
33
+
34
+ @log_file = nil
35
+ opts.on(
36
+ "--log=FILE", String,
37
+ "Specify the log file."
38
+ ) {|v| @log_file = v }
39
+
40
+ @log_level = Logger::INFO
41
+ opts.on(
42
+ "--debug",
43
+ "Set log-level debug"
44
+ ) { @log_level = Logger::DEBUG }
45
+
46
+ opts.order!(argv)
47
+
48
+ if @connection_file.nil?
49
+ # Without -f option, the connection file is at the beginning of the rest arguments
50
+ if argv.length <= 3
51
+ @connection_file, @boot_file, @work_dir = argv
52
+ else
53
+ raise ArgumentError, "Too many commandline arguments"
54
+ end
55
+ else
56
+ if argv.length <= 2
57
+ @boot_file, @work_dir = argv
58
+ else
59
+ raise ArgumentError, "Too many commandline arguments"
60
+ end
61
+ end
62
+
63
+ @connection_file ||= DEFAULT_CONNECTION_FILE
64
+ end
65
+
66
+ private def dump_connection_file
67
+ puts File.read(@connection_file)
68
+ end
69
+
70
+ private def run_kernel
71
+ IRuby.logger = MultiLogger.new(*Logger.new(STDOUT))
72
+ STDOUT.sync = true # FIXME: This can make the integration test.
73
+
74
+ IRuby.logger.loggers << Logger.new(@log_file) unless @log_file.nil?
75
+ IRuby.logger.level = @log_level
76
+
77
+ if @work_dir
78
+ IRuby.logger.debug("iruby kernel") { "Change the working directory: #{@work_dir}" }
79
+ Dir.chdir(@work_dir)
80
+ end
81
+
82
+ if @boot_file
83
+ IRuby.logger.debug("iruby kernel") { "Load the boot file: #{@boot_file}" }
84
+ require @boot_file
85
+ end
86
+
87
+ check_bundler {|e| IRuby.logger.warn "Could not load bundler: #{e.message}" }
88
+
89
+ require "iruby"
90
+ Kernel.new(@connection_file).run
91
+ rescue Exception => e
92
+ IRuby.logger.fatal "Kernel died: #{e.message}\n#{e.backtrace.join("\n")}"
93
+ exit 1
94
+ end
95
+
96
+ private def check_bundler
97
+ require "bundler"
98
+ unless Bundler.definition.specs.any? {|s| s.name == "iruby" }
99
+ raise %{IRuby is missing from Gemfile. This might not work. Add `gem "iruby"` in your Gemfile to fix it.}
100
+ end
101
+ Bundler.setup
102
+ rescue LoadError
103
+ # do nothing
104
+ rescue Exception => e
105
+ yield e
106
+ end
107
+ end
108
+ end
data/lib/iruby/logger.rb CHANGED
@@ -6,10 +6,20 @@ module IRuby
6
6
  end
7
7
 
8
8
  class MultiLogger < BasicObject
9
+ def initialize(*loggers, level: ::Logger::DEBUG)
10
+ @loggers = loggers
11
+ @level = level
12
+ end
13
+
9
14
  attr_reader :loggers
10
15
 
11
- def initialize(*loggers)
12
- @loggers = loggers
16
+ attr_reader :level
17
+
18
+ def level=(new_level)
19
+ @loggers.each do |l|
20
+ l.level = new_level
21
+ end
22
+ @level = new_level
13
23
  end
14
24
 
15
25
  def method_missing(name, *args, &b)
data/lib/iruby/session.rb CHANGED
@@ -2,6 +2,7 @@ require 'iruby/session_adapter'
2
2
  require 'iruby/session/mixin'
3
3
 
4
4
  require 'securerandom'
5
+ require 'time'
5
6
 
6
7
  module IRuby
7
8
  class Session
@@ -79,6 +80,7 @@ module IRuby
79
80
  header = {
80
81
  msg_type: message_type,
81
82
  msg_id: SecureRandom.uuid,
83
+ date: Time.now.utc.iso8601,
82
84
  username: 'kernel',
83
85
  session: @session_id,
84
86
  version: '5.0'
data/lib/iruby/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module IRuby
2
- VERSION = '0.7.4'
2
+ VERSION = '0.8.0'
3
3
  end
data/test/helper.rb CHANGED
@@ -2,18 +2,36 @@ require "iruby"
2
2
  require "json"
3
3
  require 'multi_json'
4
4
  require "pathname"
5
+ require "rbconfig"
5
6
  require "test/unit"
6
7
  require "test/unit/rr"
7
8
  require "tmpdir"
8
9
 
9
-
10
10
  IRuby.logger = IRuby::MultiLogger.new(*Logger.new(STDERR, level: Logger::Severity::INFO))
11
11
 
12
12
  module IRubyTest
13
13
  class TestBase < Test::Unit::TestCase
14
+ TEST_DIR = File.expand_path("..", __FILE__).freeze
15
+ EXE_DIR = File.expand_path("../exe", TEST_DIR).freeze
16
+ LIB_DIR = File.expand_path("../lib", TEST_DIR).freeze
17
+
18
+ RUBY = RbConfig.ruby.freeze
19
+ IRUBY_PATH = File.join(EXE_DIR, "iruby").freeze
20
+
21
+ def iruby_command(*args)
22
+ [RUBY, "-I#{LIB_DIR}", IRUBY_PATH, *args]
23
+ end
24
+
14
25
  def self.startup
15
- @__config_dir = Dir.mktmpdir("iruby-test")
26
+ @__work_dir = Dir.mktmpdir("iruby-test-data")
27
+
28
+ @__jupyter_data_dir = File.join(@__work_dir, "jupyter")
29
+ @__save_jupyter_data_dir = ENV["JUPYTER_DATA_DIR"]
30
+ ENV["JUPYTER_DATA_DIR"] = @__jupyter_data_dir
31
+
32
+ @__config_dir = File.join(@__work_dir, "config")
16
33
  @__config_path = Pathname.new(@__config_dir) + "config.json"
34
+ @__config_path.dirname.mkpath
17
35
  File.write(@__config_path, {
18
36
  control_port: 50160,
19
37
  shell_port: 57503,
@@ -30,7 +48,8 @@ module IRubyTest
30
48
  end
31
49
 
32
50
  def self.shutdown
33
- FileUtils.remove_entry_secure(@__config_dir)
51
+ FileUtils.remove_entry_secure(@__work_dir)
52
+ ENV["JUPYTER_DATA_DIR"] = @__save_jupyter_data_dir
34
53
  end
35
54
 
36
55
  def self.test_config_filename
@@ -1,11 +1,17 @@
1
+ require 'bundler'
1
2
  require 'pty'
2
3
  require 'expect'
3
4
 
4
5
  class IRubyTest::IntegrationTest < IRubyTest::TestBase
5
6
  def setup
7
+ system(*iruby_command("register", "--name=iruby-test"), out: File::NULL, err: File::NULL)
8
+ kernel_json = File.join(ENV["JUPYTER_DATA_DIR"], "kernels", "iruby-test", "kernel.json")
9
+ assert_path_exist kernel_json
10
+
6
11
  $expect_verbose = false # make true if you want to dump the output of iruby console
7
12
 
8
- @in, @out, pid = PTY.spawn('bin/iruby --simple-prompt')
13
+ command = iruby_command("console", "--kernel=iruby-test").map {|x| %Q["#{x}"] }
14
+ @in, @out, pid = PTY.spawn(command.join(" "))
9
15
  @waiter = Thread.start { Process.waitpid(pid) }
10
16
  expect 'In [', 30
11
17
  expect '1'