iruby 0.4.0 → 0.5.0

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ubuntu.yml +62 -0
  3. data/CHANGES +24 -0
  4. data/Gemfile +0 -2
  5. data/LICENSE +1 -1
  6. data/README.md +66 -62
  7. data/Rakefile +10 -10
  8. data/ci/Dockerfile.main.erb +1 -3
  9. data/iruby.gemspec +13 -19
  10. data/lib/iruby.rb +2 -6
  11. data/lib/iruby/backend.rb +19 -5
  12. data/lib/iruby/display.rb +57 -41
  13. data/lib/iruby/formatter.rb +3 -3
  14. data/lib/iruby/input.rb +6 -6
  15. data/lib/iruby/input/autoload.rb +1 -1
  16. data/lib/iruby/input/builder.rb +4 -4
  17. data/lib/iruby/input/button.rb +2 -2
  18. data/lib/iruby/input/cancel.rb +1 -1
  19. data/lib/iruby/input/checkbox.rb +3 -3
  20. data/lib/iruby/input/date.rb +3 -3
  21. data/lib/iruby/input/field.rb +2 -2
  22. data/lib/iruby/input/file.rb +3 -3
  23. data/lib/iruby/input/form.rb +6 -6
  24. data/lib/iruby/input/label.rb +4 -4
  25. data/lib/iruby/input/multiple.rb +10 -10
  26. data/lib/iruby/input/popup.rb +2 -2
  27. data/lib/iruby/input/radio.rb +6 -6
  28. data/lib/iruby/input/select.rb +8 -8
  29. data/lib/iruby/input/textarea.rb +1 -1
  30. data/lib/iruby/input/widget.rb +2 -2
  31. data/lib/iruby/jupyter.rb +1 -0
  32. data/lib/iruby/kernel.rb +18 -13
  33. data/lib/iruby/ostream.rb +22 -10
  34. data/lib/iruby/session_adapter.rb +1 -3
  35. data/lib/iruby/session_adapter/pyzmq_adapter.rb +11 -10
  36. data/lib/iruby/utils.rb +4 -0
  37. data/lib/iruby/version.rb +1 -1
  38. data/run-test.sh +1 -1
  39. data/test/helper.rb +90 -0
  40. data/test/integration_test.rb +1 -2
  41. data/test/iruby/backend_test.rb +37 -0
  42. data/test/iruby/command_test.rb +0 -1
  43. data/test/iruby/jupyter_test.rb +0 -1
  44. data/test/iruby/mime_test.rb +32 -0
  45. data/test/iruby/multi_logger_test.rb +0 -1
  46. data/test/iruby/session_adapter/cztop_adapter_test.rb +1 -1
  47. data/test/iruby/session_adapter/ffirzmq_adapter_test.rb +1 -1
  48. data/test/iruby/session_adapter/session_adapter_test_base.rb +1 -3
  49. data/test/iruby/session_adapter_test.rb +42 -67
  50. data/test/iruby/session_test.rb +9 -15
  51. data/test/run-test.rb +18 -0
  52. metadata +68 -64
  53. data/.travis.yml +0 -41
  54. data/CONTRIBUTORS +0 -19
  55. data/lib/iruby/session/rbczmq.rb +0 -72
  56. data/lib/iruby/session_adapter/rbczmq_adapter.rb +0 -33
  57. data/test/iruby/session_adapter/rbczmq_adapter_test.rb +0 -37
  58. data/test/test_helper.rb +0 -48
data/lib/iruby/display.rb CHANGED
@@ -11,7 +11,10 @@ module IRuby
11
11
  obj = obj.object
12
12
 
13
13
  fuzzy_mime = options[:format] # Treated like a fuzzy mime type
14
- raise 'Invalid argument :format' unless !fuzzy_mime || String === fuzzy_mime
14
+ unless !fuzzy_mime || String === fuzzy_mime
15
+ raise 'Invalid argument :format'
16
+ end
17
+
15
18
  if exact_mime = options[:mime]
16
19
  raise 'Invalid argument :mime' unless String === exact_mime
