iruby 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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