jnv-iruby 0.0.2

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,71 @@
1
+ module IRuby
2
+ class Profile
3
+ attr_accessor :iruby_name
4
+
5
+ IPYTHON_DIR = `ipython locate`.strip
6
+
7
+ # FIXME These should be stored as ERB files
8
+ PROFILE_CONFIG = {}
9
+ PROFILE_CONFIG['ipython_config.py'] = <<-PYTHON
10
+ ### IRuby custom configuration ###
11
+
12
+ c.KernelManager.kernel_cmd = ['iruby_kernel', '{connection_file}']
13
+ #
14
+ ## to autorequire a Ruby file (for loading another project's environment),
15
+ ## add absolute path as third parameter:
16
+ #c.KernelManager.kernel_cmd = ['iruby_kernel', '{connection_file}', '~/my_project/config/boot.rb']
17
+ #
18
+ ## if using Bundler, prepend "bundle exec"
19
+ ## (remember to add 'iruby' to your projects Gemfile)
20
+ #c.KernelManager.kernel_cmd = ['bundle', 'exec', 'iruby_kernel', '{connection_file}', '~/my_project/config/boot.rb']
21
+
22
+ c.Session.key = ''
23
+ PYTHON
24
+
25
+ STATIC_DIR = File.join(File.dirname(__FILE__), '..', '..', 'static')
26
+
27
+ def initialize(iruby_name='ruby')
28
+ @iruby_name = iruby_name
29
+ end
30
+
31
+ def name
32
+ "#{@iruby_name}"
33
+ end
34
+
35
+ def path
36
+ File.join(IPYTHON_DIR, "profile_#{name}")
37
+ end
38
+
39
+ def create!
40
+ run_ipython_create_profile!
41
+ apply_patches!
42
+ create_static_symlink!
43
+ end
44
+
45
+ private
46
+ def run_ipython_create_profile!
47
+ cmd = "ipython profile create '#{name}'"
48
+ puts "=> Run #{cmd}"
49
+ `#{cmd}`
50
+ end
51
+
52
+ def apply_patches!
53
+ # FIXME only append if needed!
54
+ PROFILE_CONFIG.each do |file, config|
55
+ file_path = File.join(path, file)
56
+ puts "=> Append extra configuration to #{file_path}"
57
+ File.open(file_path, 'a') do |f|
58
+ f.write("\n#{config}\n")
59
+ end
60
+ end
61
+ end
62
+
63
+ def create_static_symlink!
64
+ src, dst = File.join(STATIC_DIR), File.join(path, 'static')
65
+ if not File.exists?(dst)
66
+ puts "=> Symlink #{src} to #{dst}"
67
+ File.symlink(src, dst)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,329 @@
1
+ require 'ffi-rzmq'
2
+ require 'uuid'
3
+ require 'json'
4
+
5
+ require 'iruby/message'
6
+
7
+ module IRuby
8
+ class Session
9
+ DELIM = "<IDS|MSG>"
10
+
11
+ def initialize username='jadams'
12
+ @username = username
13
+ @session = UUID.new.generate
14
+ @msg_id = 0
15
+
16
+ @auth = nil
17
+ end
18
+
19
+ def pack(s)
20
+ s.to_json
21
+ end
22
+
23
+ def sign(msg_list)
24
+ """Sign a message with HMAC digest. If no auth, return b''.
25
+
26
+ Parameters
27
+ ----------
28
+ msg_list : list
29
+ The [p_header,p_parent,p_content] part of the message list.
30
+ """
31
+ if @auth.nil?
32
+ return ''
33
+ end
34
+ #h = self.auth.copy()
35
+ #msg_list.each do |m|
36
+ #h.update(m)
37
+ #end
38
+ #return str_to_bytes(h.hexdigest())
39
+ end
40
+
41
+ def msg_header
42
+ h = Message.msg_header(@msg_id, @username, @session)
43
+ @msg_id += 1
44
+ return h
45
+ end
46
+
47
+ def msg(msg_type, content=nil, parent=nil)
48
+ msg = {}
49
+ msg['header'] = msg_header()
50
+ msg['parent_header'] = parent.nil? ? {} : Message.extract_header(parent)
51
+ msg['metadata'] = {}
52
+ msg['header']['msg_type'] = msg_type
53
+ msg['content'] = content || {}
54
+ return msg
55
+ end
56
+
57
+ def send(stream, msg_or_type, content=nil, parent=nil, ident=nil, buffers=nil, subheader=nil, track=false, header=nil)
58
+ """Build and send a message via stream or socket.
59
+
60
+ The message format used by this function internally is as follows:
61
+
62
+ [ident1,ident2,...,DELIM,HMAC,p_header,p_parent,p_content,
63
+ buffer1,buffer2,...]
64
+
65
+ The serialize/unserialize methods convert the nested message dict into this
66
+ format.
67
+
68
+ Parameters
69
+ ----------
70
+
71
+ stream : zmq.Socket or ZMQStream
72
+ The socket-like object used to send the data.
73
+ msg_or_type : str or Message/dict
74
+ Normally, msg_or_type will be a msg_type unless a message is being
75
+ sent more than once. If a header is supplied, this can be set to
76
+ None and the msg_type will be pulled from the header.
77
+
78
+ content : dict or None
79
+ The content of the message (ignored if msg_or_type is a message).
80
+ header : dict or None
81
+ The header dict for the message (ignores if msg_to_type is a message).
82
+ parent : Message or dict or None
83
+ The parent or parent header describing the parent of this message
84
+ (ignored if msg_or_type is a message).
85
+ ident : bytes or list of bytes
86
+ The zmq.IDENTITY routing path.
87
+ subheader : dict or None
88
+ Extra header keys for this message's header (ignored if msg_or_type
89
+ is a message).
90
+ buffers : list or None
91
+ The already-serialized buffers to be appended to the message.
92
+ track : bool
93
+ Whether to track. Only for use with Sockets, because ZMQStream
94
+ objects cannot track messages.
95
+
96
+ Returns
97
+ -------
98
+ msg : dict
99
+ The constructed message.
100
+ (msg,tracker) : (dict, MessageTracker)
101
+ if track=True, then a 2-tuple will be returned,
102
+ the first element being the constructed
103
+ message, and the second being the MessageTracker
104
+
105
+ """
106
+
107
+ if !stream.is_a?(ZMQ::Socket)
108
+ raise "stream must be Socket or ZMQSocket, not %r"%stream.class
109
+ end
110
+
111
+ if msg_or_type.is_a?(Hash)
112
+ msg = msg_or_type
113
+ else
114
+ msg = self.msg(msg_or_type, content, parent)
115
+ end
116
+
117
+ buffers ||= []
118
+ to_send = self.serialize(msg, ident)
119
+ flag = 0
120
+ if buffers.any?
121
+ flag = ZMQ::SNDMORE
122
+ _track = false
123
+ else
124
+ _track=track
125
+ end
126
+ if track
127
+ to_send.each_with_index do |part, i|
128
+ if i == to_send.length - 1
129
+ flag = 0
130
+ else
131
+ flag = ZMQ::SNDMORE
132
+ end
133
+ stream.send_string(part, flag)
134
+ end
135
+ else
136
+ to_send.each_with_index do |part, i|
137
+ if i == to_send.length - 1
138
+ flag = 0
139
+ else
140
+ flag = ZMQ::SNDMORE
141
+ end
142
+ stream.send_string(part, flag)
143
+ end
144
+ end
145
+ # STDOUT.puts '-'*30
146
+ # STDOUT.puts "SENDING"
147
+ # STDOUT.puts to_send
148
+ # STDOUT.puts to_send.length
149
+ # STDOUT.puts '-'*30
150
+
151
+ #buffers.each do |b|
152
+ #stream.send(b, flag, copy=False)
153
+ #end
154
+ #if buffers:
155
+ #if track:
156
+ #tracker = stream.send(buffers[-1], copy=False, track=track)
157
+ #else:
158
+ #tracker = stream.send(buffers[-1], copy=False)
159
+
160
+ # omsg = Message(msg)
161
+ #if self.debug:
162
+ #pprint.pprint(msg)
163
+ #pprint.pprint(to_send)
164
+ #pprint.pprint(buffers)
165
+
166
+ #msg['tracker'] = tracker
167
+
168
+ return msg
169
+ end
170
+
171
+ def recv(socket, mode=ZMQ::NOBLOCK)
172
+ begin
173
+ msg = []
174
+ frame = ""
175
+ rc = socket.recv_string(frame, mode)
176
+ ZMQ::Util.error_check("zmq_msg_send", rc)
177
+
178
+ msg << frame
179
+ while socket.more_parts?
180
+ begin
181
+ frame = ""
182
+ rc = socket.recv_string(frame, mode)
183
+ ZMQ::Util.error_check("zmq_msg_send", rc)
184
+ msg << frame
185
+ rescue
186
+ end
187
+ end
188
+ # Skip everything before DELIM, then munge the three json objects into the
189
+ # one the rest of my code expects
190
+ i = msg.index(DELIM)
191
+ idents = msg[0..i-1]
192
+ msg_list = msg[i+1..-1]
193
+ end
194
+ return idents, unserialize(msg_list)
195
+ end
196
+
197
+ def serialize(msg, ident=nil)
198
+ """Serialize the message components to bytes.
199
+
200
+ This is roughly the inverse of unserialize. The serialize/unserialize
201
+ methods work with full message lists, whereas pack/unpack work with
202
+ the individual message parts in the message list.
203
+
204
+ Parameters
205
+ ----------
206
+ msg : dict or Message
207
+ The nexted message dict as returned by the self.msg method.
208
+
209
+ Returns
210
+ -------
211
+ msg_list : list
212
+ The list of bytes objects to be sent with the format:
213
+ [ident1,ident2,...,DELIM,HMAC,p_header,p_parent,p_content,
214
+ buffer1,buffer2,...]. In this list, the p_* entities are
215
+ the packed or serialized versions, so if JSON is used, these
216
+ are utf8 encoded JSON strings.
217
+ """
218
+ content = msg.fetch('content', {})
219
+ if content.nil?
220
+ content = {}.to_json
221
+ elsif content.is_a?(Hash)
222
+ content = content.to_json
223
+ #elsif isinstance(content, bytes):
224
+ # content is already packed, as in a relayed message
225
+ #pass
226
+ #elsif isinstance(content, unicode):
227
+ # should be bytes, but JSON often spits out unicode
228
+ #content = content.encode('utf8')
229
+ else
230
+ raise "Content incorrect type: %s"%type(content)
231
+ end
232
+
233
+ real_message = [self.pack(msg['header']),
234
+ self.pack(msg['parent_header']),
235
+ self.pack(msg['metadata']),
236
+ self.pack(msg['content']),
237
+ ]
238
+
239
+ to_send = []
240
+
241
+ if ident.is_a?(Array)
242
+ # accept list of idents
243
+ to_send += ident
244
+ elsif !ident.nil?
245
+ to_send << ident
246
+ end
247
+ to_send << DELIM
248
+
249
+ signature = self.sign(real_message)
250
+ to_send << signature
251
+
252
+ to_send += real_message
253
+ # STDOUT.puts to_send
254
+ # STDOUT.puts to_send.length
255
+
256
+ return to_send
257
+ end
258
+
259
+ def unserialize(msg_list, content=true, copy=true)
260
+ =begin
261
+ Unserialize a msg_list to a nested message dict.
262
+ This is roughly the inverse of serialize. The serialize/unserialize
263
+ methods work with full message lists, whereas pack/unpack work with
264
+ the individual message parts in the message list.
265
+
266
+ Parameters:
267
+ -----------
268
+ msg_list : list of bytes or Message objects
269
+ The list of message parts of the form [HMAC,p_header,p_parent,
270
+ p_content,buffer1,buffer2,...].
271
+ content : bool (True)
272
+ Whether to unpack the content dict (True), or leave it packed
273
+ (False).
274
+ copy : bool (True)
275
+ Whether to return the bytes (True), or the non-copying Message
276
+ object in each place (False).
277
+
278
+ Returns
279
+ -------
280
+ msg : dict
281
+ The nested message dict with top-level keys [header, parent_header,
282
+ content, buffers].
283
+ =end
284
+ minlen = 5
285
+ message = {}
286
+ unless copy
287
+ minlen.times do |i|
288
+ msg_list[i] = msg_list[i].bytes
289
+ end
290
+ end
291
+ unless msg_list.length >= minlen
292
+ raise Exception "malformed message, must have at least %i elements"%minlen
293
+ end
294
+ # STDERR.puts msg_list.inspect
295
+ header = msg_list[1]
296
+ message['header'] = JSON.parse(header)
297
+ message['msg_id'] = header['msg_id']
298
+ message['msg_type'] = header['msg_type']
299
+ message['parent_header'] = JSON.parse(msg_list[2])
300
+ message['metadata'] = JSON.parse(msg_list[3])
301
+ if content
302
+ message['content'] = JSON.parse(msg_list[4])
303
+ else
304
+ message['content'] = msg_list[4]
305
+ end
306
+
307
+ message['buffers'] = msg_list[4..-1]
308
+ return message
309
+ end
310
+ end
311
+ end
312
+
313
+ =begin
314
+ def test_msg2obj():
315
+ am = dict(x=1)
316
+ ao = Message(am)
317
+ assert ao.x == am['x']
318
+
319
+ am['y'] = dict(z=1)
320
+ ao = Message(am)
321
+ assert ao.y.z == am['y']['z']
322
+
323
+ k1, k2 = 'y', 'z'
324
+ assert ao[k1][k2] == am[k1][k2]
325
+
326
+ am2 = dict(ao)
327
+ assert am['x'] == am2['x']
328
+ assert am['y']['z'] == am2['y']['z']
329
+ =end
@@ -0,0 +1,3 @@
1
+ module IRuby
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,268 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <svg
3
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
4
+ xmlns:cc="http://creativecommons.org/ns#"
5
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6
+ xmlns:svg="http://www.w3.org/2000/svg"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
9
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
10
+ xml:space="preserve"
11
+ width="1564.3486"
12
+ height="140.88943"
13
+ style="fill-rule:evenodd"
14
+ viewBox="0 0 1564.3486 140.88803"
15
+ id="svg2"
16
+ version="1.1"
17
+ inkscape:version="0.48.4 r9939"
18
+ sodipodi:docname="ipynblogo.svg"
19
+ inkscape:export-filename="ipynblogo.png"
20
+ inkscape:export-xdpi="39.83239"
21
+ inkscape:export-ydpi="39.83239"><metadata
22
+ id="metadata121"><rdf:RDF><cc:Work
23
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
24
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
25
+ pagecolor="#ffffff"
26
+ bordercolor="#666666"
27
+ borderopacity="1"
28
+ objecttolerance="10"
29
+ gridtolerance="10"
30
+ guidetolerance="10"
31
+ inkscape:pageopacity="0"
32
+ inkscape:pageshadow="2"
33
+ inkscape:window-width="1366"
34
+ inkscape:window-height="709"
35
+ id="namedview119"
36
+ showgrid="false"
37
+ showguides="true"
38
+ inkscape:guide-bbox="true"
39
+ inkscape:zoom="0.52458827"
40
+ inkscape:cx="736.80103"
41
+ inkscape:cy="19.84062"
42
+ inkscape:window-x="0"
43
+ inkscape:window-y="27"
44
+ inkscape:window-maximized="1"
45
+ inkscape:current-layer="g3107-3"
46
+ fit-margin-top="0"
47
+ fit-margin-left="0"
48
+ fit-margin-right="0"
49
+ fit-margin-bottom="0"><sodipodi:guide
50
+ orientation="0,1"
51
+ position="314.64428,33.80925"
52
+ id="guide3042" /><sodipodi:guide
53
+ orientation="0,1"
54
+ position="-63.933938,140.7389"
55
+ id="guide3815" /><sodipodi:guide
56
+ orientation="1,0"
57
+ position="-23.444718,305.07749"
58
+ id="guide3817" /></sodipodi:namedview><defs
59
+ id="defs4"><font
60
+ id="FontID0"
61
+ font-variant="normal"
62
+ font-weight="400"
63
+ horiz-origin-x="0"
64
+ horiz-origin-y="0"
65
+ horiz-adv-x="90"
66
+ vert-origin-x="45"
67
+ vert-origin-y="90"
68
+ vert-adv-y="90"
69
+ style="font-variant:normal;font-weight:400"><font-face
70
+ font-family="Droid Sans Mono"
71
+ id="font-face7" /><missing-glyph
72
+ id="missing-glyph9"><path
73
+ d="M0 0z"
74
+ id="path11" /></missing-glyph><glyph
75
+ unicode=" "
76
+ horiz-adv-x="600"
77
+ id="glyph13" /><glyph
78
+ unicode=":"
79
+ horiz-adv-x="600"
80
+ id="glyph15"><path
81
+ d="M299.831 549.838c41.3387,0 62.0033,-22.6678 62.0033,-67.8333 0,-45.3356 -20.6646,-68.0034 -62.0033,-68.0034 -41.3293,0 -61.9939,22.6678 -61.9939,68.0034 0,45.1655 20.6646,67.8333 61.9939,67.8333zm0 -427.834c41.3387,0 62.0033,-22.5072 62.0033,-67.8333 0,-45.5057 -20.6646,-68.3341 -62.0033,-68.3341 -41.3293,0 -61.9939,22.8284 -61.9939,68.3341 0,45.3261 20.6646,67.8333 61.9939,67.8333z"
82
+ id="path17" /></glyph><glyph
83
+ unicode="C"
84
+ horiz-adv-x="600"
85
+ id="glyph19"><path
86
+ d="M548.841 98.1632l0 -79.1712c-47.5084,-19.1621 -105.845,-28.8282 -174.84,-28.8282 -100.488,0 -177.504,32.0029 -230.994,95.8388 -53.3477,63.6657 -79.9932,154.317 -79.9932,271.841 0,112.648 29.14,201.826 87.3065,267.646 58.3366,65.6783 138.018,98.6734 238.846,98.6734 71.6594,0 133.993,-14.0031 187,-42.0092l-38.0124 -76.1664c-50.1446,25.3416 -99.8072,38.0124 -148.988,38.0124 -69.987,0 -125.829,-25.8235 -167.498,-77.3286 -41.669,-51.6753 -62.5035,-121.492 -62.5035,-209.677 0,-93.486 19.5022,-164.664 58.6768,-213.646 39.0045,-49.0107 96.1506,-73.5019 171.325,-73.5019 42.321,0 95.4986,9.496 159.675,28.3179z"
87
+ id="path21" /></glyph><glyph
88
+ unicode="I"
89
+ horiz-adv-x="600"
90
+ id="glyph23"><path
91
+ d="M488.838 0l-379.013 0 0 60.0064 144.001 9.83275 0 574.162 -144.001 9.83275 0 60.0064 379.013 0 0 -60.0064 -143.665 -9.83275 0 -574.162 143.665 -9.83275 0 -60.0064z"
92
+ id="path25" /></glyph><glyph
93
+ unicode="]"
94
+ horiz-adv-x="600"
95
+ id="glyph27"><path
96
+ d="M141.166 -85.0018l168.832 0 0 726.172 -168.832 0 0 72.6616 257.831 0 0 -871.996 -257.831 0 0 73.1624z"
97
+ id="path29" /></glyph><glyph
98
+ unicode="["
99
+ horiz-adv-x="600"
100
+ id="glyph31"><path
101
+ d="M458.997 -158.164l-257.831 0 0 871.996 257.831 0 0 -72.6616 -168.993 0 0 -726.172 168.993 0 0 -73.1624z"
102
+ id="path33" /></glyph><glyph
103
+ unicode="P"
104
+ horiz-adv-x="600"
105
+ id="glyph35"><path
106
+ d="M176.83 277.833l0 -277.833 -90.8334 0 0 713.84 197.169 0c167.334,0 251.01,-69.6797 251.01,-209.004 0,-71.1679 -22.5002,-126.834 -67.6777,-166.997 -45.0004,-40.0043 -110.499,-60.0064 -196.496,-60.0064l-93.172 0zm0 77.1738l83.0026 0c64.3292,0 110.499,11.6576 138.332,35.1676 27.8329,23.3329 41.8291,59.9887 41.8291,109.826 0,90.8334 -54.9926,136.17 -165.155,136.17l-98.0086 0 0 -281.164z"
107
+ id="path37" /></glyph><glyph
108
+ unicode="g"
109
+ horiz-adv-x="600"
110
+ id="glyph39"><path
111
+ d="M549.833 536.17l0 -55.1619 -95.6687 -13.181c21.1747,-27.666 31.6628,-62.3335 31.6628,-104.002 0,-52.4973 -17.3196,-94.1663 -51.9871,-125.319 -34.6675,-31.0108 -82.9979,-46.6863 -144.849,-46.6863 -17.8298,0 -31.8329,1.02047 -41.9808,3.00471 -32.5132,-18.17 -48.8406,-39.8265 -48.8406,-64.998 0,-27.3258 26.3337,-40.9887 78.6609,-40.9887l91.3317 0c56.6642,0 100.006,-12.5007 129.826,-37.5021 30.0187,-25.1715 45.0139,-61.0012 45.0139,-107.489 0,-122.683 -92.012,-184.024 -275.838,-184.024 -71.0074,0 -125.007,13.0109 -161.999,39.1746 -36.8218,26.3337 -55.3319,63.0138 -55.3319,110.182 0,68.9948 39.0045,112.988 117.155,131.81 -31.3226,15.3353 -46.8281,40.3368 -46.8281,75.1743 0,36.51 21.6849,67.8326 64.8279,93.8262 -28.8282,12.0188 -51.6469,32.0029 -68.3145,59.839 -16.4975,27.836 -24.8313,58.1666 -24.8313,90.9916 0,59.3571 17.3196,104.853 51.9871,137.026 34.6675,31.9746 84.0184,47.9902 148.166,47.9902 28.0061,0 52.3272,-3.17478 73.1617,-9.66608l184.676 0zm-259.822 -283.179c72.6515,0 108.991,37.332 108.991,112.166 0,77.8389 -36.6801,116.843 -110.012,116.843 -73.1617,0 -109.813,-39.4864 -109.813,-118.176 0,-73.9838 36.9919,-110.834 110.834,-110.834zm47.8202 -244.146l-91.6719 0c-75.0043,0 -112.336,-32.3431 -112.336,-96.6892 0,-56.6642 44.0218,-84.9821 132.349,-84.9821 128.494,0 192.84,36.3399 192.84,108.821 0,28.6864 -8.19207,48.0186 -24.5195,57.8264 -16.1574,10.0062 -48.5005,15.0235 -96.6608,15.0235z"
112
+ id="path41" /></glyph><glyph
113
+ unicode="m"
114
+ horiz-adv-x="600"
115
+ id="glyph43"><path
116
+ d="M477.011 0l0 345.173c0,47.48 -4.33698,80.6735 -12.8409,99.1553 -8.67396,18.5101 -23.1589,27.836 -43.3415,27.836 -28.3179,0 -48.8406,-13.4928 -61.6532,-40.5068 -12.8409,-26.9857 -19.3322,-72.3114 -19.3322,-135.835l0 -295.822 -78.6893 0 0 345.173c0,84.6703 -20.3243,126.991 -61.0012,126.991 -27.3258,0 -46.8281,-13.0109 -58.4784,-38.8344 -11.8487,-25.8235 -17.6881,-77.6688 -17.6881,-155.508l0 -277.822 -78.9727 0 0 536.17 61.9933 0 13.1527 -72.3397 4.84721 0c21.8266,54.68 54.4815,82.0058 98.1632,82.0058 53.0075,0 87.675,-29.5085 104.002,-88.8372l2.83463 0c24.8313,59.3288 60.491,88.8372 106.979,88.8372 41.669,0 72.0279,-14.9952 90.8498,-45.1556 18.8219,-30.0187 28.3179,-80.3334 28.3179,-150.519l0 -350.162 -79.1428 0z"
117
+ id="path45" /></glyph><glyph
118
+ unicode="i"
119
+ horiz-adv-x="600"
120
+ id="glyph47"><path
121
+ d="M309.173 756.846c34.4974,0 51.6469,-18.5101 51.6469,-55.6721 0,-18.8503 -5.15902,-32.9951 -15.307,-42.1793 -10.3464,-9.32593 -22.5069,-14.0031 -36.3399,-14.0031 -34.8376,0 -52.3272,18.6802 -52.3272,56.1823 0,37.162 17.4897,55.6721 52.3272,55.6721zm-45.0139 -291.003l-131.328 10.148 0 60.1791 220.166 0 0 -466.325 171.835 -9.83616 0 -60.0091 -428.652 0 0 60.0091 167.98 9.83616 0 395.998z"
122
+ id="path49" /></glyph><glyph
123
+ unicode="c"
124
+ horiz-adv-x="600"
125
+ id="glyph51"><path
126
+ d="M518 517.178l-30.1604 -77.1869c-48.8406,18.5101 -92.4939,27.836 -130.846,27.836 -120.84,0 -181.161,-67.3224 -181.161,-201.655 0,-132.179 58.6768,-198.339 176.172,-198.339 51.165,0 103.322,10.1763 156.84,30.3305l0 -78.1507c-43.6816,-19.8424 -97.171,-29.8486 -160.667,-29.8486 -83.6782,0 -148.676,23.6691 -194.852,71.1775 -46.1477,47.3383 -69.335,115.313 -69.335,203.838 0,91.4734 23.6691,161.149 70.8373,208.997 47.1682,47.8202 113.498,71.6594 199.161,71.6594 58.0248,0 112.676,-9.496 164.012,-28.6581z"
127
+ id="path53" /></glyph><glyph
128
+ unicode="a"
129
+ horiz-adv-x="600"
130
+ id="glyph55"><path
131
+ d="M436.986 0l-17.9999 74.1539 -3.99683 0c-25.0014,-31.4927 -50.6548,-53.3193 -77.1586,-65.65 -26.3337,-12.1606 -60.3209,-18.34 -101.99,-18.34 -53.0075,0 -94.6766,14.0031 -124.667,42.0092 -30.1604,28.0061 -45.184,67.3224 -45.184,117.665 0,108.169 82.9979,164.834 249.022,169.993l98.9852 3.34486 0 33.8171c0,76.8468 -39.6564,115.171 -118.998,115.171 -47.9902,0 -101.338,-13.3228 -160.156,-39.9966l-30.8408 66.8405c63.8358,31.3226 126.169,46.8281 187,46.8281 73.8421,0 127.331,-14.1731 160.497,-42.3493 32.9951,-28.3179 49.4926,-73.8137 49.4926,-136.317l0 -367.169 -64.0059 0zm-23.8109 262.175l-79.1712 -3.34486c-63.8358,-2.66455 -108.991,-12.6708 -135.835,-29.9904 -26.6738,-17.518 -39.9966,-44.1635 -39.9966,-79.8515 0,-57.9965 32.6549,-86.9947 97.6529,-86.9947 47.8485,0 86.0026,13.3511 114.519,39.8265 28.488,26.5038 42.8312,63.8358 42.8312,112.024l0 48.3304z"
132
+ id="path57" /></glyph><glyph
133
+ unicode="e"
134
+ horiz-adv-x="600"
135
+ id="glyph59"><path
136
+ d="M535.178 251.006l-377.998 0c2.66455,-122.172 58.6484,-183.174 167.98,-183.174 63.4957,0 123.675,12.3306 180.679,37.162l0 -78.1507c-53.9997,-24.3495 -113.328,-36.6801 -177.674,-36.6801 -79.8231,0 -143.659,24.3495 -191.507,72.9917 -47.8202,48.6706 -71.6594,115.681 -71.6594,201.003 0,86.6829 21.9967,155.168 66.1602,205.851 44.0218,50.6548 103.01,75.8263 177.023,75.8263 68.9948,0 123.987,-21.6566 165.145,-65.3382 41.1871,-43.6533 61.8516,-101.82 61.8516,-174.33l0 -55.1619zm-376.013 72.1696l279.834 0c0,99.3254 -44.3336,148.988 -132.831,148.988 -89.4892,0 -138.5,-49.6627 -147.004,-148.988z"
137
+ id="path61" /></glyph><glyph
138
+ unicode="n"
139
+ horiz-adv-x="600"
140
+ id="glyph63"><path
141
+ d="M433.173 0l0 345.174c0,84.668 -38.835,126.993 -116.345,126.993 -99.8335,0 -149.83,-64.8253 -149.83,-194.334l0 -277.833 -88.8314 0 0 536.16 71.664 0 13.3407 -72.3195 4.83665 0c33.4845,54.6559 88.1582,81.9928 163.986,81.9928 126.674,0 190.011,-65.1619 190.011,-195.663l0 -350.17 -88.8314 0z"
142
+ id="path65" /></glyph><glyph
143
+ unicode="o"
144
+ horiz-adv-x="600"
145
+ id="glyph67"><path
146
+ d="M297.835 -9.83275c-70.3352,0 -128.162,25.3348 -173.499,76.0045 -45.4964,50.6697 -68.1738,118.17 -68.1738,202.82 0,85.6778 22.0041,153.178 66.1718,202.679 44.1677,49.5004 103.501,74.162 178.495,74.162 70.8313,0 129.013,-25.1577 174.332,-75.6679 45.1775,-50.3331 67.8371,-117.497 67.8371,-201.173 0,-86.1562 -22.323,-154.33 -67.0045,-203.99 -44.4866,-49.837 -103.997,-74.8352 -178.159,-74.8352zm2.00198 73.8254c100.826,0 151.336,68.3332 151.336,205 0,135.515 -50.8469,203.175 -152.346,203.175 -100.666,0 -150.822,-67.66 -150.822,-203.175 0,-136.666 50.4925,-205 151.832,-205z"
147
+ id="path69" /></glyph><glyph
148
+ unicode="h"
149
+ horiz-adv-x="600"
150
+ id="glyph71"><path
151
+ d="M433.173 0l0 345.174c0,84.668 -38.835,126.993 -116.345,126.993 -99.8335,0 -149.83,-64.8253 -149.83,-194.334l0 -277.833 -88.8314 0 0 759.833 88.8314 0 0 -225.657 -3.8268 -70.3352 4.83665 0c33.4845,54.6559 88.1582,81.9928 163.986,81.9928 126.674,0 190.011,-65.1619 190.011,-195.663l0 -350.17 -88.8314 0z"
152
+ id="path73" /></glyph><glyph
153
+ unicode="u"
154
+ horiz-adv-x="600"
155
+ id="glyph75"><path
156
+ d="M450.167 0l-13.181 71.8295 -4.81887 0c-34.1573,-54.5099 -88.4971,-81.6656 -163.161,-81.6656 -127.161,0 -190.827,65.3382 -190.827,195.844l0 350.162 88.8089 0 0 -345.173c0,-84.6703 38.3525,-126.991 115.171,-126.991 52.4973,0 90.6797,14.9952 114.831,45.1556 24.0093,30.0187 36.1699,79.6814 36.1699,148.676l0 278.332 88.8372 0 0 -536.17 -71.8295 0z"
157
+ id="path77" /></glyph><glyph
158
+ unicode="p"
159
+ horiz-adv-x="600"
160
+ id="glyph79"><path
161
+ d="M165.996 67.8326l-5.83933 0c3.85509,-42.0092 5.83933,-68.3429 5.83933,-79.0011l0 -229.01 -88.8372 0 0 776.348 71.8295 0 13.181 -72.3397 3.82675 0c35.8297,54.68 88.1569,82.0058 157.18,82.0058 65.4799,0 116.815,-24.3495 154.147,-72.9917 37.1903,-48.6706 55.8422,-116.503 55.8422,-203.838 0,-87.8451 -18.6519,-156.33 -56.154,-205.34 -37.332,-49.0107 -88.6672,-73.5019 -153.835,-73.5019 -67.3508,0 -119.678,25.9935 -157.18,77.6688zm0 221.158l0 -19.9841c0,-73.8421 11.3385,-126.509 34.0155,-157.832 22.4786,-31.5211 58.6484,-47.1682 108.169,-47.1682 88.4971,0 132.831,68.6547 132.831,205.992 0,134.843 -44.6737,202.166 -133.851,202.166 -49.4926,0 -84.9821,-14.3432 -106.667,-43.0013 -21.6566,-28.6581 -33.1651,-75.3161 -34.4974,-140.172z"
162
+ id="path81" /></glyph><glyph
163
+ unicode="v"
164
+ horiz-adv-x="600"
165
+ id="glyph83"><path
166
+ d="M243.154 0l-203.158 536.17 91.8419 0 117.155 -318.329c27.666,-75.3444 43.9934,-128.182 48.8406,-158.682l3.00471 0c2.15432,14.1731 18.6519,67.1807 49.3225,158.682l116.673 318.329 92.3238 0 -203.158 -536.17 -112.847 0z"
167
+ id="path85" /></glyph><glyph
168
+ unicode="r"
169
+ horiz-adv-x="600"
170
+ id="glyph87"><path
171
+ d="M517.178 524.009l-24.0093 -81.1837c-39.9966,14.6834 -76.5066,21.9967 -109.332,21.9967 -53.1776,0 -93.9963,-14.9952 -122.824,-45.1556 -28.8565,-30.1604 -43.1714,-73.672 -43.1714,-130.676l0 -288.99 -89.0073 0 0 536.17 72.3397 0 10.6582 -98.1632 3.99683 0c24.6613,38.6643 51.3351,66.3303 79.5113,82.9979 28.3179,16.6676 63.1555,24.8313 104.484,24.8313 38.5226,0 77.4987,-7.34169 117.354,-21.8266z"
172
+ id="path89" /></glyph><glyph
173
+ unicode="t"
174
+ horiz-adv-x="600"
175
+ id="glyph91"><path
176
+ d="M497.998 73.1699l0 -67.3411c-42.3251,-10.3288 -83.3392,-15.6615 -122.989,-15.6615 -117.834,0 -176.848,56.0024 -176.848,168.007l0 310.999 -130.324 0 0 45.9925 130.324 23.8289 37.6657 140.174 51.3429 0 0 -143.009 213.823 0 0 -66.9867 -213.823 0 0 -310.999c0,-63.5143 31.1636,-95.174 93.6681,-95.174 30.3309,0 69.3253,3.33073 117.16,10.1694z"
177
+ id="path93" /></glyph><glyph
178
+ unicode="y"
179
+ horiz-adv-x="600"
180
+ id="glyph95"><path
181
+ d="M40.0043 536.16l91.8255 0 128.003 -319.325c26.6636,-66.8273 41.1736,-114.007 43.335,-141.663l2.99412 0c7.51187,36.4964 22.1636,83.9948 44.0082,142.655l116.664 318.333 92.3393 0 -232 -605.999c-21.8447,-56.6579 -47.1795,-99.1602 -76.1817,-127.666 -28.9845,-28.4884 -68.9887,-42.6618 -120.154,-42.6618 -28.0101,0 -55.3292,2.67522 -82.0105,8.16739l0 70.8313c20.1793,-3.8268 42.3429,-5.82879 66.3312,-5.82879 31.3408,0 55.6835,6.66147 73.0104,20.0021 17.5041,13.3229 33.0062,36.3369 46.6657,68.8293l28.329 73.3293 -223.159 540.996z"
182
+ id="path97" /></glyph></font><style
183
+ type="text/css"
184
+ id="style99">
185
+
186
+ @font-face { font-family:&quot;Droid Sans Mono&quot;;src:url(&quot;#FontID0&quot;) format(svg)}
187
+ .fil2 {fill:black}
188
+ .fil0 {fill:#2B2828}
189
+ .fil1 {fill:#3465A4}
190
+ .fnt1 {font-weight:normal;font-size:41.6669;font-family:'Droid Sans Mono'}
191
+ .fnt0 {font-weight:normal;font-size:66.6661;font-family:'Droid Sans Mono'}
192
+ .fnt3 {font-weight:normal;font-size:125;font-family:'Droid Sans Mono'}
193
+ .fnt2 {font-weight:normal;font-size:150;font-family:'Droid Sans Mono'}
194
+
195
+ </style></defs><g
196
+ id="g3107"
197
+ transform="translate(-187.8219,-31.158651)"><text
198
+ x="569.31348"
199
+ y="138.23804"
200
+ id="text3840"
201
+ class="fil0 fnt0"
202
+ style="font-size:140.73484802px;font-weight:normal;fill:#3465a4;fill-opacity:1;font-family:Droid Sans Mono">Notebook</text>
203
+ </g><text
204
+ style="font-size:150px;font-weight:normal;fill:#000000;font-family:Droid Sans Mono"
205
+ id="text109"
206
+ class="fil2 fnt2"
207
+ y="107.07938"
208
+ x="-16.479492">IP</text>
209
+ <g
210
+ id="g3115"
211
+ transform="translate(-103.83379,-34.841245)"><text
212
+ x="261.15134"
213
+ y="124.71784"
214
+ class="fil1 fnt3"
215
+ id="text111"
216
+ style="font-size:108.73868561px;font-weight:normal;fill:#3465a4;font-family:Droid Sans Mono">[</text>
217
+ <text
218
+ x="356.85321"
219
+ y="124.71784"
220
+ class="fil1 fnt3"
221
+ id="text113"
222
+ style="font-size:108.73868561px;font-weight:normal;fill:#3465a4;font-family:Droid Sans Mono">]</text>
223
+ <text
224
+ x="395.29062"
225
+ y="123.62939"
226
+ class="fil1 fnt3"
227
+ id="text115"
228
+ style="font-size:108.73868561px;font-weight:normal;fill:#3465a4;font-family:Droid Sans Mono">:</text>
229
+ <text
230
+ x="315.31311"
231
+ y="118.70238"
232
+ class="fil2 fnt3"
233
+ id="text117"
234
+ style="font-size:96.64835358px;font-weight:normal;fill:#000000;font-family:Droid Sans Mono">y</text>
235
+ </g><g
236
+ style="fill-rule:evenodd"
237
+ id="g3107-3"
238
+ transform="translate(508.42312,-31.158652)"><text
239
+ x="555.31348"
240
+ y="138.23804"
241
+ id="text3840-2"
242
+ class="fil0 fnt0"
243
+ style="font-size:140.73484802px;font-weight:normal;fill:#3465a4;fill-opacity:1;font-family:Droid Sans Mono"><tspan
244
+ style="fill:#800000"
245
+ id="tspan3069">+IRuby</tspan></text>
246
+ <flowRoot
247
+ xml:space="preserve"
248
+ id="flowRoot3071"
249
+ style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
250
+ transform="translate(-531.86784,-0.07879489)"><flowRegion
251
+ id="flowRegion3073"><rect
252
+ id="rect3075"
253
+ width="1942.4757"
254
+ height="495.6268"
255
+ x="-89.59407"
256
+ y="-152.62613" /></flowRegion><flowPara
257
+ id="flowPara3077"></flowPara></flowRoot><flowRoot
258
+ xml:space="preserve"
259
+ id="flowRoot3079"
260
+ style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
261
+ transform="translate(-531.86784,-0.07879489)"><flowRegion
262
+ id="flowRegion3081"><rect
263
+ id="rect3083"
264
+ width="1877.663"
265
+ height="488.00177"
266
+ x="-104.84413"
267
+ y="-148.81361" /></flowRegion><flowPara
268
+ id="flowPara3085"></flowPara></flowRoot></g></svg>