17
20
  raise 'Invalid mime type' unless exact_mime.include?('/')
@@ -27,32 +30,38 @@ module IRuby
27
30
 
28
31
  # As a last resort, interpret string representation of the object
29
32
  # as the given mime type.
30
- data[exact_mime] = protect(exact_mime, obj) if exact_mime && !data.any? {|m,_| exact_mime == m }
33
+ if exact_mime && data.none? { |m, _| exact_mime == m }
34
+ data[exact_mime] = protect(exact_mime, obj)
35
+ end
31
36
 
32
37
  data
33
38
  end
34
39
 
35
- def clear_output(wait=false)
36
- IRuby::Kernel.instance.session.send(:publish, :clear_output, {wait: wait})
40
+ def clear_output(wait = false)
41
+ IRuby::Kernel.instance.session.send(:publish, :clear_output, wait: wait)
37
42
  end
38
43
 
39
44
  private
40
45
 
41
46
  def protect(mime, data)
42
- MimeMagic.new(mime).text? ? data.to_s : [data.to_s].pack('m0')
47
+ MIME::Type.new(mime).ascii? ? data.to_s : [data.to_s].pack('m0')
43
48
  end
44
49
 
45
50
  def render(data, obj, exact_mime, fuzzy_mime)
46
51
  # Filter matching renderer by object type
47
- renderer = Registry.renderer.select {|r| r.match?(obj) }
52
+ renderer = Registry.renderer.select { |r| r.match?(obj) }
48
53
 
49
54
  matching_renderer = nil
50
55
 
51
56
  # Find exactly matching display by exact_mime
52
- matching_renderer = renderer.find {|r| exact_mime == r.mime } if exact_mime
57
+ if exact_mime
58
+ matching_renderer = renderer.find { |r| exact_mime == r.mime }
59
+ end
53
60
 
54
61
  # Find fuzzy matching display by fuzzy_mime
55
- matching_renderer ||= renderer.find {|r| r.mime && r.mime.include?(fuzzy_mime) } if fuzzy_mime
62
+ if fuzzy_mime
63
+ matching_renderer ||= renderer.find { |r| r.mime&.include?(fuzzy_mime) }
64
+ end
56
65
 
57
66
  renderer.unshift matching_renderer if matching_renderer
58
67
 
@@ -73,7 +82,8 @@ module IRuby
73
82
  attr_reader :object, :options
74
83
 
75
84
  def initialize(object, options)
76
- @object, @options = object, options
85
+ @object = object
86
+ @options = options
77
87
  end
78
88
 
79
89
  class << self
@@ -91,10 +101,13 @@ module IRuby
91
101
  end
92
102
 
93
103
  class Renderer
94
- attr_reader :match, :mime, :render, :priority
104
+ attr_reader :match, :mime, :priority
95
105
 
96
106
  def initialize(match, mime, render, priority)
97
- @match, @mime, @render, @priority = match, mime, render, priority
107
+ @match = match
108
+ @mime = mime
109
+ @render = render
110
+ @priority = priority
98
111
  end
99
112
 
100
113
  def match?(obj)
@@ -114,7 +127,7 @@ module IRuby
114
127
  @renderer ||= []
115
128
  end
116
129
 
117
- SUPPORTED_MIMES = %w(
130
+ SUPPORTED_MIMES = %w[
118
131
  text/plain
119
132
  text/html
120
133
  text/latex
@@ -122,7 +135,8 @@ module IRuby
122
135
  application/javascript
123
136
  image/png
124
137
  image/jpeg
125
- image/svg+xml)
138
+ image/svg+xml
139
+ ]
126
140
 
127
141
  def match(&block)
128
142
  @match = block
@@ -131,7 +145,7 @@ module IRuby
131
145
  end
132
146
 
133
147
  def respond_to(name)
134
- match {|obj| obj.respond_to?(name) }
148
+ match { |obj| obj.respond_to?(name) }
135
149
  end
136
150
 
137
151
  def type(&block)
@@ -153,7 +167,7 @@ module IRuby
153
167
 
154
168
  def format(mime = nil, &block)
