iruby 0.2.9 → 0.6.1
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.
- checksums.yaml +5 -5
- data/.github/workflows/ubuntu.yml +62 -0
- data/CHANGES +64 -0
- data/Gemfile +3 -1
- data/LICENSE +1 -1
- data/README.md +120 -92
- data/Rakefile +36 -10
- data/ci/Dockerfile.base.erb +41 -0
- data/ci/Dockerfile.main.erb +7 -0
- data/ci/requirements.txt +1 -0
- data/docker/setup.sh +15 -0
- data/docker/test.sh +7 -0
- data/iruby.gemspec +13 -18
- data/lib/iruby.rb +13 -6
- data/lib/iruby/backend.rb +38 -9
- data/lib/iruby/command.rb +68 -12
- data/lib/iruby/display.rb +81 -41
- data/lib/iruby/event_manager.rb +40 -0
- data/lib/iruby/formatter.rb +3 -3
- data/lib/iruby/input.rb +6 -6
- data/lib/iruby/input/README.ipynb +55 -3
- data/lib/iruby/input/README.md +299 -0
- data/lib/iruby/input/autoload.rb +3 -2
- data/lib/iruby/input/builder.rb +4 -4
- data/lib/iruby/input/button.rb +2 -2
- data/lib/iruby/input/cancel.rb +1 -1
- data/lib/iruby/input/checkbox.rb +22 -4
- data/lib/iruby/input/date.rb +17 -6
- data/lib/iruby/input/field.rb +5 -4
- data/lib/iruby/input/file.rb +3 -3
- data/lib/iruby/input/form.rb +6 -6
- data/lib/iruby/input/label.rb +9 -3
- data/lib/iruby/input/multiple.rb +76 -0
- data/lib/iruby/input/popup.rb +5 -2
- data/lib/iruby/input/radio.rb +18 -6
- data/lib/iruby/input/select.rb +26 -12
- data/lib/iruby/input/textarea.rb +2 -1
- data/lib/iruby/input/widget.rb +2 -2
- data/lib/iruby/jupyter.rb +77 -0
- data/lib/iruby/kernel.rb +171 -31
- data/lib/iruby/ostream.rb +29 -8
- data/lib/iruby/session.rb +116 -0
- data/lib/iruby/session/{rbczmq.rb → cztop.rb} +21 -19
- data/lib/iruby/session/ffi_rzmq.rb +1 -1
- data/lib/iruby/session_adapter.rb +72 -0
- data/lib/iruby/session_adapter/cztop_adapter.rb +45 -0
- data/lib/iruby/session_adapter/ffirzmq_adapter.rb +55 -0
- data/lib/iruby/session_adapter/pyzmq_adapter.rb +77 -0
- data/lib/iruby/session_adapter/test_adapter.rb +49 -0
- data/lib/iruby/utils.rb +13 -2
- data/lib/iruby/version.rb +1 -1
- data/run-test.sh +12 -0
- data/tasks/ci.rake +65 -0
- data/test/helper.rb +133 -0
- data/test/integration_test.rb +22 -11
- data/test/iruby/backend_test.rb +37 -0
- data/test/iruby/command_test.rb +207 -0
- data/test/iruby/event_manager_test.rb +92 -0
- data/test/iruby/jupyter_test.rb +27 -0
- data/test/iruby/kernel_test.rb +153 -0
- data/test/iruby/mime_test.rb +43 -0
- data/test/iruby/multi_logger_test.rb +1 -2
- data/test/iruby/session_adapter/cztop_adapter_test.rb +20 -0
- data/test/iruby/session_adapter/ffirzmq_adapter_test.rb +20 -0
- data/test/iruby/session_adapter/session_adapter_test_base.rb +27 -0
- data/test/iruby/session_adapter_test.rb +91 -0
- data/test/iruby/session_test.rb +48 -0
- data/test/run-test.rb +19 -0
- metadata +107 -50
- data/.travis.yml +0 -16
- data/CONTRIBUTORS +0 -19
- data/test/test_helper.rb +0 -5
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
FROM rubylang/ruby:<%= ruby_version %>-bionic
|
|
2
|
+
|
|
3
|
+
ADD ci/requirements.txt /tmp
|
|
4
|
+
|
|
5
|
+
RUN apt-get update \
|
|
6
|
+
&& apt-get install -y --no-install-recommends \
|
|
7
|
+
libczmq-dev \
|
|
8
|
+
python3 \
|
|
9
|
+
python3-pip \
|
|
10
|
+
python3-setuptools \
|
|
11
|
+
libpython3.6 \
|
|
12
|
+
&& pip3 install wheel \
|
|
13
|
+
&& pip3 install -r /tmp/requirements.txt \
|
|
14
|
+
&& rm -f /tmp/requirements.txt
|
|
15
|
+
|
|
16
|
+
# ZeroMQ version 4.1.6 and CZMQ version 3.0.2 for rbczmq
|
|
17
|
+
RUN apt-get update \
|
|
18
|
+
&& apt-get install -y --no-install-recommends \
|
|
19
|
+
build-essential \
|
|
20
|
+
file \
|
|
21
|
+
wget \
|
|
22
|
+
&& cd /tmp \
|
|
23
|
+
&& wget https://github.com/zeromq/zeromq4-1/releases/download/v4.1.6/zeromq-4.1.6.tar.gz \
|
|
24
|
+
&& wget https://archive.org/download/zeromq_czmq_3.0.2/czmq-3.0.2.tar.gz \
|
|
25
|
+
&& tar xf zeromq-4.1.6.tar.gz \
|
|
26
|
+
&& tar xf czmq-3.0.2.tar.gz \
|
|
27
|
+
&& \
|
|
28
|
+
( \
|
|
29
|
+
cd zeromq-4.1.6 \
|
|
30
|
+
&& ./configure \
|
|
31
|
+
&& make install \
|
|
32
|
+
) \
|
|
33
|
+
&& \
|
|
34
|
+
( \
|
|
35
|
+
cd czmq-3.0.2 \
|
|
36
|
+
&& wget -O 1.patch https://github.com/zeromq/czmq/commit/2594d406d8ec6f54e54d7570d7febba10a6906b2.diff \
|
|
37
|
+
&& wget -O 2.patch https://github.com/zeromq/czmq/commit/b651cb479235751b22b8f9a822a2fc6bc1be01ab.diff \
|
|
38
|
+
&& cat *.patch | patch -p1 \
|
|
39
|
+
&& ./configure \
|
|
40
|
+
&& make install \
|
|
41
|
+
)
|
data/ci/requirements.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
jupyter-console>=6.0.0
|
data/docker/setup.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -ex
|
|
4
|
+
|
|
5
|
+
apt-get update
|
|
6
|
+
apt-get install -y --no-install-recommends \
|
|
7
|
+
libczmq-dev \
|
|
8
|
+
python3 \
|
|
9
|
+
python3-pip \
|
|
10
|
+
python3-setuptools \
|
|
11
|
+
python3-wheel
|
|
12
|
+
|
|
13
|
+
cd /tmp/iruby
|
|
14
|
+
bundle install --with test --without plot
|
|
15
|
+
pip3 install jupyter
|
data/docker/test.sh
ADDED
data/iruby.gemspec
CHANGED
|
@@ -1,34 +1,29 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
1
|
require_relative 'lib/iruby/version'
|
|
3
|
-
require 'date'
|
|
4
2
|
|
|
5
3
|
Gem::Specification.new do |s|
|
|
6
4
|
s.name = 'iruby'
|
|
7
|
-
s.date = Date.today.to_s
|
|
8
5
|
s.version = IRuby::VERSION
|
|
9
6
|
s.authors = ['Daniel Mendler', 'The SciRuby developers']
|
|
10
7
|
s.email = ['mail@daniel-mendler.de']
|
|
11
|
-
s.summary = 'Ruby Kernel for Jupyter
|
|
12
|
-
s.description = 'A Ruby kernel for Jupyter
|
|
8
|
+
s.summary = 'Ruby Kernel for Jupyter'
|
|
9
|
+
s.description = 'A Ruby kernel for Jupyter environment. Try it at try.jupyter.org.'
|
|
13
10
|
s.homepage = 'https://github.com/SciRuby/iruby'
|
|
14
11
|
s.license = 'MIT'
|
|
15
12
|
|
|
16
|
-
s.files = `git ls-files`.split(
|
|
13
|
+
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
17
14
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
15
|
s.test_files = s.files.grep(%r{^test/})
|
|
19
|
-
s.require_paths = %w
|
|
16
|
+
s.require_paths = %w[lib]
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
File.read('Gemfile').scan(/gem\s+'(.*?)'/) { m << " * #{$1}\n" }
|
|
23
|
-
s.post_install_message = m << "\n"
|
|
18
|
+
s.required_ruby_version = '>= 2.3.0'
|
|
24
19
|
|
|
25
|
-
s.
|
|
20
|
+
s.add_dependency 'data_uri', '~> 0.1'
|
|
21
|
+
s.add_dependency 'ffi-rzmq'
|
|
22
|
+
s.add_dependency 'mime-types', '>= 3.3.1'
|
|
23
|
+
s.add_dependency 'multi_json', '~> 1.11'
|
|
26
24
|
|
|
27
|
-
s.add_development_dependency '
|
|
28
|
-
s.add_development_dependency '
|
|
29
|
-
|
|
30
|
-
s.
|
|
31
|
-
s.add_runtime_dependency 'multi_json', '~> 1.11'
|
|
32
|
-
s.add_runtime_dependency 'mimemagic', '~> 0.3'
|
|
33
|
-
s.add_runtime_dependency 'data_uri', '~> 0.1'
|
|
25
|
+
s.add_development_dependency 'pycall', '>= 1.2.1'
|
|
26
|
+
s.add_development_dependency 'rake'
|
|
27
|
+
s.add_development_dependency 'test-unit'
|
|
28
|
+
s.add_development_dependency 'test-unit-rr'
|
|
34
29
|
end
|
data/lib/iruby.rb
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'mime/types'
|
|
2
2
|
require 'multi_json'
|
|
3
3
|
require 'securerandom'
|
|
4
4
|
require 'openssl'
|
|
5
5
|
require 'tempfile'
|
|
6
6
|
require 'set'
|
|
7
|
+
|
|
7
8
|
require 'iruby/version'
|
|
9
|
+
require 'iruby/jupyter'
|
|
10
|
+
require 'iruby/event_manager'
|
|
8
11
|
require 'iruby/kernel'
|
|
9
12
|
require 'iruby/backend'
|
|
10
13
|
require 'iruby/ostream'
|
|
@@ -13,14 +16,18 @@ require 'iruby/formatter'
|
|
|
13
16
|
require 'iruby/utils'
|
|
14
17
|
require 'iruby/display'
|
|
15
18
|
require 'iruby/comm'
|
|
16
|
-
require 'iruby/session/mixin'
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
require 'iruby/session/
|
|
20
|
-
rescue LoadError
|
|
20
|
+
if ENV.fetch('IRUBY_OLD_SESSION', false)
|
|
21
|
+
require 'iruby/session/mixin'
|
|
21
22
|
begin
|
|
22
23
|
require 'iruby/session/ffi_rzmq'
|
|
23
24
|
rescue LoadError
|
|
24
|
-
|
|
25
|
+
begin
|
|
26
|
+
require 'iruby/session/cztop'
|
|
27
|
+
rescue LoadError
|
|
28
|
+
STDERR.puts "Please install ffi-rzmq or cztop before running iruby. See README."
|
|
29
|
+
end
|
|
25
30
|
end
|
|
31
|
+
else
|
|
32
|
+
require 'iruby/session'
|
|
26
33
|
end
|
data/lib/iruby/backend.rb
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
module IRuby
|
|
2
2
|
In, Out = [nil], [nil]
|
|
3
|
-
::In, ::Out = In, Out
|
|
4
3
|
|
|
5
4
|
module History
|
|
6
5
|
def eval(code, store_history)
|
|
7
|
-
b =
|
|
6
|
+
b = eval_binding
|
|
8
7
|
|
|
9
8
|
b.local_variable_set(:_ih, In) unless b.local_variable_defined?(:_ih)
|
|
10
9
|
b.local_variable_set(:_oh, Out) unless b.local_variable_defined?(:_oh)
|
|
@@ -33,44 +32,74 @@ module IRuby
|
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
class PlainBackend
|
|
35
|
+
attr_reader :eval_path
|
|
36
36
|
prepend History
|
|
37
37
|
|
|
38
38
|
def initialize
|
|
39
|
-
require '
|
|
40
|
-
|
|
39
|
+
require 'irb'
|
|
40
|
+
require 'irb/completion'
|
|
41
|
+
IRB.setup(nil)
|
|
42
|
+
@main = TOPLEVEL_BINDING.eval("self").dup
|
|
43
|
+
@workspace = IRB::WorkSpace.new(@main)
|
|
44
|
+
@irb = IRB::Irb.new(@workspace)
|
|
45
|
+
@eval_path = @irb.context.irb_path
|
|
46
|
+
IRB.conf[:MAIN_CONTEXT] = @irb.context
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def eval_binding
|
|
50
|
+
@workspace.binding
|
|
41
51
|
end
|
|
42
52
|
|
|
43
53
|
def eval(code, store_history)
|
|
44
|
-
|
|
54
|
+
@irb.context.evaluate(code, 0)
|
|
55
|
+
@irb.context.last_value
|
|
45
56
|
end
|
|
46
57
|
|
|
47
58
|
def complete(code)
|
|
48
|
-
|
|
59
|
+
IRB::InputCompletor::CompletionProc.call(code)
|
|
49
60
|
end
|
|
50
61
|
end
|
|
51
62
|
|
|
52
63
|
class PryBackend
|
|
64
|
+
attr_reader :eval_path
|
|
53
65
|
prepend History
|
|
54
66
|
|
|
55
67
|
def initialize
|
|
56
68
|
require 'pry'
|
|
69
|
+
Pry.memory_size = 3
|
|
57
70
|
Pry.pager = false # Don't use the pager
|
|
58
71
|
Pry.print = proc {|output, value|} # No result printing
|
|
59
72
|
Pry.exception_handler = proc {|output, exception, _| }
|
|
73
|
+
@eval_path = Pry.eval_path
|
|
60
74
|
reset
|
|
61
75
|
end
|
|
62
76
|
|
|
77
|
+
def eval_binding
|
|
78
|
+
TOPLEVEL_BINDING
|
|
79
|
+
end
|
|
80
|
+
|
|
63
81
|
def eval(code, store_history)
|
|
82
|
+
Pry.current_line = 1
|
|
64
83
|
@pry.last_result = nil
|
|
65
84
|
unless @pry.eval(code)
|
|
66
85
|
reset
|
|
67
86
|
raise SystemExit
|
|
68
87
|
end
|
|
69
|
-
|
|
88
|
+
|
|
89
|
+
# Pry::Code.complete_expression? return false
|
|
90
|
+
if !@pry.eval_string.empty?
|
|
70
91
|
syntax_error = @pry.eval_string
|
|
71
92
|
@pry.reset_eval_string
|
|
72
|
-
@pry.evaluate_ruby
|
|
93
|
+
@pry.evaluate_ruby(syntax_error)
|
|
94
|
+
|
|
95
|
+
# Pry::Code.complete_expression? raise SyntaxError
|
|
96
|
+
# evaluate again for current line number
|
|
97
|
+
elsif @pry.last_result_is_exception? &&
|
|
98
|
+
@pry.last_exception.is_a?(SyntaxError) &&
|
|
99
|
+
@pry.last_exception.is_a?(Pry::UserError)
|
|
100
|
+
@pry.evaluate_ruby(code)
|
|
73
101
|
end
|
|
102
|
+
|
|
74
103
|
raise @pry.last_exception if @pry.last_result_is_exception?
|
|
75
104
|
@pry.push_initial_binding unless @pry.current_binding # ensure that we have a binding
|
|
76
105
|
@pry.last_result
|
|
@@ -81,7 +110,7 @@ module IRuby
|
|
|
81
110
|
end
|
|
82
111
|
|
|
83
112
|
def reset
|
|
84
|
-
@pry = Pry.new(output: $stdout, target:
|
|
113
|
+
@pry = Pry.new(output: $stdout, target: eval_binding)
|
|
85
114
|
end
|
|
86
115
|
end
|
|
87
116
|
end
|
data/lib/iruby/command.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'iruby/jupyter'
|
|
2
|
+
|
|
1
3
|
require 'fileutils'
|
|
2
4
|
require 'multi_json'
|
|
3
5
|
|
|
@@ -6,15 +8,18 @@ module IRuby
|
|
|
6
8
|
def initialize(args)
|
|
7
9
|
@args = args
|
|
8
10
|
|
|
9
|
-
ipython_dir =
|
|
10
|
-
@
|
|
11
|
-
|
|
12
|
-
end
|
|
13
|
-
@kernel_dir = File.join(File.expand_path(ipython_dir), 'kernels', 'ruby')
|
|
14
|
-
@kernel_file = File.join(@kernel_dir, 'kernel.json')
|
|
11
|
+
@ipython_dir = File.expand_path("~/.ipython")
|
|
12
|
+
@kernel_dir = resolve_kernelspec_dir.freeze
|
|
13
|
+
@kernel_file = File.join(@kernel_dir, 'kernel.json').freeze
|
|
15
14
|
@iruby_path = File.expand_path $0
|
|
16
15
|
end
|
|
17
16
|
|
|
17
|
+
attr_reader :ipython_dir, :kernel_dir, :kernel_file
|
|
18
|
+
|
|
19
|
+
def ipython_kernel_dir
|
|
20
|
+
File.join(File.expand_path(@ipython_dir), 'kernels', 'ruby')
|
|
21
|
+
end
|
|
22
|
+
|
|
18
23
|
def run
|
|
19
24
|
case @args.first
|
|
20
25
|
when 'version', '-v', '--version'
|
|
@@ -23,11 +28,12 @@ module IRuby
|
|
|
23
28
|
when 'help', '-h', '--help'
|
|
24
29
|
print_help
|
|
25
30
|
when 'register'
|
|
26
|
-
|
|
31
|
+
force_p = @args.include?('--force')
|
|
32
|
+
if registered_iruby_path && !force_p
|
|
27
33
|
STDERR.puts "#{@kernel_file} already exists!\nUse --force to force a register."
|
|
28
34
|
exit 1
|
|
29
35
|
end
|
|
30
|
-
register_kernel
|
|
36
|
+
register_kernel(force_p)
|
|
31
37
|
when 'unregister'
|
|
32
38
|
unregister_kernel
|
|
33
39
|
when 'kernel'
|
|
@@ -39,6 +45,38 @@ module IRuby
|
|
|
39
45
|
|
|
40
46
|
private
|
|
41
47
|
|
|
48
|
+
def resolve_kernelspec_dir
|
|
49
|
+
if ENV.has_key?('JUPYTER_DATA_DIR')
|
|
50
|
+
if ENV.has_key?('IPYTHONDIR')
|
|
51
|
+
warn 'both JUPYTER_DATA_DIR and IPYTHONDIR are supplied; IPYTHONDIR is ignored.'
|
|
52
|
+
end
|
|
53
|
+
if @args.find {|x| /\A--ipython-dir=/ =~ x }
|
|
54
|
+
warn 'both JUPYTER_DATA_DIR and --ipython-dir are supplied; --ipython-dir is ignored.'
|
|
55
|
+
end
|
|
56
|
+
jupyter_data_dir = ENV['JUPYTER_DATA_DIR']
|
|
57
|
+
return File.join(jupyter_data_dir, 'kernels', 'ruby')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if ENV.has_key?('IPYTHONDIR')
|
|
61
|
+
warn 'IPYTHONDIR is deprecated. Use JUPYTER_DATA_DIR instead.'
|
|
62
|
+
ipython_dir = ENV['IPYTHONDIR']
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
@args.each do |arg|
|
|
66
|
+
next unless /\A--ipython-dir=(.*)\Z/ =~ arg
|
|
67
|
+
ipython_dir = Regexp.last_match[1]
|
|
68
|
+
warn '--ipython-dir is deprecated. Use JUPYTER_DATA_DIR environment variable instead.'
|
|
69
|
+
break
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if ipython_dir
|
|
73
|
+
@ipython_dir = ipython_dir
|
|
74
|
+
ipython_kernel_dir
|
|
75
|
+
else
|
|
76
|
+
File.join(Jupyter.kernelspec_dir, 'ruby')
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
42
80
|
def print_help
|
|
43
81
|
puts %{
|
|
44
82
|
Usage:
|
|
@@ -56,6 +94,8 @@ Try `ipython help` for more information.
|
|
|
56
94
|
def run_kernel
|
|
57
95
|
require 'iruby/logger'
|
|
58
96
|
IRuby.logger = MultiLogger.new(*Logger.new(STDOUT))
|
|
97
|
+
STDOUT.sync = true # FIXME: This can make the integration test.
|
|
98
|
+
|
|
59
99
|
@args.reject! {|arg| arg =~ /\A--log=(.*)\Z/ && IRuby.logger.loggers << Logger.new($1) }
|
|
60
100
|
IRuby.logger.level = @args.delete('--debug') ? Logger::DEBUG : Logger::INFO
|
|
61
101
|
|
|
@@ -64,7 +104,7 @@ Try `ipython help` for more information.
|
|
|
64
104
|
Dir.chdir(working_dir) if working_dir
|
|
65
105
|
|
|
66
106
|
require boot_file if boot_file
|
|
67
|
-
check_bundler {|e| IRuby.logger.warn "Could not load bundler: #{e.message}
|
|
107
|
+
check_bundler {|e| IRuby.logger.warn "Could not load bundler: #{e.message}" }
|
|
68
108
|
|
|
69
109
|
require 'iruby'
|
|
70
110
|
Kernel.new(config_file).run
|
|
@@ -95,7 +135,7 @@ Try `ipython help` for more information.
|
|
|
95
135
|
end
|
|
96
136
|
|
|
97
137
|
def check_registered_kernel
|
|
98
|
-
if kernel = registered_iruby_path
|
|
138
|
+
if (kernel = registered_iruby_path)
|
|
99
139
|
STDERR.puts "#{@iruby_path} differs from registered path #{registered_iruby_path}.
|
|
100
140
|
This might not work. Run 'iruby register --force' to fix it." if @iruby_path != kernel
|
|
101
141
|
else
|
|
@@ -106,14 +146,19 @@ This might not work. Run 'iruby register --force' to fix it." if @iruby_path !=
|
|
|
106
146
|
def check_bundler
|
|
107
147
|
require 'bundler'
|
|
108
148
|
raise %q{iruby is missing from Gemfile. This might not work.
|
|
109
|
-
Add `gem 'iruby'` to your Gemfile to fix it.} unless Bundler.definition.
|
|
149
|
+
Add `gem 'iruby'` to your Gemfile to fix it.} unless Bundler.definition.specs.any? {|s| s.name == 'iruby' }
|
|
110
150
|
Bundler.setup
|
|
111
151
|
rescue LoadError
|
|
112
152
|
rescue Exception => e
|
|
113
153
|
yield(e)
|
|
114
154
|
end
|
|
115
155
|
|
|
116
|
-
def register_kernel
|
|
156
|
+
def register_kernel(force_p=false)
|
|
157
|
+
if force_p
|
|
158
|
+
unregister_kernel_in_ipython_dir
|
|
159
|
+
else
|
|
160
|
+
return unless check_existing_kernel_in_ipython_dir
|
|
161
|
+
end
|
|
117
162
|
FileUtils.mkpath(@kernel_dir)
|
|
118
163
|
unless RUBY_PLATFORM =~ /mswin(?!ce)|mingw|cygwin/
|
|
119
164
|
File.write(@kernel_file, MultiJson.dump(argv: [ @iruby_path, 'kernel', '{connection_file}' ],
|
|
@@ -127,6 +172,13 @@ Add `gem 'iruby'` to your Gemfile to fix it.} unless Bundler.definition.dependen
|
|
|
127
172
|
FileUtils.copy(Dir[File.join(__dir__, 'assets', '*')], @kernel_dir) rescue nil
|
|
128
173
|
end
|
|
129
174
|
|
|
175
|
+
def check_existing_kernel_in_ipython_dir
|
|
176
|
+
return true unless File.file?(File.join(ipython_kernel_dir, 'kernel.json'))
|
|
177
|
+
warn "IRuby kernel file already exists in the deprecated IPython's data directory."
|
|
178
|
+
warn "Using --force, you can replace the old kernel file with the new one in Jupyter's data directory."
|
|
179
|
+
false
|
|
180
|
+
end
|
|
181
|
+
|
|
130
182
|
def registered_iruby_path
|
|
131
183
|
File.exist?(@kernel_file) && MultiJson.load(File.read(@kernel_file))['argv'].first
|
|
132
184
|
end
|
|
@@ -134,5 +186,9 @@ Add `gem 'iruby'` to your Gemfile to fix it.} unless Bundler.definition.dependen
|
|
|
134
186
|
def unregister_kernel
|
|
135
187
|
FileUtils.rm_rf(@kernel_dir)
|
|
136
188
|
end
|
|
189
|
+
|
|
190
|
+
def unregister_kernel_in_ipython_dir
|
|
191
|
+
FileUtils.rm_rf(ipython_kernel_dir)
|
|
192
|
+
end
|
|
137
193
|
end
|
|
138
194
|
end
|
data/lib/iruby/display.rb
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
module IRuby
|
|
2
2
|
module Display
|
|
3
3
|
class << self
|
|
4
|
+
# @private
|
|
4
5
|
def convert(obj, options)
|
|
5
6
|
Representation.new(obj, options)
|
|
6
7
|
end
|
|
7
8
|
|
|
9
|
+
# @private
|
|
8
10
|
def display(obj, options = {})
|
|
9
11
|
obj = convert(obj, options)
|
|
10
12
|
options = obj.options
|
|
11
13
|
obj = obj.object
|
|
12
14
|
|
|
13
15
|
fuzzy_mime = options[:format] # Treated like a fuzzy mime type
|
|
14
|
-
|
|
16
|
+
unless !fuzzy_mime || String === fuzzy_mime
|
|
17
|
+
raise 'Invalid argument :format'
|
|
18
|
+
end
|
|
19
|
+
|
|
15
20
|
if exact_mime = options[:mime]
|
|
16
21
|
raise 'Invalid argument :mime' unless String === exact_mime
|
|
17
22
|
raise 'Invalid mime type' unless exact_mime.include?('/')
|
|
@@ -27,32 +32,50 @@ module IRuby
|
|
|
27
32
|
|
|
28
33
|
# As a last resort, interpret string representation of the object
|
|
29
34
|
# as the given mime type.
|
|
30
|
-
|
|
35
|
+
if exact_mime && data.none? { |m, _| exact_mime == m }
|
|
36
|
+
data[exact_mime] = protect(exact_mime, obj)
|
|
37
|
+
end
|
|
31
38
|
|
|
32
39
|
data
|
|
33
40
|
end
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
# @private
|
|
43
|
+
def clear_output(wait = false)
|
|
44
|
+
IRuby::Kernel.instance.session.send(:publish, :clear_output, wait: wait)
|
|
37
45
|
end
|
|
38
46
|
|
|
39
47
|
private
|
|
40
48
|
|
|
41
49
|
def protect(mime, data)
|
|
42
|
-
|
|
50
|
+
ascii?(mime) ? data.to_s : [data.to_s].pack('m0')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def ascii?(mime)
|
|
54
|
+
case mime
|
|
55
|
+
when "application/javascript"
|
|
56
|
+
# Special case for application/javascript.
|
|
57
|
+
# This needs because mime-types tells us application/javascript a non-text type.
|
|
58
|
+
true
|
|
59
|
+
else
|
|
60
|
+
MIME::Type.new(mime).ascii?
|
|
61
|
+
end
|
|
43
62
|
end
|
|
44
63
|
|
|
45
64
|
def render(data, obj, exact_mime, fuzzy_mime)
|
|
46
65
|
# Filter matching renderer by object type
|
|
47
|
-
renderer = Registry.renderer.select {|r| r.match?(obj) }
|
|
66
|
+
renderer = Registry.renderer.select { |r| r.match?(obj) }
|
|
48
67
|
|
|
49
68
|
matching_renderer = nil
|
|
50
69
|
|
|
51
70
|
# Find exactly matching display by exact_mime
|
|
52
|
-
|
|
71
|
+
if exact_mime
|
|
72
|
+
matching_renderer = renderer.find { |r| exact_mime == r.mime }
|
|
73
|
+
end
|
|
53
74
|
|
|
54
75
|
# Find fuzzy matching display by fuzzy_mime
|
|
55
|
-
|
|
76
|
+
if fuzzy_mime
|
|
77
|
+
matching_renderer ||= renderer.find { |r| r.mime&.include?(fuzzy_mime) }
|
|
78
|
+
end
|
|
56
79
|
|
|
57
80
|
renderer.unshift matching_renderer if matching_renderer
|
|
58
81
|
|
|
@@ -73,7 +96,8 @@ module IRuby
|
|
|
73
96
|
attr_reader :object, :options
|
|
74
97
|
|
|
75
98
|
def initialize(object, options)
|
|
76
|
-
@object
|
|
99
|
+
@object = object
|
|
100
|
+
@options = options
|
|
77
101
|
end
|
|
78
102
|
|
|
79
103
|
class << self
|
|
@@ -91,10 +115,13 @@ module IRuby
|
|
|
91
115
|
end
|
|
92
116
|
|
|
93
117
|
class Renderer
|
|
94
|
-
attr_reader :match, :mime, :
|
|
118
|
+
attr_reader :match, :mime, :priority
|
|
95
119
|
|
|
96
120
|
def initialize(match, mime, render, priority)
|
|
97
|
-
@match
|
|
121
|
+
@match = match
|
|
122
|
+
@mime = mime
|
|
123
|
+
@render = render
|
|
124
|
+
@priority = priority
|
|
98
125
|
end
|
|
99
126
|
|
|
100
127
|
def match?(obj)
|
|
@@ -114,7 +141,7 @@ module IRuby
|
|
|
114
141
|
@renderer ||= []
|
|
115
142
|
end
|
|
116
143
|
|
|
117
|
-
SUPPORTED_MIMES = %w
|
|
144
|
+
SUPPORTED_MIMES = %w[
|
|
118
145
|
text/plain
|
|
119
146
|
text/html
|
|
120
147
|
text/latex
|
|
@@ -122,7 +149,8 @@ module IRuby
|
|
|
122
149
|
application/javascript
|
|
123
150
|
image/png
|
|
124
151
|
image/jpeg
|
|
125
|
-
image/svg+xml
|
|
152
|
+
image/svg+xml
|
|
153
|
+
]
|
|
126
154
|
|
|
127
155
|
def match(&block)
|
|
128
156
|
@match = block
|
|
@@ -131,7 +159,7 @@ module IRuby
|
|
|
131
159
|
end
|
|
132
160
|
|
|
133
161
|
def respond_to(name)
|
|
134
|
-
match {|obj| obj.respond_to?(name) }
|
|
162
|
+
match { |obj| obj.respond_to?(name) }
|
|
135
163
|
end
|
|
136
164
|
|
|
137
165
|
def type(&block)
|
|
@@ -153,7 +181,7 @@ module IRuby
|
|
|
153
181
|
|
|
154
182
|
def format(mime = nil, &block)
|
|
155
183
|
renderer << Renderer.new(@match, mime, block, @priority)
|
|
156
|
-
renderer.sort_by! {|r| -r.priority }
|
|
184
|
+
renderer.sort_by! { |r| -r.priority }
|
|
157
185
|
|
|
158
186
|
# Decrease priority implicitly for all formats
|
|
159
187
|
# which are added later for a type.
|
|
@@ -169,7 +197,19 @@ module IRuby
|
|
|
169
197
|
LaTeX.vector(obj.to_a)
|
|
170
198
|
end
|
|
171
199
|
|
|
200
|
+
type { Numo::NArray }
|
|
201
|
+
format 'text/plain', &:inspect
|
|
202
|
+
format 'text/latex' do |obj|
|
|
203
|
+
obj.ndim == 2 ?
|
|
204
|
+
LaTeX.matrix(obj, obj.shape[0], obj.shape[1]) :
|
|
205
|
+
LaTeX.vector(obj.to_a)
|
|
206
|
+
end
|
|
207
|
+
format 'text/html' do |obj|
|
|
208
|
+
HTML.table(obj.to_a)
|
|
209
|
+
end
|
|
210
|
+
|
|
172
211
|
type { NArray }
|
|
212
|
+
format 'text/plain', &:inspect
|
|
173
213
|
format 'text/latex' do |obj|
|
|
174
214
|
obj.dim == 2 ?
|
|
175
215
|
LaTeX.matrix(obj.transpose(1, 0), obj.shape[1], obj.shape[0]) :
|
|
@@ -231,37 +271,41 @@ module IRuby
|
|
|
231
271
|
|
|
232
272
|
match do |obj|
|
|
233
273
|
defined?(Magick::Image) && Magick::Image === obj ||
|
|
234
|
-
|
|
274
|
+
defined?(MiniMagick::Image) && MiniMagick::Image === obj
|
|
235
275
|
end
|
|
236
276
|
format 'image' do |obj|
|
|
237
277
|
format = obj.format || 'PNG'
|
|
238
|
-
[format == 'PNG' ? 'image/png' : 'image/jpeg', obj.to_blob {|i| i.format = format }]
|
|
278
|
+
[format == 'PNG' ? 'image/png' : 'image/jpeg', obj.to_blob { |i| i.format = format }]
|
|
239
279
|
end
|
|
240
280
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
281
|
+
match do |obj|
|
|
282
|
+
defined?(Vips::Image) && Vips::Image === obj
|
|
283
|
+
end
|
|
284
|
+
format do |obj|
|
|
285
|
+
# handles Vips::Error, vips_image_get: field "vips-loader" not found
|
|
286
|
+
loader = obj.get('vips-loader') rescue nil
|
|
287
|
+
if loader == 'jpegload'
|
|
288
|
+
['image/jpeg', obj.write_to_buffer('.jpg')]
|
|
289
|
+
else
|
|
290
|
+
# falls back to png for other/unknown types
|
|
291
|
+
['image/png', obj.write_to_buffer('.png')]
|
|
292
|
+
end
|
|
244
293
|
end
|
|
245
294
|
|
|
295
|
+
type { Gruff::Base }
|
|
296
|
+
format 'image/png', &:to_blob
|
|
297
|
+
|
|
246
298
|
respond_to :to_html
|
|
247
|
-
format 'text/html'
|
|
248
|
-
obj.to_html
|
|
249
|
-
end
|
|
299
|
+
format 'text/html', &:to_html
|
|
250
300
|
|
|
251
301
|
respond_to :to_latex
|
|
252
|
-
format 'text/latex'
|
|
253
|
-
obj.to_latex
|
|
254
|
-
end
|
|
302
|
+
format 'text/latex', &:to_latex
|
|
255
303
|
|
|
256
304
|
respond_to :to_tex
|
|
257
|
-
format 'text/latex'
|
|
258
|
-
obj.to_tex
|
|
259
|
-
end
|
|
305
|
+
format 'text/latex', &:to_tex
|
|
260
306
|
|
|
261
307
|
respond_to :to_javascript
|
|
262
|
-
format 'text/javascript'
|
|
263
|
-
obj.to_javascript
|
|
264
|
-
end
|
|
308
|
+
format 'text/javascript', &:to_javascript
|
|
265
309
|
|
|
266
310
|
respond_to :to_svg
|
|
267
311
|
format 'image/svg+xml' do |obj|
|
|
@@ -270,21 +314,17 @@ module IRuby
|
|
|
270
314
|
end
|
|
271
315
|
|
|
272
316
|
respond_to :to_iruby
|
|
273
|
-
format
|
|
274
|
-
obj.to_iruby
|
|
275
|
-
end
|
|
317
|
+
format(&:to_iruby)
|
|
276
318
|
|
|
277
|
-
match {|obj| obj.respond_to?(:path) && File.readable?(obj.path) }
|
|
319
|
+
match { |obj| obj.respond_to?(:path) && obj.method(:path).arity == 0 && File.readable?(obj.path) }
|
|
278
320
|
format do |obj|
|
|
279
|
-
mime =
|
|
321
|
+
mime = MIME::Types.of(obj.path).first.to_s
|
|
280
322
|
[mime, File.read(obj.path)] if SUPPORTED_MIMES.include?(mime)
|
|
281
323
|
end
|
|
282
324
|
|
|
283
325
|
type { Object }
|
|
284
|
-
priority
|
|
285
|
-
format 'text/plain'
|
|
286
|
-
obj.inspect
|
|
287
|
-
end
|
|
326
|
+
priority(-1000)
|
|
327
|
+
format 'text/plain', &:inspect
|
|
288
328
|
end
|
|
289
329
|
end
|
|
290
330
|
end
|