iruby 0.8.2 → 0.8.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +15 -11
- data/CHANGES.md +12 -1
- data/README.md +8 -11
- data/Rakefile +0 -24
- data/iruby.gemspec +1 -3
- data/lib/iruby/backend.rb +1 -1
- data/lib/iruby/input/README.ipynb +2 -2
- data/lib/iruby/input/README.md +2 -2
- data/lib/iruby/input/form.rb +2 -2
- data/lib/iruby/kernel.rb +15 -1
- data/lib/iruby/session.rb +39 -3
- data/lib/iruby/session_adapter/ffirzmq_adapter.rb +27 -5
- data/lib/iruby/session_adapter/test_adapter.rb +22 -1
- data/lib/iruby/session_adapter.rb +12 -0
- data/lib/iruby/{session/mixin.rb → session_serializer.rb} +8 -8
- data/lib/iruby/version.rb +1 -1
- data/lib/iruby.rb +2 -16
- data/test/helper.rb +3 -2
- data/test/iruby/application/console_test.rb +1 -1
- data/test/iruby/kernel_test.rb +1 -0
- data/test/iruby/session_test.rb +35 -2
- metadata +6 -45
- data/ci/Dockerfile.base.erb +0 -41
- data/ci/Dockerfile.main.erb +0 -7
- data/ci/requirements.txt +0 -1
- data/docker/setup.sh +0 -15
- data/docker/test.sh +0 -7
- data/lib/iruby/session/cztop.rb +0 -70
- data/lib/iruby/session/ffi_rzmq.rb +0 -87
- data/run-test.sh +0 -12
- data/tasks/ci.rake +0 -65
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 43bde0525564da42d868ec8eded9727ba0398ad0ae30e7fbcaea3eb795068a24
|
|
4
|
+
data.tar.gz: 32bc31a371dcccc92c04ee85b557754d3336f88a9aec72efd6dbe9cfe096552a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a8c7e7275de0fb026784a66286a8e3474fe54a8d60b551e2103434d3d5a1ada05ad1d5dfd2e285f19aaa4ef4bff07d181b956cef23b2da788158e9c400cae871
|
|
7
|
+
data.tar.gz: 6f66cf0aab532b765d3760287fb0e1aab4578054484d7fa7b4cd5d724222154c943c2768597f36054bdddb6da6b9c8aa23040b1f278618d9917ead1f61ce3969
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -16,6 +16,7 @@ jobs:
|
|
|
16
16
|
os:
|
|
17
17
|
- ubuntu-latest
|
|
18
18
|
ruby:
|
|
19
|
+
- "4.0"
|
|
19
20
|
- "3.4"
|
|
20
21
|
- "3.3"
|
|
21
22
|
- "3.2"
|
|
@@ -27,7 +28,7 @@ jobs:
|
|
|
27
28
|
- debug
|
|
28
29
|
|
|
29
30
|
steps:
|
|
30
|
-
- uses: actions/checkout@
|
|
31
|
+
- uses: actions/checkout@v7
|
|
31
32
|
with:
|
|
32
33
|
fetch-depth: 1
|
|
33
34
|
|
|
@@ -35,6 +36,15 @@ jobs:
|
|
|
35
36
|
with:
|
|
36
37
|
ruby-version: ${{ matrix.ruby }}
|
|
37
38
|
|
|
39
|
+
- uses: mamba-org/setup-micromamba@v3
|
|
40
|
+
with:
|
|
41
|
+
environment-name: iruby-ci
|
|
42
|
+
create-args: >-
|
|
43
|
+
python=3.12
|
|
44
|
+
jupyter_console
|
|
45
|
+
cache-environment: true
|
|
46
|
+
cache-downloads: true
|
|
47
|
+
|
|
38
48
|
- run: rake build
|
|
39
49
|
|
|
40
50
|
- name: Install ffi (if Ruby 2.7)
|
|
@@ -81,23 +91,17 @@ jobs:
|
|
|
81
91
|
run: |
|
|
82
92
|
sudo apt update
|
|
83
93
|
sudo apt install -y --no-install-recommends \
|
|
84
|
-
libczmq-dev
|
|
85
|
-
python3 \
|
|
86
|
-
python3-pip \
|
|
87
|
-
python3-setuptools
|
|
88
|
-
sudo pip3 install wheel
|
|
89
|
-
sudo pip3 install -r ci/requirements.txt
|
|
94
|
+
libczmq-dev
|
|
90
95
|
|
|
91
96
|
- run: bundle install --jobs 4 --retry 3
|
|
92
97
|
|
|
93
98
|
- name: Run tests
|
|
94
99
|
env:
|
|
95
|
-
PYTHON: python3
|
|
96
100
|
ADAPTERS: cztop ffi-rzmq
|
|
97
101
|
run: |
|
|
98
102
|
for adapter in $ADAPTERS; do
|
|
99
103
|
export IRUBY_TEST_SESSION_ADAPTER_NAME=$adapter
|
|
100
|
-
bundle exec rake test TESTOPTS="-v"
|
|
104
|
+
micromamba run -n iruby-ci bundle exec rake test TESTOPTS="-v"
|
|
101
105
|
done
|
|
102
106
|
|
|
103
107
|
windows:
|
|
@@ -105,7 +109,7 @@ jobs:
|
|
|
105
109
|
runs-on: windows-latest
|
|
106
110
|
|
|
107
111
|
steps:
|
|
108
|
-
- uses: actions/checkout@
|
|
112
|
+
- uses: actions/checkout@v7
|
|
109
113
|
with:
|
|
110
114
|
fetch-depth: 1
|
|
111
115
|
|
|
@@ -126,7 +130,7 @@ jobs:
|
|
|
126
130
|
runs-on: macos-latest
|
|
127
131
|
|
|
128
132
|
steps:
|
|
129
|
-
- uses: actions/checkout@
|
|
133
|
+
- uses: actions/checkout@v7
|
|
130
134
|
with:
|
|
131
135
|
fetch-depth: 1
|
|
132
136
|
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
# 0.8.3 (2026-06-30)
|
|
2
|
+
|
|
3
|
+
* Remove MultiJson dependency and replace with JSON by @kojix2 in https://github.com/SciRuby/iruby/pull/373
|
|
4
|
+
* Fix undefined var in FfirzmqAdapter by @kojix2 in https://github.com/SciRuby/iruby/pull/377
|
|
5
|
+
* Avoid conflict with Ruby's numbered parameters by @zalt50 in https://github.com/SciRuby/iruby/pull/380
|
|
6
|
+
* Remove legacy IRUBY_OLD_SESSION session implementations by @kojix2 in https://github.com/SciRuby/iruby/pull/384
|
|
7
|
+
* Add explicit session cleanup by @kojix2 in https://github.com/SciRuby/iruby/pull/388
|
|
8
|
+
* Use raw zmq_proxy for ffi-rzmq heartbeat by @kojix2 in https://github.com/SciRuby/iruby/pull/391
|
|
9
|
+
* Remove obsolete PyCall dependency by @kojix2 in https://github.com/SciRuby/iruby/pull/393
|
|
10
|
+
* Add Ruby 4.0 to CI workflow matrix by @kojix2 in https://github.com/SciRuby/iruby/pull/394
|
|
11
|
+
|
|
1
12
|
# 0.8.2 (2025-04-10)
|
|
2
13
|
|
|
3
14
|
* Update CI to refresh apt packages before installing IRuby gem by @kojix2 in https://github.com/SciRuby/iruby/pull/367
|
|
@@ -141,7 +152,7 @@
|
|
|
141
152
|
|
|
142
153
|
* Improvements to IRuby dependency detection using `Bundler::Dependencies#specs` (@kou).
|
|
143
154
|
* Use less memory forcing pry to store only the last 3 commands in memory (@kylekyle).
|
|
144
|
-
* Use bigger z-index that is used
|
|
155
|
+
* Use bigger z-index that is used across all browsers (@kylekyle).
|
|
145
156
|
* Ability to input date values as DateTime objects in IRuby/Input (@kylekyle).
|
|
146
157
|
* Add option to have check boxes checked by default (@kylekyle).
|
|
147
158
|
* Option for multi-select in drop down menus in the prompter (@kylekyle).
|
data/README.md
CHANGED
|
@@ -6,15 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
IRuby is a Ruby kernel for [Jupyter project](https://jupyter.org/).
|
|
8
8
|
|
|
9
|
-
## Try IRuby
|
|
10
|
-
|
|
11
|
-
You can try IRuby with a sample notebook on Binder (the same link as the banner placed above):
|
|
12
|
-
|
|
13
|
-
<https://mybinder.org/v2/gh/RubyData/binder/master?filepath=ruby-data.ipynb>
|
|
14
|
-
|
|
15
|
-
The following URL launches JupyterLab directly on Binder.
|
|
16
|
-
|
|
17
|
-
<https://mybinder.org/v2/gh/RubyData/binder/master?filepath=../lab>
|
|
18
9
|
|
|
19
10
|
## Installation
|
|
20
11
|
|
|
@@ -35,8 +26,8 @@ The following dependencies are optional.
|
|
|
35
26
|
|
|
36
27
|
See the official document to know how to install Jupyter Notebook and/or JupyterLab.
|
|
37
28
|
|
|
38
|
-
- <https://jupyter.
|
|
39
|
-
- <https://jupyter.
|
|
29
|
+
- <https://docs.jupyter.org/en/latest/install/notebook-classic.html>
|
|
30
|
+
- <https://docs.jupyter.org/en/latest/install.html>
|
|
40
31
|
|
|
41
32
|
### Ubuntu
|
|
42
33
|
|
|
@@ -167,6 +158,12 @@ Take a look at the [example notebook](https://nbviewer.jupyter.org/urls/raw.gith
|
|
|
167
158
|
and the [collection of notebooks](https://github.com/SciRuby/sciruby-notebooks/) which includes a Dockerfile to create a containerized installation of iruby
|
|
168
159
|
and other scientific gems.
|
|
169
160
|
|
|
161
|
+
## Try IRuby
|
|
162
|
+
|
|
163
|
+
- [Try a sample notebook on Binder](https://mybinder.org/v2/gh/RubyData/binder/master?filepath=ruby-data.ipynb)
|
|
164
|
+
|
|
165
|
+
- [Launch JupyterLab on Binder](https://mybinder.org/v2/gh/RubyData/binder/master?filepath=../lab)
|
|
166
|
+
|
|
170
167
|
## Contributing
|
|
171
168
|
|
|
172
169
|
Contributions to IRuby are very welcome.
|
data/Rakefile
CHANGED
|
@@ -16,27 +16,3 @@ task :test do
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
task default: 'test'
|
|
19
|
-
|
|
20
|
-
namespace :docker do
|
|
21
|
-
def root_dir
|
|
22
|
-
@root_dir ||= File.expand_path("..", __FILE__)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
task :build do
|
|
26
|
-
container_name = "iruby_build"
|
|
27
|
-
image_name = "mrkn/iruby"
|
|
28
|
-
sh "docker", "run",
|
|
29
|
-
"--name", container_name,
|
|
30
|
-
"-v", "#{root_dir}:/tmp/iruby",
|
|
31
|
-
"rubylang/ruby", "/bin/bash", "/tmp/iruby/docker/setup.sh"
|
|
32
|
-
sh "docker", "commit", container_name, image_name
|
|
33
|
-
sh "docker", "rm", container_name
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
task :test do
|
|
37
|
-
root_dir = File.expand_path("..", __FILE__)
|
|
38
|
-
sh "docker", "run", "-it", "--rm",
|
|
39
|
-
"-v", "#{root_dir}:/tmp/iruby",
|
|
40
|
-
"mrkn/iruby", "/bin/bash", "/tmp/iruby/docker/test.sh"
|
|
41
|
-
end
|
|
42
|
-
end
|
data/iruby.gemspec
CHANGED
|
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
|
6
6
|
s.authors = ['Daniel Mendler', 'The SciRuby developers']
|
|
7
7
|
s.email = ['mail@daniel-mendler.de']
|
|
8
8
|
s.summary = 'Ruby Kernel for Jupyter'
|
|
9
|
-
s.description = 'A Ruby kernel for Jupyter environment.
|
|
9
|
+
s.description = 'A Ruby kernel for Jupyter environment.'
|
|
10
10
|
s.homepage = 'https://github.com/SciRuby/iruby'
|
|
11
11
|
s.license = 'MIT'
|
|
12
12
|
|
|
@@ -23,9 +23,7 @@ Gem::Specification.new do |s|
|
|
|
23
23
|
s.add_dependency 'irb'
|
|
24
24
|
s.add_dependency 'logger'
|
|
25
25
|
s.add_dependency 'mime-types', '>= 3.3.1'
|
|
26
|
-
s.add_dependency 'multi_json', '~> 1.11'
|
|
27
26
|
|
|
28
|
-
s.add_development_dependency 'pycall', '>= 1.2.1'
|
|
29
27
|
s.add_development_dependency 'rake'
|
|
30
28
|
s.add_development_dependency 'test-unit'
|
|
31
29
|
s.add_development_dependency 'test-unit-rr'
|
data/lib/iruby/backend.rb
CHANGED
|
@@ -18,7 +18,7 @@ module IRuby
|
|
|
18
18
|
# TODO Add IRuby.cache_size which controls the size of the Out array
|
|
19
19
|
# and sets the oldest entries and _<n> variables to nil.
|
|
20
20
|
if store_history
|
|
21
|
-
b.local_variable_set("
|
|
21
|
+
b.local_variable_set("_o#{Out.size}", out)
|
|
22
22
|
b.local_variable_set("_i#{In.size}", code)
|
|
23
23
|
|
|
24
24
|
Out << out
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"\n",
|
|
114
114
|
"The enter key will submit an input or form and the escape key will cancel it. Canceled inputs are returned as `nil`. Inputs are automatically canceled if destroyed. An input can be destroyed by clearing its cell's output. The `cancel` button will cancel a form and all other buttons will submit it. \n",
|
|
115
115
|
"\n",
|
|
116
|
-
"After a form destroyed, the cell's output is cleared. Be careful not to prompt for input in a block that has previous output you would like to keep. Output is cleared to prevent forms from
|
|
116
|
+
"After a form destroyed, the cell's output is cleared. Be careful not to prompt for input in a block that has previous output you would like to keep. Output is cleared to prevent forms from interfering with one another and to ensure that inputs are not inadvertently saved to the notebook. "
|
|
117
117
|
]
|
|
118
118
|
},
|
|
119
119
|
{
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
"source": [
|
|
185
185
|
"## Defaults\n",
|
|
186
186
|
"\n",
|
|
187
|
-
"Most inputs will accept a `default` parameter. If no default is given, the
|
|
187
|
+
"Most inputs will accept a `default` parameter. If no default is given, the default is `nil`. Since checkboxes can have multiple values selected, you can pass an array of values. To check everything, pass `true` as the default. "
|
|
188
188
|
]
|
|
189
189
|
},
|
|
190
190
|
{
|
data/lib/iruby/input/README.md
CHANGED
|
@@ -67,7 +67,7 @@ end
|
|
|
67
67
|
|
|
68
68
|
The enter key will submit an input or form and the escape key will cancel it. Canceled inputs are returned as `nil`. Inputs are automatically canceled if destroyed. An input can be destroyed by clearing its cell's output. The `cancel` button will cancel a form and all other buttons will submit it.
|
|
69
69
|
|
|
70
|
-
After a form destroyed, the cell's output is cleared. Be careful not to prompt for input in a block that has previous output you would like to keep. Output is cleared to prevent forms from
|
|
70
|
+
After a form destroyed, the cell's output is cleared. Be careful not to prompt for input in a block that has previous output you would like to keep. Output is cleared to prevent forms from interfering with one another and to ensure that inputs are not inadvertently saved to the notebook.
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
```ruby
|
|
@@ -105,7 +105,7 @@ end
|
|
|
105
105
|
|
|
106
106
|
## Defaults
|
|
107
107
|
|
|
108
|
-
Most inputs will accept a `default` parameter. If no default is given, the
|
|
108
|
+
Most inputs will accept a `default` parameter. If no default is given, the default is `nil`. Since checkboxes can have multiple values selected, you can pass an array of values. To check everything, pass `true` as the default.
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
```ruby
|
data/lib/iruby/input/form.rb
CHANGED
|
@@ -63,7 +63,7 @@ module IRuby
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def submit
|
|
66
|
-
result =
|
|
66
|
+
result = JSON.parse(Kernel.instance.session.recv_input)
|
|
67
67
|
|
|
68
68
|
unless result.has_key? @id
|
|
69
69
|
submit
|
|
@@ -74,4 +74,4 @@ module IRuby
|
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
|
-
end
|
|
77
|
+
end
|
data/lib/iruby/kernel.rb
CHANGED
|
@@ -38,7 +38,7 @@ module IRuby
|
|
|
38
38
|
].freeze
|
|
39
39
|
|
|
40
40
|
def initialize(config_file, session_adapter_name=nil)
|
|
41
|
-
@config =
|
|
41
|
+
@config = JSON.parse(File.read(config_file))
|
|
42
42
|
IRuby.logger.debug("IRuby kernel start with config #{@config}")
|
|
43
43
|
Kernel.instance = self
|
|
44
44
|
|
|
@@ -126,6 +126,13 @@ module IRuby
|
|
|
126
126
|
while @running
|
|
127
127
|
dispatch
|
|
128
128
|
end
|
|
129
|
+
ensure
|
|
130
|
+
close
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def close
|
|
134
|
+
@session&.close
|
|
135
|
+
stop_parent_process_poller
|
|
129
136
|
end
|
|
130
137
|
|
|
131
138
|
# @private
|
|
@@ -314,6 +321,13 @@ module IRuby
|
|
|
314
321
|
end
|
|
315
322
|
end
|
|
316
323
|
|
|
324
|
+
def stop_parent_process_poller
|
|
325
|
+
return unless @parent_poller&.alive?
|
|
326
|
+
|
|
327
|
+
@parent_poller.kill
|
|
328
|
+
@parent_poller.join
|
|
329
|
+
end
|
|
330
|
+
|
|
317
331
|
def start_parent_process_pollar_unix
|
|
318
332
|
Thread.start do
|
|
319
333
|
IRuby.logger.warn("parent process poller thread started.")
|
data/lib/iruby/session.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'iruby/session_adapter'
|
|
2
|
-
require 'iruby/
|
|
2
|
+
require 'iruby/session_serializer'
|
|
3
3
|
|
|
4
4
|
require 'securerandom'
|
|
5
5
|
require 'time'
|
|
@@ -25,6 +25,26 @@ module IRuby
|
|
|
25
25
|
"#{@adapter.name} session adapter"
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
def close
|
|
29
|
+
return if @closed
|
|
30
|
+
|
|
31
|
+
@closed = true
|
|
32
|
+
begin
|
|
33
|
+
@adapter.shutdown_heartbeat(@hb_socket) if @hb_socket
|
|
34
|
+
ensure
|
|
35
|
+
begin
|
|
36
|
+
stop_heartbeat
|
|
37
|
+
ensure
|
|
38
|
+
begin
|
|
39
|
+
close_sockets
|
|
40
|
+
ensure
|
|
41
|
+
@adapter.close
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Optional setup hook.
|
|
28
48
|
def setup
|
|
29
49
|
end
|
|
30
50
|
|
|
@@ -51,10 +71,10 @@ module IRuby
|
|
|
51
71
|
@hb_socket, @hb_port = @adapter.make_rep_socket(protocol, host, hb_port)
|
|
52
72
|
@heartbeat_thread = Thread.start do
|
|
53
73
|
begin
|
|
54
|
-
#
|
|
74
|
+
# Adapters should return when cleanup closes the heartbeat socket/context.
|
|
55
75
|
@adapter.heartbeat_loop(@hb_socket)
|
|
56
76
|
rescue Exception => e
|
|
57
|
-
IRuby.logger.fatal "Kernel heartbeat died: #{e.message}\n#{e.backtrace.join("\n")}"
|
|
77
|
+
IRuby.logger.fatal "Kernel heartbeat died: #{e.message}\n#{e.backtrace.join("\n")}" unless @closed
|
|
58
78
|
end
|
|
59
79
|
end
|
|
60
80
|
end
|
|
@@ -102,6 +122,22 @@ module IRuby
|
|
|
102
122
|
|
|
103
123
|
private
|
|
104
124
|
|
|
125
|
+
def close_sockets
|
|
126
|
+
@sockets&.values&.each do |socket|
|
|
127
|
+
@adapter.close_socket(socket)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def stop_heartbeat
|
|
132
|
+
return unless @heartbeat_thread&.alive?
|
|
133
|
+
|
|
134
|
+
@heartbeat_thread.join(1)
|
|
135
|
+
return unless @heartbeat_thread.alive?
|
|
136
|
+
|
|
137
|
+
@heartbeat_thread.kill
|
|
138
|
+
@heartbeat_thread.join
|
|
139
|
+
end
|
|
140
|
+
|
|
105
141
|
def check_socket_type(socket_type)
|
|
106
142
|
case socket_type
|
|
107
143
|
when :publish, :reply, :stdin
|
|
@@ -26,23 +26,41 @@ module IRuby
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def heartbeat_loop(sock)
|
|
29
|
-
|
|
29
|
+
# Avoid ZMQ::Device in #357; call libzmq's proxy directly.
|
|
30
|
+
rc = LibZMQ.zmq_proxy(sock.socket, sock.socket, nil)
|
|
31
|
+
errno = ZMQ::Util.errno
|
|
32
|
+
return if rc == -1 && (zmq_errno?(:ETERM, errno) || zmq_errno?(:EINTR, errno))
|
|
33
|
+
|
|
34
|
+
ZMQ::Util.error_check('zmq_proxy', rc)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def shutdown_heartbeat(sock)
|
|
38
|
+
if @zmq_context&.context && LibZMQ.respond_to?(:zmq_ctx_shutdown)
|
|
39
|
+
LibZMQ.zmq_ctx_shutdown(@zmq_context.context)
|
|
40
|
+
end
|
|
41
|
+
close_socket(sock)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def close
|
|
45
|
+
@zmq_context&.terminate
|
|
46
|
+
@zmq_context = nil
|
|
30
47
|
end
|
|
31
48
|
|
|
32
49
|
private
|
|
33
50
|
|
|
34
|
-
def make_socket(
|
|
35
|
-
case
|
|
51
|
+
def make_socket(type_symbol, protocol, host, port)
|
|
52
|
+
case type_symbol
|
|
36
53
|
when :ROUTER, :PUB, :REP
|
|
37
|
-
type = ZMQ.const_get(
|
|
54
|
+
type = ZMQ.const_get(type_symbol)
|
|
38
55
|
else
|
|
39
|
-
if ZMQ.const_defined?(
|
|
56
|
+
if ZMQ.const_defined?(type_symbol)
|
|
40
57
|
raise ArgumentError, "Unsupported ZMQ socket type: #{type_symbol}"
|
|
41
58
|
else
|
|
42
59
|
raise ArgumentError, "Invalid ZMQ socket type: #{type_symbol}"
|
|
43
60
|
end
|
|
44
61
|
end
|
|
45
62
|
zmq_context.socket(type).tap do |sock|
|
|
63
|
+
sock.setsockopt(ZMQ::LINGER, 0) if type_symbol == :REP
|
|
46
64
|
sock.bind("#{protocol}://#{host}:#{port}")
|
|
47
65
|
end
|
|
48
66
|
end
|
|
@@ -50,6 +68,10 @@ module IRuby
|
|
|
50
68
|
def zmq_context
|
|
51
69
|
@zmq_context ||= ZMQ::Context.new
|
|
52
70
|
end
|
|
71
|
+
|
|
72
|
+
def zmq_errno?(name, errno)
|
|
73
|
+
ZMQ.const_defined?(name) && ZMQ.const_get(name) == errno
|
|
74
|
+
end
|
|
53
75
|
end
|
|
54
76
|
end
|
|
55
77
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require 'iruby/
|
|
1
|
+
require 'iruby/session_serializer'
|
|
2
2
|
|
|
3
3
|
module IRuby
|
|
4
4
|
module SessionAdapter
|
|
@@ -20,9 +20,14 @@ module IRuby
|
|
|
20
20
|
|
|
21
21
|
@send_callback = nil
|
|
22
22
|
@recv_callback = nil
|
|
23
|
+
@closed_sockets = []
|
|
24
|
+
@closed = false
|
|
25
|
+
@heartbeat_started = false
|
|
26
|
+
@heartbeat_finished = false
|
|
23
27
|
end
|
|
24
28
|
|
|
25
29
|
attr_accessor :send_callback, :recv_callback
|
|
30
|
+
attr_reader :closed_sockets, :closed, :heartbeat_started, :heartbeat_finished
|
|
26
31
|
|
|
27
32
|
def send(sock, data)
|
|
28
33
|
unless @send_callback.nil?
|
|
@@ -37,6 +42,22 @@ module IRuby
|
|
|
37
42
|
end
|
|
38
43
|
|
|
39
44
|
def heartbeat_loop(sock)
|
|
45
|
+
@heartbeat_started = true
|
|
46
|
+
sleep 0.01 until @closed
|
|
47
|
+
@heartbeat_finished = true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def close_socket(sock)
|
|
51
|
+
@closed_sockets << sock
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def shutdown_heartbeat(sock)
|
|
55
|
+
@closed = true
|
|
56
|
+
close_socket(sock)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def close
|
|
60
|
+
@closed = true
|
|
40
61
|
end
|
|
41
62
|
|
|
42
63
|
private
|
|
@@ -36,6 +36,18 @@ module IRuby
|
|
|
36
36
|
socket, port = make_socket(:REP, protocol, host, port)
|
|
37
37
|
[socket, port]
|
|
38
38
|
end
|
|
39
|
+
|
|
40
|
+
def close_socket(socket)
|
|
41
|
+
socket.close if socket.respond_to?(:close)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def shutdown_heartbeat(socket)
|
|
45
|
+
close_socket(socket)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Override in adapters that need cleanup.
|
|
49
|
+
def close
|
|
50
|
+
end
|
|
39
51
|
end
|
|
40
52
|
|
|
41
53
|
require_relative 'session_adapter/ffirzmq_adapter'
|
|
@@ -5,10 +5,10 @@ module IRuby
|
|
|
5
5
|
private
|
|
6
6
|
|
|
7
7
|
def serialize(idents, header, metadata = nil, content)
|
|
8
|
-
msg = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
msg = [JSON.generate(header),
|
|
9
|
+
JSON.generate(@last_recvd_msg ? @last_recvd_msg[:header] : {}),
|
|
10
|
+
JSON.generate(metadata || {}),
|
|
11
|
+
JSON.generate(content || {})]
|
|
12
12
|
frames = ([*idents].compact.map(&:to_s) << DELIM << sign(msg)) + msg
|
|
13
13
|
IRuby.logger.debug "Sent #{frames.inspect}"
|
|
14
14
|
frames
|
|
@@ -28,10 +28,10 @@ module IRuby
|
|
|
28
28
|
raise 'Invalid signature' unless s == sign(msg_list[1..-1])
|
|
29
29
|
{
|
|
30
30
|
idents: idents,
|
|
31
|
-
header:
|
|
32
|
-
parent_header:
|
|
33
|
-
metadata:
|
|
34
|
-
content:
|
|
31
|
+
header: JSON.parse(header),
|
|
32
|
+
parent_header: JSON.parse(parent_header),
|
|
33
|
+
metadata: JSON.parse(metadata),
|
|
34
|
+
content: JSON.parse(content),
|
|
35
35
|
buffers: buffers
|
|
36
36
|
}
|
|
37
37
|
end
|
data/lib/iruby/version.rb
CHANGED
data/lib/iruby.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'fileutils'
|
|
2
2
|
require 'mime/types'
|
|
3
|
-
require '
|
|
3
|
+
require 'json'
|
|
4
4
|
require 'securerandom'
|
|
5
5
|
require 'openssl'
|
|
6
6
|
require 'tempfile'
|
|
@@ -19,18 +19,4 @@ require 'iruby/formatter'
|
|
|
19
19
|
require 'iruby/utils'
|
|
20
20
|
require 'iruby/display'
|
|
21
21
|
require 'iruby/comm'
|
|
22
|
-
|
|
23
|
-
if ENV.fetch('IRUBY_OLD_SESSION', false)
|
|
24
|
-
require 'iruby/session/mixin'
|
|
25
|
-
begin
|
|
26
|
-
require 'iruby/session/ffi_rzmq'
|
|
27
|
-
rescue LoadError
|
|
28
|
-
begin
|
|
29
|
-
require 'iruby/session/cztop'
|
|
30
|
-
rescue LoadError
|
|
31
|
-
STDERR.puts "Please install ffi-rzmq or cztop before running iruby. See README."
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
else
|
|
35
|
-
require 'iruby/session'
|
|
36
|
-
end
|
|
22
|
+
require 'iruby/session'
|
data/test/helper.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require "iruby"
|
|
2
2
|
require "json"
|
|
3
|
-
require 'multi_json'
|
|
4
3
|
require "pathname"
|
|
5
4
|
require "rbconfig"
|
|
6
5
|
require "test/unit"
|
|
@@ -61,10 +60,12 @@ module IRubyTest
|
|
|
61
60
|
end
|
|
62
61
|
|
|
63
62
|
def teardown
|
|
63
|
+
IRuby::Kernel.instance&.close
|
|
64
64
|
self.class.restore_kernel
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def with_session_adapter(session_adapter_name)
|
|
68
|
+
IRuby::Kernel.instance&.close
|
|
68
69
|
IRuby::Kernel.new(self.class.test_config_filename, session_adapter_name)
|
|
69
70
|
$stdout = STDOUT
|
|
70
71
|
$stderr = STDERR
|
|
@@ -137,7 +138,7 @@ module IRubyTest
|
|
|
137
138
|
end
|
|
138
139
|
|
|
139
140
|
def apple_only
|
|
140
|
-
omit('apple only test') unless
|
|
141
|
+
omit('apple only test') unless apple?
|
|
141
142
|
end
|
|
142
143
|
|
|
143
144
|
def unix_only
|
|
@@ -74,7 +74,7 @@ module IRubyTest::ApplicationTests
|
|
|
74
74
|
kernel_name = "other-kernel-#{Process.pid}"
|
|
75
75
|
out, status = Open3.capture2e(*iruby_command("console", "--kernel=#{kernel_name}"))
|
|
76
76
|
refute status.success?
|
|
77
|
-
assert_match(/\
|
|
77
|
+
assert_match(/\b(?:No such kernel named|Could not find kernel) '?#{Regexp.escape(kernel_name)}'?(?=\W|\z)/, out)
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
|
data/test/iruby/kernel_test.rb
CHANGED
data/test/iruby/session_test.rb
CHANGED
|
@@ -15,7 +15,7 @@ module IRubyTest
|
|
|
15
15
|
}
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def
|
|
18
|
+
def test_selects_correct_adapter_class
|
|
19
19
|
adapter_name = ENV['IRUBY_TEST_SESSION_ADAPTER_NAME']
|
|
20
20
|
adapter_class = case adapter_name
|
|
21
21
|
when 'cztop'
|
|
@@ -26,8 +26,20 @@ module IRubyTest
|
|
|
26
26
|
flunk "Unknown session adapter: #{adapter_name.inspect}"
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
selected_class = IRuby::SessionAdapter.select_adapter_class(adapter_name)
|
|
30
|
+
assert_equal(adapter_class, selected_class)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_new_with_session_adapter_closes_heartbeat
|
|
34
|
+
adapter_name = ENV['IRUBY_TEST_SESSION_ADAPTER_NAME']
|
|
35
|
+
omit("ffi-rzmq only") unless adapter_name == 'ffi-rzmq'
|
|
36
|
+
|
|
29
37
|
session = IRuby::Session.new(@session_config, adapter_name)
|
|
30
|
-
|
|
38
|
+
|
|
39
|
+
session.close
|
|
40
|
+
refute(session.instance_variable_get(:@heartbeat_thread).alive?)
|
|
41
|
+
ensure
|
|
42
|
+
session&.close
|
|
31
43
|
end
|
|
32
44
|
|
|
33
45
|
def test_without_any_session_adapter
|
|
@@ -40,5 +52,26 @@ module IRubyTest
|
|
|
40
52
|
end
|
|
41
53
|
end
|
|
42
54
|
end
|
|
55
|
+
|
|
56
|
+
def test_close_releases_adapter_resources
|
|
57
|
+
session = IRuby::Session.new(@session_config, "test")
|
|
58
|
+
adapter = session.adapter
|
|
59
|
+
|
|
60
|
+
session.close
|
|
61
|
+
|
|
62
|
+
assert(adapter.closed)
|
|
63
|
+
assert(adapter.heartbeat_started)
|
|
64
|
+
assert(adapter.heartbeat_finished)
|
|
65
|
+
assert_equal([
|
|
66
|
+
:PUB,
|
|
67
|
+
:REP,
|
|
68
|
+
:ROUTER,
|
|
69
|
+
:ROUTER,
|
|
70
|
+
],
|
|
71
|
+
adapter.closed_sockets.map(&:type).sort_by(&:to_s))
|
|
72
|
+
refute(session.instance_variable_get(:@heartbeat_thread).alive?)
|
|
73
|
+
ensure
|
|
74
|
+
session&.close
|
|
75
|
+
end
|
|
43
76
|
end
|
|
44
77
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: iruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Mendler
|
|
8
8
|
- The SciRuby developers
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: exe
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: data_uri
|
|
@@ -81,34 +80,6 @@ dependencies:
|
|
|
81
80
|
- - ">="
|
|
82
81
|
- !ruby/object:Gem::Version
|
|
83
82
|
version: 3.3.1
|
|
84
|
-
- !ruby/object:Gem::Dependency
|
|
85
|
-
name: multi_json
|
|
86
|
-
requirement: !ruby/object:Gem::Requirement
|
|
87
|
-
requirements:
|
|
88
|
-
- - "~>"
|
|
89
|
-
- !ruby/object:Gem::Version
|
|
90
|
-
version: '1.11'
|
|
91
|
-
type: :runtime
|
|
92
|
-
prerelease: false
|
|
93
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
94
|
-
requirements:
|
|
95
|
-
- - "~>"
|
|
96
|
-
- !ruby/object:Gem::Version
|
|
97
|
-
version: '1.11'
|
|
98
|
-
- !ruby/object:Gem::Dependency
|
|
99
|
-
name: pycall
|
|
100
|
-
requirement: !ruby/object:Gem::Requirement
|
|
101
|
-
requirements:
|
|
102
|
-
- - ">="
|
|
103
|
-
- !ruby/object:Gem::Version
|
|
104
|
-
version: 1.2.1
|
|
105
|
-
type: :development
|
|
106
|
-
prerelease: false
|
|
107
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
-
requirements:
|
|
109
|
-
- - ">="
|
|
110
|
-
- !ruby/object:Gem::Version
|
|
111
|
-
version: 1.2.1
|
|
112
83
|
- !ruby/object:Gem::Dependency
|
|
113
84
|
name: rake
|
|
114
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -151,7 +122,7 @@ dependencies:
|
|
|
151
122
|
- - ">="
|
|
152
123
|
- !ruby/object:Gem::Version
|
|
153
124
|
version: '0'
|
|
154
|
-
description: A Ruby kernel for Jupyter environment.
|
|
125
|
+
description: A Ruby kernel for Jupyter environment.
|
|
155
126
|
email:
|
|
156
127
|
- mail@daniel-mendler.de
|
|
157
128
|
executables:
|
|
@@ -159,6 +130,7 @@ executables:
|
|
|
159
130
|
extensions: []
|
|
160
131
|
extra_rdoc_files: []
|
|
161
132
|
files:
|
|
133
|
+
- ".github/dependabot.yml"
|
|
162
134
|
- ".github/workflows/ci.yml"
|
|
163
135
|
- ".gitignore"
|
|
164
136
|
- CHANGES.md
|
|
@@ -166,11 +138,6 @@ files:
|
|
|
166
138
|
- LICENSE
|
|
167
139
|
- README.md
|
|
168
140
|
- Rakefile
|
|
169
|
-
- ci/Dockerfile.base.erb
|
|
170
|
-
- ci/Dockerfile.main.erb
|
|
171
|
-
- ci/requirements.txt
|
|
172
|
-
- docker/setup.sh
|
|
173
|
-
- docker/test.sh
|
|
174
141
|
- exe/iruby
|
|
175
142
|
- iruby.gemspec
|
|
176
143
|
- lib/iruby.rb
|
|
@@ -210,20 +177,16 @@ files:
|
|
|
210
177
|
- lib/iruby/logger.rb
|
|
211
178
|
- lib/iruby/ostream.rb
|
|
212
179
|
- lib/iruby/session.rb
|
|
213
|
-
- lib/iruby/session/cztop.rb
|
|
214
|
-
- lib/iruby/session/ffi_rzmq.rb
|
|
215
|
-
- lib/iruby/session/mixin.rb
|
|
216
180
|
- lib/iruby/session_adapter.rb
|
|
217
181
|
- lib/iruby/session_adapter/cztop_adapter.rb
|
|
218
182
|
- lib/iruby/session_adapter/ffirzmq_adapter.rb
|
|
219
183
|
- lib/iruby/session_adapter/test_adapter.rb
|
|
184
|
+
- lib/iruby/session_serializer.rb
|
|
220
185
|
- lib/iruby/utils.rb
|
|
221
186
|
- lib/iruby/version.rb
|
|
222
187
|
- logo/logo-32x32.png
|
|
223
188
|
- logo/logo-64x64.png
|
|
224
189
|
- logo/ruby.svg
|
|
225
|
-
- run-test.sh
|
|
226
|
-
- tasks/ci.rake
|
|
227
190
|
- test/helper.rb
|
|
228
191
|
- test/integration_test.rb
|
|
229
192
|
- test/iruby/application/application_test.rb
|
|
@@ -251,7 +214,6 @@ licenses:
|
|
|
251
214
|
- MIT
|
|
252
215
|
metadata:
|
|
253
216
|
msys2_mingw_dependencies: zeromq
|
|
254
|
-
post_install_message:
|
|
255
217
|
rdoc_options: []
|
|
256
218
|
require_paths:
|
|
257
219
|
- lib
|
|
@@ -271,8 +233,7 @@ requirements:
|
|
|
271
233
|
- 'system: libzmq: freebsd: libzmq4'
|
|
272
234
|
- 'system: libzmq: homebrew: zmq'
|
|
273
235
|
- 'system: libzmq: macports: zmq'
|
|
274
|
-
rubygems_version:
|
|
275
|
-
signing_key:
|
|
236
|
+
rubygems_version: 4.0.10
|
|
276
237
|
specification_version: 4
|
|
277
238
|
summary: Ruby Kernel for Jupyter
|
|
278
239
|
test_files:
|
data/ci/Dockerfile.base.erb
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
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/Dockerfile.main.erb
DELETED
data/ci/requirements.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
jupyter-console>=6.0.0
|
data/docker/setup.sh
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
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
DELETED
data/lib/iruby/session/cztop.rb
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
require 'cztop'
|
|
2
|
-
|
|
3
|
-
module IRuby
|
|
4
|
-
class Session
|
|
5
|
-
include SessionSerialize
|
|
6
|
-
|
|
7
|
-
def initialize(config)
|
|
8
|
-
connection = "#{config['transport']}://#{config['ip']}:%d"
|
|
9
|
-
|
|
10
|
-
reply_socket = CZTop::Socket::ROUTER.new(connection % config['shell_port'])
|
|
11
|
-
pub_socket = CZTop::Socket::PUB.new(connection % config['iopub_port'])
|
|
12
|
-
stdin_socket = CZTop::Socket::ROUTER.new(connection % config['stdin_port'])
|
|
13
|
-
|
|
14
|
-
Thread.new do
|
|
15
|
-
begin
|
|
16
|
-
hb_socket = CZTop::Socket::REP.new(connection % config['hb_port'])
|
|
17
|
-
loop do
|
|
18
|
-
message = hb_socket.receive
|
|
19
|
-
hb_socket << message
|
|
20
|
-
end
|
|
21
|
-
rescue Exception => e
|
|
22
|
-
IRuby.logger.fatal "Kernel heartbeat died: #{e.message}\n#{e.backtrace.join("\n")}"
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
@sockets = {
|
|
27
|
-
publish: pub_socket,
|
|
28
|
-
reply: reply_socket,
|
|
29
|
-
stdin: stdin_socket,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
@session = SecureRandom.uuid
|
|
33
|
-
unless config['key'].to_s.empty? || config['signature_scheme'].to_s.empty?
|
|
34
|
-
raise 'Unknown signature scheme' unless config['signature_scheme'] =~ /\Ahmac-(.*)\Z/
|
|
35
|
-
@hmac = OpenSSL::HMAC.new(config['key'], OpenSSL::Digest.new($1))
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def description
|
|
40
|
-
'old-stle session using cztop'
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Build and send a message
|
|
44
|
-
def send(socket, type, content)
|
|
45
|
-
idents =
|
|
46
|
-
if socket == :reply && @last_recvd_msg
|
|
47
|
-
@last_recvd_msg[:idents]
|
|
48
|
-
else
|
|
49
|
-
type == :stream ? "stream.#{content[:name]}" : type
|
|
50
|
-
end
|
|
51
|
-
header = {
|
|
52
|
-
msg_type: type,
|
|
53
|
-
msg_id: SecureRandom.uuid,
|
|
54
|
-
username: 'kernel',
|
|
55
|
-
session: @session,
|
|
56
|
-
version: '5.0'
|
|
57
|
-
}
|
|
58
|
-
@sockets[socket] << serialize(idents, header, content)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Receive a message and decode it
|
|
62
|
-
def recv(socket)
|
|
63
|
-
@last_recvd_msg = unserialize(@sockets[socket].receive)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def recv_input
|
|
67
|
-
unserialize(@sockets[:stdin].receive)[:content]["value"]
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
require 'ffi-rzmq'
|
|
2
|
-
|
|
3
|
-
module IRuby
|
|
4
|
-
class Session
|
|
5
|
-
include SessionSerialize
|
|
6
|
-
|
|
7
|
-
def initialize(config)
|
|
8
|
-
c = ZMQ::Context.new
|
|
9
|
-
|
|
10
|
-
connection = "#{config['transport']}://#{config['ip']}:%d"
|
|
11
|
-
reply_socket = c.socket(ZMQ::XREP)
|
|
12
|
-
reply_socket.bind(connection % config['shell_port'])
|
|
13
|
-
|
|
14
|
-
pub_socket = c.socket(ZMQ::PUB)
|
|
15
|
-
pub_socket.bind(connection % config['iopub_port'])
|
|
16
|
-
|
|
17
|
-
stdin_socket = c.socket(ZMQ::XREP)
|
|
18
|
-
stdin_socket.bind(connection % config['stdin_port'])
|
|
19
|
-
|
|
20
|
-
Thread.new do
|
|
21
|
-
begin
|
|
22
|
-
hb_socket = c.socket(ZMQ::REP)
|
|
23
|
-
hb_socket.bind(connection % config['hb_port'])
|
|
24
|
-
ZMQ::Device.new(hb_socket, hb_socket)
|
|
25
|
-
rescue Exception => e
|
|
26
|
-
IRuby.logger.fatal "Kernel heartbeat died: #{e.message}\n#{e.backtrace.join("\n")}"
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
@sockets = {
|
|
31
|
-
publish: pub_socket, reply: reply_socket, stdin: stdin_socket
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@session = SecureRandom.uuid
|
|
35
|
-
unless config['key'].to_s.empty? || config['signature_scheme'].to_s.empty?
|
|
36
|
-
raise 'Unknown signature scheme' unless config['signature_scheme'] =~ /\Ahmac-(.*)\Z/
|
|
37
|
-
@hmac = OpenSSL::HMAC.new(config['key'], OpenSSL::Digest.new($1))
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# Build and send a message
|
|
42
|
-
def send(socket, type, content)
|
|
43
|
-
idents =
|
|
44
|
-
if socket == :reply && @last_recvd_msg
|
|
45
|
-
@last_recvd_msg[:idents]
|
|
46
|
-
else
|
|
47
|
-
type == :stream ? "stream.#{content[:name]}" : type
|
|
48
|
-
end
|
|
49
|
-
header = {
|
|
50
|
-
msg_type: type,
|
|
51
|
-
msg_id: SecureRandom.uuid,
|
|
52
|
-
username: 'kernel',
|
|
53
|
-
session: @session,
|
|
54
|
-
version: '5.0'
|
|
55
|
-
}
|
|
56
|
-
socket = @sockets[socket]
|
|
57
|
-
list = serialize(idents, header, content)
|
|
58
|
-
list.each_with_index do |part, i|
|
|
59
|
-
socket.send_string(part, i == list.size - 1 ? 0 : ZMQ::SNDMORE)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Receive a message and decode it
|
|
64
|
-
def recv(socket)
|
|
65
|
-
socket = @sockets[socket]
|
|
66
|
-
msg = []
|
|
67
|
-
while msg.empty? || socket.more_parts?
|
|
68
|
-
begin
|
|
69
|
-
frame = ''
|
|
70
|
-
rc = socket.recv_string(frame)
|
|
71
|
-
ZMQ::Util.error_check('zmq_msg_send', rc)
|
|
72
|
-
msg << frame
|
|
73
|
-
rescue
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
@last_recvd_msg = unserialize(msg)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def recv_input
|
|
81
|
-
last_recvd_msg = @last_recvd_msg
|
|
82
|
-
input = recv(:stdin)[:content]["value"]
|
|
83
|
-
@last_recvd_msg = last_recvd_msg
|
|
84
|
-
input
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
data/run-test.sh
DELETED
data/tasks/ci.rake
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
namespace :ci do
|
|
2
|
-
namespace :docker do
|
|
3
|
-
def ruby_version
|
|
4
|
-
@ruby_version ||= ENV['ruby_version']
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
def ruby_image_name
|
|
8
|
-
@ruby_image_name ||= "rubylang/ruby:#{ruby_version}-bionic"
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def iruby_test_base_image_name
|
|
12
|
-
@iruby_test_base_image_name ||= "iruby-test-base:ruby-#{ruby_version}"
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def iruby_test_image_name
|
|
16
|
-
@docker_image_name ||= begin
|
|
17
|
-
"sciruby/iruby-test:ruby-#{ruby_version}"
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def docker_image_found?(image_name)
|
|
22
|
-
image_id = `docker images -q #{image_name}`.chomp
|
|
23
|
-
image_id.length > 0
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
directory 'tmp'
|
|
27
|
-
|
|
28
|
-
desc "Build iruby-test-base docker image"
|
|
29
|
-
task :build_test_base_image => 'tmp' do
|
|
30
|
-
unless docker_image_found?(iruby_test_base_image_name)
|
|
31
|
-
require 'erb'
|
|
32
|
-
dockerfile_content = ERB.new(File.read('ci/Dockerfile.base.erb')).result(binding)
|
|
33
|
-
File.write('tmp/Dockerfile', dockerfile_content)
|
|
34
|
-
sh 'docker', 'build', '-t', iruby_test_base_image_name, '-f', 'tmp/Dockerfile', '.'
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
desc "Pull docker image of ruby"
|
|
39
|
-
task :pull_ruby_image do
|
|
40
|
-
sh 'docker', 'pull', ruby_image_name
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
desc "Build iruby-test docker image"
|
|
44
|
-
task :build_test_image => 'tmp' do
|
|
45
|
-
require 'erb'
|
|
46
|
-
dockerfile_content = ERB.new(File.read('ci/Dockerfile.main.erb')).result(binding)
|
|
47
|
-
File.write('tmp/Dockerfile', dockerfile_content)
|
|
48
|
-
sh 'docker', 'build', '-t', iruby_test_image_name, '-f', 'tmp/Dockerfile', '.'
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
desc 'before_install script for CI with Docker'
|
|
52
|
-
task :before_install => :pull_ruby_image
|
|
53
|
-
task :before_install => :build_test_base_image
|
|
54
|
-
|
|
55
|
-
desc 'install script for CI with Docker'
|
|
56
|
-
task :install => :build_test_image
|
|
57
|
-
|
|
58
|
-
desc 'main script for CI with Docker'
|
|
59
|
-
task :script do
|
|
60
|
-
volumes = ['-v', "#{Dir.pwd}:/iruby"] if ENV['attach_pwd']
|
|
61
|
-
sh 'docker', 'run', '--rm', '-it', *volumes,
|
|
62
|
-
iruby_test_image_name, 'bash', 'run-test.sh'
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|