155
169
  renderer << Renderer.new(@match, mime, block, @priority)
156
- renderer.sort_by! {|r| -r.priority }
170
+ renderer.sort_by! { |r| -r.priority }
157
171
 
158
172
  # Decrease priority implicitly for all formats
159
173
  # which are added later for a type.
@@ -170,6 +184,7 @@ module IRuby
170
184
  end
171
185
 
172
186
  type { Numo::NArray }
187
+ format 'text/plain', &:inspect
173
188
  format 'text/latex' do |obj|
174
189
  obj.ndim == 2 ?
175
190
  LaTeX.matrix(obj, obj.shape[0], obj.shape[1]) :
@@ -180,6 +195,7 @@ module IRuby
180
195
  end
181
196
 
182
197
  type { NArray }
198
+ format 'text/plain', &:inspect
183
199
  format 'text/latex' do |obj|
184
200
  obj.dim == 2 ?
185
201
  LaTeX.matrix(obj.transpose(1, 0), obj.shape[1], obj.shape[0]) :
@@ -241,37 +257,41 @@ module IRuby
241
257
 
242
258
  match do |obj|
243
259
  defined?(Magick::Image) && Magick::Image === obj ||
244
- defined?(MiniMagick::Image) && MiniMagick::Image === obj
260
+ defined?(MiniMagick::Image) && MiniMagick::Image === obj
245
261
  end
246
262
  format 'image' do |obj|
247
263
  format = obj.format || 'PNG'
248
- [format == 'PNG' ? 'image/png' : 'image/jpeg', obj.to_blob {|i| i.format = format }]
264
+ [format == 'PNG' ? 'image/png' : 'image/jpeg', obj.to_blob { |i| i.format = format }]
249
265
  end
250
266
 
251
- type { Gruff::Base }
252
- format 'image/png' do |obj|
253
- obj.to_blob
267
+ match do |obj|
268
+ defined?(Vips::Image) && Vips::Image === obj
254
269
  end
270
+ format do |obj|
271
+ # handles Vips::Error, vips_image_get: field "vips-loader" not found
272
+ loader = obj.get('vips-loader') rescue nil
273
+ if loader == 'jpegload'
274
+ ['image/jpeg', obj.write_to_buffer('.jpg')]
275
+ else
276
+ # falls back to png for other/unknown types
277
+ ['image/png', obj.write_to_buffer('.png')]
278
+ end
279
+ end
280
+
281
+ type { Gruff::Base }
282
+ format 'image/png', &:to_blob
255
283
 
256
284
  respond_to :to_html
257
- format 'text/html' do |obj|
258
- obj.to_html
259
- end
285
+ format 'text/html', &:to_html
260
286
 
261
287
  respond_to :to_latex
262
- format 'text/latex' do |obj|
263
- obj.to_latex
264
- end
288
+ format 'text/latex', &:to_latex
265
289
 
266
290
  respond_to :to_tex
267
- format 'text/latex' do |obj|
268
- obj.to_tex
269
- end
291
+ format 'text/latex', &:to_tex
270
292
 
271
293
  respond_to :to_javascript
272
- format 'text/javascript' do |obj|
273
- obj.to_javascript
274
- end
294
+ format 'text/javascript', &:to_javascript
275
295
 
276
296
  respond_to :to_svg
277
297
  format 'image/svg+xml' do |obj|
@@ -280,21 +300,17 @@ module IRuby
280
300
  end
281
301
 
282
302
  respond_to :to_iruby
283
- format do |obj|
284
- obj.to_iruby
285
- end
303
+ format(&:to_iruby)
286
304
 
287
- match {|obj| obj.respond_to?(:path) && File.readable?(obj.path) }
305
+ match { |obj| obj.respond_to?(:path) && obj.method(:path).arity == 0 && File.readable?(obj.path) }
288
306
  format do |obj|
289
- mime = MimeMagic.by_path(obj.path).to_s
307
+ mime = MIME::Types.of(obj.path).first.to_s
290
308
  [mime, File.read(obj.path)] if SUPPORTED_MIMES.include?(mime)
291
309
  end
292
310
 
