irails 0.1.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.
@@ -0,0 +1,103 @@
1
+ module IRails
2
+ class Session
3
+ DELIM = '<IDS|MSG>'
4
+
5
+ def initialize(config)
6
+ c = ZMQ::Context.new
7
+
8
+ connection = "#{config['transport']}://#{config['ip']}:%d"
9
+ reply_socket = c.socket(:ROUTER)
10
+ reply_socket.bind(connection % config['shell_port'])
11
+
12
+ pub_socket = c.socket(:PUB)
13
+ pub_socket.bind(connection % config['iopub_port'])
14
+
15
+ Thread.new do
16
+ begin
17
+ hb_socket = c.socket(:REP)
18
+ hb_socket.bind(connection % config['hb_port'])
19
+ ZMQ.proxy(hb_socket, hb_socket)
20
+ rescue Exception => e
21
+ IRails.logger.fatal "Kernel heartbeat died: #{e.message}\n#{e.backtrace.join("\n")}"
22
+ end
23
+ end
24
+
25
+ @sockets = { publish: pub_socket, reply: reply_socket }
26
+ @session = SecureRandom.uuid
27
+ unless config['key'].to_s.empty? || config['signature_scheme'].to_s.empty?
28
+ raise 'Unknown signature scheme' unless config['signature_scheme'] =~ /\Ahmac-(.*)\Z/
29
+ @hmac = OpenSSL::HMAC.new(config['key'], OpenSSL::Digest.new($1))
30
+ end
31
+
32
+ require './config/boot'
33
+ require './config/application'
34
+
35
+ Rails.application.require_environment!
36
+ end
37
+
38
+ # Build and send a message
39
+ def send(socket, type, content)
40
+ idents =
41
+ if socket == :reply && @last_recvd_msg
42
+ @last_recvd_msg[:idents]
43
+ else
44
+ type == :stream ? "stream.#{content[:name]}" : type
45
+ end
46
+ header = {
47
+ msg_type: type,
48
+ msg_id: SecureRandom.uuid,
49
+ username: 'kernel',
50
+ session: @session,
51
+ version: '5.0'
52
+ }
53
+ @sockets[socket].send_message(serialize(idents, header, content))
54
+ end
55
+
56
+ # Receive a message and decode it
57
+ def recv(socket)
58
+ @last_recvd_msg = unserialize(@sockets[socket].recv_message)
59
+ end
60
+
61
+ private
62
+
63
+ def serialize(idents, header, content)
64
+ msg = [MultiJson.dump(header),
65
+ MultiJson.dump(@last_recvd_msg ? @last_recvd_msg[:header] : {}),
66
+ '{}',
67
+ MultiJson.dump(content || {})]
68
+ frames = ([*idents].compact.map(&:to_s) << DELIM << sign(msg)) + msg
69
+ IRails.logger.debug "Sent #{frames.inspect}"
70
+ ZMQ::Message(*frames)
71
+ end
72
+
73
+ def unserialize(msg)
74
+ raise 'no message received' unless msg
75
+ frames = msg.to_a.map(&:to_s)
76
+ IRails.logger.debug "Received #{frames.inspect}"
77
+
78
+ i = frames.index(DELIM)
79
+ idents, msg_list = frames[0..i-1], frames[i+1..-1]
80
+
81
+ minlen = 5
82
+ raise 'malformed message, must have at least #{minlen} elements' unless msg_list.length >= minlen
83
+ s, header, parent_header, metadata, content, buffers = *msg_list
84
+ raise 'Invalid signature' unless s == sign(msg_list[1..-1])
85
+ {
86
+ idents: idents,
87
+ header: MultiJson.load(header),
88
+ parent_header: MultiJson.load(parent_header),
89
+ metadata: MultiJson.load(metadata),
90
+ content: MultiJson.load(content),
91
+ buffers: buffers
92
+ }
93
+ end
94
+
95
+ # Sign using HMAC
96
+ def sign(list)
97
+ return '' unless @hmac
98
+ @hmac.reset
99
+ list.each {|m| @hmac.update(m) }
100
+ @hmac.hexdigest
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,41 @@
1
+ module IRails
2
+ module Utils
3
+ def convert(object, options)
4
+ Display.convert(object, options)
5
+ end
6
+
7
+ def display(obj, options = {})
8
+ Kernel.instance.session.send(:publish, :display_data,
9
+ data: Display.display(obj, options),
10
+ metadata: {},
11
+ source: 'ruby') unless obj.nil?
12
+ end
13
+
14
+ def table(s, **options)
15
+ html(HTML.table(s, options))
16
+ end
17
+
18
+ def latex(s)
19
+ convert(s, mime: 'text/latex')
20
+ end
21
+ alias tex latex
22
+
23
+ def math(s)
24
+ convert("$$#{s}$$", mime: 'text/latex')
25
+ end
26
+
27
+ def html(s)
28
+ convert(s, mime: 'text/html')
29
+ end
30
+
31
+ def javascript(s)
32
+ convert(s, mime: 'application/javascript')
33
+ end
34
+
35
+ def svg(s)
36
+ convert(s, mime: 'image/svg+xml')
37
+ end
38
+ end
39
+
40
+ extend Utils
41
+ end
@@ -0,0 +1,3 @@
1
+ module IRails
2
+ VERSION = '0.1.0'
3
+ end
data/lib/irails.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'rbczmq'
2
+ require 'mimemagic'
3
+ require 'multi_json'
4
+ require 'securerandom'
5
+ require 'openssl'
6
+ require 'tempfile'
7
+ require 'set'
8
+ require 'irails/version'
9
+ require 'irails/kernel'
10
+ require 'irails/backend'
11
+ require 'irails/session'
12
+ require 'irails/ostream'
13
+ require 'irails/formatter'
14
+ require 'irails/utils'
15
+ require 'irails/display'
16
+ require 'irails/comm'
Binary file
Binary file