293
311
  type { Object }
294
- priority -1000
295
- format 'text/plain' do |obj|
296
- obj.inspect
297
- end
312
+ priority(-1000)
313
+ format 'text/plain', &:inspect
298
314
  end
299
315
  end
300
316
  end
@@ -78,16 +78,16 @@ module IRuby
78
78
 
79
79
  if maxcols && keys.size > maxcols
80
80
  keys1 = keys[0...maxcols / 2]
81
- keys2 = keys[-maxcols / 2...-1]
81
+ keys2 = keys[-maxcols / 2 + 1..-1]
82
82
  if header
83
83
  header1 = header[0...maxcols / 2]
84
- header2 = header[-maxcols / 2...-1]
84
+ header2 = header[-maxcols / 2 + 1..-1]
85
85
  end
86
86
  end
87
87
 
88
88
  if maxrows && rows.size > maxrows
89
89
  rows1 = rows[0...maxrows / 2]
90
- rows2 = rows[-maxrows / 2...-1]
90
+ rows2 = rows[-maxrows / 2 + 1..-1]
91
91
  end
92
92
 
93
93
  table = '<table>'
data/lib/iruby/input.rb CHANGED
@@ -15,21 +15,21 @@ module IRuby
15
15
  end
16
16
 
17
17
  def form &block
18
- builder = Builder.new &block
18
+ builder = Builder.new(&block)
19
19
  form = InputForm.new(
20
- fields: builder.fields,
20
+ fields: builder.fields,
21
21
  buttons: builder.buttons
22
22
  )
23
23
  form.widget_display
24
24
  builder.process_result form.submit
25
25
  end
26
-
26
+
27
27
  def popup title='Input', &block
28
- builder = Builder.new &block
28
+ builder = Builder.new(&block)
29
29
  form = InputForm.new fields: builder.fields
30
30
  popup = Popup.new(
31
- title: title,
32
- form: form,
31
+ title: title,
32
+ form: form,
33
33
  buttons: builder.buttons
34
34
  )
35
35
  popup.widget_display
@@ -2,7 +2,7 @@ begin
2
2
  require 'erector'
3
3
  rescue LoadError
4
4
  raise LoadError, <<-ERROR.gsub(/\s+/,' ')
5
- IRuby::Input requires the erector gem.
5
+ IRuby::Input requires the erector gem.
6
6
  `gem install erector` or add `gem 'erector'`
7
7
  it to your Gemfile to continue.
8
8
  ERROR
@@ -21,7 +21,7 @@ module IRuby
21
21
  def html &block
22
22
  add_field Class.new(Widget) {
23
23
  define_method(:widget_html) { instance_eval &block }
24
- }.new
24
+ }.new
25
25
  end
26
26
 
27
27
  def text string
@@ -44,7 +44,7 @@ module IRuby
44
44
  end
45
45
  end
46
46
 
47
- private
47
+ private
48
48
 
49
49
  def process key, &block
50
50
  @processors[key.to_s] = block
@@ -52,14 +52,14 @@ module IRuby
52
52
 
53
53
  def unique_key key
54
54
  @keys ||= []
55
-
55
+
56
56
  if @keys.include? key
57
57
  (2..Float::INFINITY).each do |i|
58
58
  test = "#{key}#{i}"
59
59
  break key = test unless @keys.include? test
60
60
  end
61
61
  end
62
-
62
+
63
63
  @keys << key; key
64
64
  end
65
65
  end
@@ -10,7 +10,7 @@ module IRuby
10
10
  green: 'success',
11
11
  aqua: 'info',
12
12
  orange: 'warning',
13
- red: 'danger',
13
+ red: 'danger',
14
14
  none: 'link'
15
15
  }
16
16
 
@@ -37,7 +37,7 @@ module IRuby
37
37
  def widget_html
38
38
  button(
39
39
  @label || to_label(@key),
40
- type: 'button',
40
+ type: 'button',
41
41
  :'data-iruby-key' => @key,
42
42
  class: "btn btn-#{COLORS[@color]} pull-right #{@js_class}"
43
43
  )
@@ -22,7 +22,7 @@ module IRuby
22
22
  def widget_html
23
23
  button(
24
24
  @label,
25
- type: 'button',
25
+ type: 'button',
26
26
  :'data-dismiss' => 'modal',
27
27
  class: "btn btn-danger pull-right iruby-cancel"
28
28
  )
@@ -56,10 +56,10 @@ module IRuby
56
56
  widget_label do
57
57
  div **params do
58
58
  @options.each do |option|
59
- label class: 'checkbox-inline' do
59
+ label class: 'checkbox-inline' do
60
60
  input(
61
- name: @key,
62
- value: option,
61
+ name: @key,
62
+ value: option,
63
63
  type: 'checkbox',
64
64
  checked: @default.include?(option)
65
65
  )
@@ -6,7 +6,7 @@ module IRuby
6
6
  builder :date do |key='date', **params|
7
7
  params[:default] ||= false
8
8
  params[:key] = unique_key key
9
-
9
+
10
10
  if params[:default].is_a? Time
11
11
  params[:default] = params[:default].strftime('%m/%d/%Y')
12
12
  end
@@ -22,13 +22,13 @@ module IRuby
22
22
  '#ui-datepicker-div { z-index: 2000 !important; }'
23
23
  end
24
24
 
25
- def widget_js
25
+ def widget_js
26
26
  <<-JS
27
27
  $('.iruby-date').datepicker({
28
28
  dateFormat: 'mm/dd/yy',
29
29
  onClose: function(date) {
30
30
  $(this).data('iruby-value', date);
31
- }
31
+ }
32
32
  });
33
33
  JS
34
34
  end
@@ -17,9 +17,9 @@ module IRuby
17
17
  end
18
18
 
19
19
  def widget_html
20
- widget_label do
20
+ widget_label do
21
21
  input(
22
- type: @type,
22
+ type: @type,
23
23
  :'data-iruby-key' => @key,
24
24
  class: "form-control #{@js_class}",
25
25
  value: @default
@@ -13,10 +13,10 @@ module IRuby
13
13
 
14
14
  # get rid of Chrome's silly path
15
15
  name = value['name'].sub('C:\\fakepath\\','')
16
-
16
+
17
17
  result[key.to_sym] = {
18
18
  name: name,
19
- data: uri.data,
19
+ data: uri.data,
20
20
  content_type: uri.content_type
21
21
  }
22
22
  end
@@ -46,7 +46,7 @@ module IRuby
46
46
  def widget_html
47
47
  widget_label do
48
48
  input(
49
- type: 'file',
49
+ type: 'file',
50
50
  :'data-iruby-key' => @key,
51
51
  class: 'form-control iruby-file'
52
52
  )
@@ -5,7 +5,7 @@ module IRuby
5
5
  class InputForm < Widget
6
6
  needs :fields, buttons: []
7
7
 
8
- def widget_js
8
+ def widget_js
9
9
  javascript = <<-JS
10
10
  var remove = function () {
11
11
  Jupyter.notebook.kernel.send_input_reply(
@@ -14,7 +14,7 @@ module IRuby
14
14
  })
15
15
  );
16
16
  };
17
-
17
+
18
18
  $("#iruby-form").on("remove", remove);
19
19
 
20
20
  $('#iruby-form').submit(function() {
@@ -33,16 +33,16 @@ module IRuby
33
33
  Jupyter.notebook.kernel.send_input_reply(
34
34
  JSON.stringify({'#{@id}': result})
35
35
  );
36
-
36
+
37
37
  $(this).remove();
38
38
  return false;
39
39
  });
40
40
 
41
41
  $('#iruby-form').keydown(function(event) {
42
- if (event.keyCode == 13 && !event.shiftKey) {
42
+ if (event.keyCode == 13 && !event.shiftKey) {
43
43
  $('#iruby-form').submit();
44
- } else if (event.keyCode == 27) {
45
- $('#iruby-form').remove();
44
+ } else if (event.keyCode == 27) {
45
+ $('#iruby-form').remove();
46
46
  }
47
47
  });
48
48
  JS