##// END OF EJS Templates
evaluate a few dangling validate_message generators...
MinRK -
Show More
@@ -1,430 +1,437 b''
1 """Test suite for our zeromq-based messaging specification.
1 """Test suite for our zeromq-based messaging specification.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (C) 2010-2011 The IPython Development Team
4 # Copyright (C) 2010-2011 The IPython Development Team
5 #
5 #
6 # Distributed under the terms of the BSD License. The full license is in
6 # Distributed under the terms of the BSD License. The full license is in
7 # the file COPYING.txt, distributed as part of this software.
7 # the file COPYING.txt, distributed as part of this software.
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 import re
10 import re
11 import sys
11 import sys
12 import time
12 import time
13 from subprocess import PIPE
13 from subprocess import PIPE
14 from Queue import Empty
14 from Queue import Empty
15
15
16 import nose.tools as nt
16 import nose.tools as nt
17
17
18 from ..blockingkernelmanager import BlockingKernelManager
18 from ..blockingkernelmanager import BlockingKernelManager
19
19
20
20
21 from IPython.testing import decorators as dec
21 from IPython.testing import decorators as dec
22 from IPython.utils import io
22 from IPython.utils import io
23 from IPython.utils.traitlets import (
23 from IPython.utils.traitlets import (
24 HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum,
24 HasTraits, TraitError, Bool, Unicode, Dict, Integer, List, Enum,
25 )
25 )
26
26
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 # Global setup and utilities
28 # Global setup and utilities
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30
30
31 def setup():
31 def setup():
32 global KM
32 global KM
33 KM = BlockingKernelManager()
33 KM = BlockingKernelManager()
34
34
35 KM.start_kernel(stdout=PIPE, stderr=PIPE)
35 KM.start_kernel(stdout=PIPE, stderr=PIPE)
36 KM.start_channels()
36 KM.start_channels()
37
37
38
38
39 def teardown():
39 def teardown():
40 KM.stop_channels()
40 KM.stop_channels()
41 KM.shutdown_kernel()
41 KM.shutdown_kernel()
42
42
43
43
44 def flush_channels():
44 def flush_channels():
45 """flush any messages waiting on the queue"""
45 """flush any messages waiting on the queue"""
46 for channel in (KM.shell_channel, KM.sub_channel):
46 for channel in (KM.shell_channel, KM.sub_channel):
47 while True:
47 while True:
48 try:
48 try:
49 msg = channel.get_msg(block=True, timeout=0.1)
49 msg = channel.get_msg(block=True, timeout=0.1)
50 except Empty:
50 except Empty:
51 break
51 break
52 else:
52 else:
53 validate_message(msg)
53 list(validate_message(msg))
54
54
55
55
56 def execute(code='', **kwargs):
56 def execute(code='', **kwargs):
57 """wrapper for doing common steps for validating an execution request"""
57 """wrapper for doing common steps for validating an execution request"""
58 shell = KM.shell_channel
58 shell = KM.shell_channel
59 sub = KM.sub_channel
59 sub = KM.sub_channel
60
60
61 msg_id = shell.execute(code=code, **kwargs)
61 msg_id = shell.execute(code=code, **kwargs)
62 reply = shell.get_msg(timeout=2)
62 reply = shell.get_msg(timeout=2)
63 validate_message(reply, 'execute_reply', msg_id)
63 list(validate_message(reply, 'execute_reply', msg_id))
64 busy = sub.get_msg(timeout=2)
64 busy = sub.get_msg(timeout=2)
65 validate_message(busy, 'status', msg_id)
65 list(validate_message(busy, 'status', msg_id))
66 nt.assert_equals(busy['content']['execution_state'], 'busy')
66 nt.assert_equals(busy['content']['execution_state'], 'busy')
67
67
68 if not kwargs.get('silent'):
68 if not kwargs.get('silent'):
69 pyin = sub.get_msg(timeout=2)
69 pyin = sub.get_msg(timeout=2)
70 validate_message(pyin, 'pyin', msg_id)
70 list(validate_message(pyin, 'pyin', msg_id))
71 nt.assert_equals(pyin['content']['code'], code)
71 nt.assert_equals(pyin['content']['code'], code)
72
72
73 return msg_id, reply['content']
73 return msg_id, reply['content']
74
74
75 #-----------------------------------------------------------------------------
75 #-----------------------------------------------------------------------------
76 # MSG Spec References
76 # MSG Spec References
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78
78
79
79
80 class Reference(HasTraits):
80 class Reference(HasTraits):
81
81
82 def check(self, d):
82 def check(self, d):
83 """validate a dict against our traits"""
83 """validate a dict against our traits"""
84 for key in self.trait_names():
84 for key in self.trait_names():
85 yield nt.assert_true(key in d, "Missing key: %r, should be found in %s" % (key, d))
85 yield nt.assert_true(key in d, "Missing key: %r, should be found in %s" % (key, d))
86 # FIXME: always allow None, probably not a good idea
86 # FIXME: always allow None, probably not a good idea
87 if d[key] is None:
87 if d[key] is None:
88 continue
88 continue
89 try:
89 try:
90 setattr(self, key, d[key])
90 setattr(self, key, d[key])
91 except TraitError as e:
91 except TraitError as e:
92 yield nt.assert_true(False, str(e))
92 yield nt.assert_true(False, str(e))
93
93
94
94
95 class RMessage(Reference):
95 class RMessage(Reference):
96 msg_id = Unicode()
96 msg_id = Unicode()
97 msg_type = Unicode()
97 msg_type = Unicode()
98 header = Dict()
98 header = Dict()
99 parent_header = Dict()
99 parent_header = Dict()
100 content = Dict()
100 content = Dict()
101
101
102 class RHeader(Reference):
102 class RHeader(Reference):
103 msg_id = Unicode()
103 msg_id = Unicode()
104 msg_type = Unicode()
104 msg_type = Unicode()
105 session = Unicode()
105 session = Unicode()
106 username = Unicode()
106 username = Unicode()
107
107
108 class RContent(Reference):
108 class RContent(Reference):
109 status = Enum((u'ok', u'error'))
109 status = Enum((u'ok', u'error'))
110
110
111
111
112 class ExecuteReply(Reference):
112 class ExecuteReply(Reference):
113 execution_count = Integer()
113 execution_count = Integer()
114 status = Enum((u'ok', u'error'))
114 status = Enum((u'ok', u'error'))
115
115
116 def check(self, d):
116 def check(self, d):
117 for tst in Reference.check(self, d):
117 for tst in Reference.check(self, d):
118 yield tst
118 yield tst
119 if d['status'] == 'ok':
119 if d['status'] == 'ok':
120 for tst in ExecuteReplyOkay().check(d):
120 for tst in ExecuteReplyOkay().check(d):
121 yield tst
121 yield tst
122 elif d['status'] == 'error':
122 elif d['status'] == 'error':
123 for tst in ExecuteReplyError().check(d):
123 for tst in ExecuteReplyError().check(d):
124 yield tst
124 yield tst
125
125
126
126
127 class ExecuteReplyOkay(Reference):
127 class ExecuteReplyOkay(Reference):
128 payload = List(Dict)
128 payload = List(Dict)
129 user_variables = Dict()
129 user_variables = Dict()
130 user_expressions = Dict()
130 user_expressions = Dict()
131
131
132
132
133 class ExecuteReplyError(Reference):
133 class ExecuteReplyError(Reference):
134 ename = Unicode()
134 ename = Unicode()
135 evalue = Unicode()
135 evalue = Unicode()
136 traceback = List(Unicode)
136 traceback = List(Unicode)
137
137
138
138
139 class OInfoReply(Reference):
139 class OInfoReply(Reference):
140 name = Unicode()
140 name = Unicode()
141 found = Bool()
141 found = Bool()
142 ismagic = Bool()
142 ismagic = Bool()
143 isalias = Bool()
143 isalias = Bool()
144 namespace = Enum((u'builtin', u'magics', u'alias', u'Interactive'))
144 namespace = Enum((u'builtin', u'magics', u'alias', u'Interactive'))
145 type_name = Unicode()
145 type_name = Unicode()
146 string_form = Unicode()
146 string_form = Unicode()
147 base_class = Unicode()
147 base_class = Unicode()
148 length = Integer()
148 length = Integer()
149 file = Unicode()
149 file = Unicode()
150 definition = Unicode()
150 definition = Unicode()
151 argspec = Dict()
151 argspec = Dict()
152 init_definition = Unicode()
152 init_definition = Unicode()
153 docstring = Unicode()
153 docstring = Unicode()
154 init_docstring = Unicode()
154 init_docstring = Unicode()
155 class_docstring = Unicode()
155 class_docstring = Unicode()
156 call_def = Unicode()
156 call_def = Unicode()
157 call_docstring = Unicode()
157 call_docstring = Unicode()
158 source = Unicode()
158 source = Unicode()
159
159
160 def check(self, d):
160 def check(self, d):
161 for tst in Reference.check(self, d):
161 for tst in Reference.check(self, d):
162 yield tst
162 yield tst
163 if d['argspec'] is not None:
163 if d['argspec'] is not None:
164 for tst in ArgSpec().check(d['argspec']):
164 for tst in ArgSpec().check(d['argspec']):
165 yield tst
165 yield tst
166
166
167
167
168 class ArgSpec(Reference):
168 class ArgSpec(Reference):
169 args = List(Unicode)
169 args = List(Unicode)
170 varargs = Unicode()
170 varargs = Unicode()
171 varkw = Unicode()
171 varkw = Unicode()
172 defaults = List()
172 defaults = List()
173
173
174
174
175 class Status(Reference):
175 class Status(Reference):
176 execution_state = Enum((u'busy', u'idle'))
176 execution_state = Enum((u'busy', u'idle'))
177
177
178
178
179 class CompleteReply(Reference):
179 class CompleteReply(Reference):
180 matches = List(Unicode)
180 matches = List(Unicode)
181
181
182
182
183 # IOPub messages
183 # IOPub messages
184
184
185 class PyIn(Reference):
185 class PyIn(Reference):
186 code = Unicode()
186 code = Unicode()
187 execution_count = Integer()
187 execution_count = Integer()
188
188
189
189
190 PyErr = ExecuteReplyError
190 PyErr = ExecuteReplyError
191
191
192
192
193 class Stream(Reference):
193 class Stream(Reference):
194 name = Enum((u'stdout', u'stderr'))
194 name = Enum((u'stdout', u'stderr'))
195 data = Unicode()
195 data = Unicode()
196
196
197
197
198 mime_pat = re.compile(r'\w+/\w+')
198 mime_pat = re.compile(r'\w+/\w+')
199
199
200 class DisplayData(Reference):
200 class DisplayData(Reference):
201 source = Unicode()
201 source = Unicode()
202 metadata = Dict()
202 metadata = Dict()
203 data = Dict()
203 data = Dict()
204 def _data_changed(self, name, old, new):
204 def _data_changed(self, name, old, new):
205 for k,v in new.iteritems():
205 for k,v in new.iteritems():
206 nt.assert_true(mime_pat.match(k))
206 nt.assert_true(mime_pat.match(k))
207 nt.assert_true(isinstance(v, basestring), "expected string data, got %r" % v)
207 nt.assert_true(isinstance(v, basestring), "expected string data, got %r" % v)
208
208
209
209
210 references = {
210 references = {
211 'execute_reply' : ExecuteReply(),
211 'execute_reply' : ExecuteReply(),
212 'object_info_reply' : OInfoReply(),
212 'object_info_reply' : OInfoReply(),
213 'status' : Status(),
213 'status' : Status(),
214 'complete_reply' : CompleteReply(),
214 'complete_reply' : CompleteReply(),
215 'pyin' : PyIn(),
215 'pyin' : PyIn(),
216 'pyerr' : PyErr(),
216 'pyerr' : PyErr(),
217 'stream' : Stream(),
217 'stream' : Stream(),
218 'display_data' : DisplayData(),
218 'display_data' : DisplayData(),
219 }
219 }
220
220
221
221
222 def validate_message(msg, msg_type=None, parent=None):
222 def validate_message(msg, msg_type=None, parent=None):
223 """validate a message"""
223 """validate a message
224
225 This is a generator, and must be iterated through to actually
226 trigger each test.
227
228 If msg_type and/or parent are given, the msg_type and/or parent msg_id
229 are compared with the given values.
230 """
224 RMessage().check(msg)
231 RMessage().check(msg)
225 if msg_type:
232 if msg_type:
226 yield nt.assert_equals(msg['msg_type'], msg_type)
233 yield nt.assert_equals(msg['msg_type'], msg_type)
227 if parent:
234 if parent:
228 yield nt.assert_equal(msg['parent_header']['msg_id'], parent)
235 yield nt.assert_equal(msg['parent_header']['msg_id'], parent)
229 content = msg['content']
236 content = msg['content']
230 ref = references[msg['msg_type']]
237 ref = references[msg['msg_type']]
231 for tst in ref.check(content):
238 for tst in ref.check(content):
232 yield tst
239 yield tst
233
240
234
241
235 #-----------------------------------------------------------------------------
242 #-----------------------------------------------------------------------------
236 # Tests
243 # Tests
237 #-----------------------------------------------------------------------------
244 #-----------------------------------------------------------------------------
238
245
239 # Shell channel
246 # Shell channel
240
247
241 @dec.parametric
248 @dec.parametric
242 def test_execute():
249 def test_execute():
243 flush_channels()
250 flush_channels()
244
251
245 shell = KM.shell_channel
252 shell = KM.shell_channel
246 msg_id = shell.execute(code='x=1')
253 msg_id = shell.execute(code='x=1')
247 reply = shell.get_msg(timeout=2)
254 reply = shell.get_msg(timeout=2)
248 for tst in validate_message(reply, 'execute_reply', msg_id):
255 for tst in validate_message(reply, 'execute_reply', msg_id):
249 yield tst
256 yield tst
250
257
251
258
252 @dec.parametric
259 @dec.parametric
253 def test_execute_silent():
260 def test_execute_silent():
254 flush_channels()
261 flush_channels()
255 msg_id, reply = execute(code='x=1', silent=True)
262 msg_id, reply = execute(code='x=1', silent=True)
256
263
257 # flush status=idle
264 # flush status=idle
258 status = KM.sub_channel.get_msg(timeout=2)
265 status = KM.sub_channel.get_msg(timeout=2)
259 for tst in validate_message(status, 'status', msg_id):
266 for tst in validate_message(status, 'status', msg_id):
260 yield tst
267 yield tst
261 nt.assert_equals(status['content']['execution_state'], 'idle')
268 nt.assert_equals(status['content']['execution_state'], 'idle')
262
269
263 yield nt.assert_raises(Empty, KM.sub_channel.get_msg, timeout=0.1)
270 yield nt.assert_raises(Empty, KM.sub_channel.get_msg, timeout=0.1)
264 count = reply['execution_count']
271 count = reply['execution_count']
265
272
266 msg_id, reply = execute(code='x=2', silent=True)
273 msg_id, reply = execute(code='x=2', silent=True)
267
274
268 # flush status=idle
275 # flush status=idle
269 status = KM.sub_channel.get_msg(timeout=2)
276 status = KM.sub_channel.get_msg(timeout=2)
270 for tst in validate_message(status, 'status', msg_id):
277 for tst in validate_message(status, 'status', msg_id):
271 yield tst
278 yield tst
272 yield nt.assert_equals(status['content']['execution_state'], 'idle')
279 yield nt.assert_equals(status['content']['execution_state'], 'idle')
273
280
274 yield nt.assert_raises(Empty, KM.sub_channel.get_msg, timeout=0.1)
281 yield nt.assert_raises(Empty, KM.sub_channel.get_msg, timeout=0.1)
275 count_2 = reply['execution_count']
282 count_2 = reply['execution_count']
276 yield nt.assert_equals(count_2, count)
283 yield nt.assert_equals(count_2, count)
277
284
278
285
279 @dec.parametric
286 @dec.parametric
280 def test_execute_error():
287 def test_execute_error():
281 flush_channels()
288 flush_channels()
282
289
283 msg_id, reply = execute(code='1/0')
290 msg_id, reply = execute(code='1/0')
284 yield nt.assert_equals(reply['status'], 'error')
291 yield nt.assert_equals(reply['status'], 'error')
285 yield nt.assert_equals(reply['ename'], 'ZeroDivisionError')
292 yield nt.assert_equals(reply['ename'], 'ZeroDivisionError')
286
293
287 pyerr = KM.sub_channel.get_msg(timeout=2)
294 pyerr = KM.sub_channel.get_msg(timeout=2)
288 for tst in validate_message(pyerr, 'pyerr', msg_id):
295 for tst in validate_message(pyerr, 'pyerr', msg_id):
289 yield tst
296 yield tst
290
297
291
298
292 def test_execute_inc():
299 def test_execute_inc():
293 """execute request should increment execution_count"""
300 """execute request should increment execution_count"""
294 flush_channels()
301 flush_channels()
295
302
296 msg_id, reply = execute(code='x=1')
303 msg_id, reply = execute(code='x=1')
297 count = reply['execution_count']
304 count = reply['execution_count']
298
305
299 flush_channels()
306 flush_channels()
300
307
301 msg_id, reply = execute(code='x=2')
308 msg_id, reply = execute(code='x=2')
302 count_2 = reply['execution_count']
309 count_2 = reply['execution_count']
303 nt.assert_equals(count_2, count+1)
310 nt.assert_equals(count_2, count+1)
304
311
305
312
306 def test_user_variables():
313 def test_user_variables():
307 flush_channels()
314 flush_channels()
308
315
309 msg_id, reply = execute(code='x=1', user_variables=['x'])
316 msg_id, reply = execute(code='x=1', user_variables=['x'])
310 user_variables = reply['user_variables']
317 user_variables = reply['user_variables']
311 nt.assert_equals(user_variables, {u'x' : u'1'})
318 nt.assert_equals(user_variables, {u'x' : u'1'})
312
319
313
320
314 def test_user_expressions():
321 def test_user_expressions():
315 flush_channels()
322 flush_channels()
316
323
317 msg_id, reply = execute(code='x=1', user_expressions=dict(foo='x+1'))
324 msg_id, reply = execute(code='x=1', user_expressions=dict(foo='x+1'))
318 user_expressions = reply['user_expressions']
325 user_expressions = reply['user_expressions']
319 nt.assert_equals(user_expressions, {u'foo' : u'2'})
326 nt.assert_equals(user_expressions, {u'foo' : u'2'})
320
327
321
328
322 @dec.parametric
329 @dec.parametric
323 def test_oinfo():
330 def test_oinfo():
324 flush_channels()
331 flush_channels()
325
332
326 shell = KM.shell_channel
333 shell = KM.shell_channel
327
334
328 msg_id = shell.object_info('a')
335 msg_id = shell.object_info('a')
329 reply = shell.get_msg(timeout=2)
336 reply = shell.get_msg(timeout=2)
330 for tst in validate_message(reply, 'object_info_reply', msg_id):
337 for tst in validate_message(reply, 'object_info_reply', msg_id):
331 yield tst
338 yield tst
332
339
333
340
334 @dec.parametric
341 @dec.parametric
335 def test_oinfo_found():
342 def test_oinfo_found():
336 flush_channels()
343 flush_channels()
337
344
338 shell = KM.shell_channel
345 shell = KM.shell_channel
339
346
340 msg_id, reply = execute(code='a=5')
347 msg_id, reply = execute(code='a=5')
341
348
342 msg_id = shell.object_info('a')
349 msg_id = shell.object_info('a')
343 reply = shell.get_msg(timeout=2)
350 reply = shell.get_msg(timeout=2)
344 for tst in validate_message(reply, 'object_info_reply', msg_id):
351 for tst in validate_message(reply, 'object_info_reply', msg_id):
345 yield tst
352 yield tst
346 content = reply['content']
353 content = reply['content']
347 yield nt.assert_true(content['found'])
354 yield nt.assert_true(content['found'])
348 argspec = content['argspec']
355 argspec = content['argspec']
349 yield nt.assert_true(argspec is None, "didn't expect argspec dict, got %r" % argspec)
356 yield nt.assert_true(argspec is None, "didn't expect argspec dict, got %r" % argspec)
350
357
351
358
352 @dec.parametric
359 @dec.parametric
353 def test_oinfo_detail():
360 def test_oinfo_detail():
354 flush_channels()
361 flush_channels()
355
362
356 shell = KM.shell_channel
363 shell = KM.shell_channel
357
364
358 msg_id, reply = execute(code='ip=get_ipython()')
365 msg_id, reply = execute(code='ip=get_ipython()')
359
366
360 msg_id = shell.object_info('ip.object_inspect', detail_level=2)
367 msg_id = shell.object_info('ip.object_inspect', detail_level=2)
361 reply = shell.get_msg(timeout=2)
368 reply = shell.get_msg(timeout=2)
362 for tst in validate_message(reply, 'object_info_reply', msg_id):
369 for tst in validate_message(reply, 'object_info_reply', msg_id):
363 yield tst
370 yield tst
364 content = reply['content']
371 content = reply['content']
365 yield nt.assert_true(content['found'])
372 yield nt.assert_true(content['found'])
366 argspec = content['argspec']
373 argspec = content['argspec']
367 yield nt.assert_true(isinstance(argspec, dict), "expected non-empty argspec dict, got %r" % argspec)
374 yield nt.assert_true(isinstance(argspec, dict), "expected non-empty argspec dict, got %r" % argspec)
368 yield nt.assert_equals(argspec['defaults'], [0])
375 yield nt.assert_equals(argspec['defaults'], [0])
369
376
370
377
371 @dec.parametric
378 @dec.parametric
372 def test_oinfo_not_found():
379 def test_oinfo_not_found():
373 flush_channels()
380 flush_channels()
374
381
375 shell = KM.shell_channel
382 shell = KM.shell_channel
376
383
377 msg_id = shell.object_info('dne')
384 msg_id = shell.object_info('dne')
378 reply = shell.get_msg(timeout=2)
385 reply = shell.get_msg(timeout=2)
379 for tst in validate_message(reply, 'object_info_reply', msg_id):
386 for tst in validate_message(reply, 'object_info_reply', msg_id):
380 yield tst
387 yield tst
381 content = reply['content']
388 content = reply['content']
382 yield nt.assert_false(content['found'])
389 yield nt.assert_false(content['found'])
383
390
384
391
385 @dec.parametric
392 @dec.parametric
386 def test_complete():
393 def test_complete():
387 flush_channels()
394 flush_channels()
388
395
389 shell = KM.shell_channel
396 shell = KM.shell_channel
390
397
391 msg_id, reply = execute(code="alpha = albert = 5")
398 msg_id, reply = execute(code="alpha = albert = 5")
392
399
393 msg_id = shell.complete('al', 'al', 2)
400 msg_id = shell.complete('al', 'al', 2)
394 reply = shell.get_msg(timeout=2)
401 reply = shell.get_msg(timeout=2)
395 for tst in validate_message(reply, 'complete_reply', msg_id):
402 for tst in validate_message(reply, 'complete_reply', msg_id):
396 yield tst
403 yield tst
397 matches = reply['content']['matches']
404 matches = reply['content']['matches']
398 for name in ('alpha', 'albert'):
405 for name in ('alpha', 'albert'):
399 yield nt.assert_true(name in matches, "Missing match: %r" % name)
406 yield nt.assert_true(name in matches, "Missing match: %r" % name)
400
407
401
408
402 # IOPub channel
409 # IOPub channel
403
410
404
411
405 @dec.parametric
412 @dec.parametric
406 def test_stream():
413 def test_stream():
407 flush_channels()
414 flush_channels()
408
415
409 msg_id, reply = execute("print('hi')")
416 msg_id, reply = execute("print('hi')")
410
417
411 stdout = KM.sub_channel.get_msg(timeout=2)
418 stdout = KM.sub_channel.get_msg(timeout=2)
412 for tst in validate_message(stdout, 'stream', msg_id):
419 for tst in validate_message(stdout, 'stream', msg_id):
413 yield tst
420 yield tst
414 content = stdout['content']
421 content = stdout['content']
415 yield nt.assert_equals(content['name'], u'stdout')
422 yield nt.assert_equals(content['name'], u'stdout')
416 yield nt.assert_equals(content['data'], u'hi\n')
423 yield nt.assert_equals(content['data'], u'hi\n')
417
424
418
425
419 @dec.parametric
426 @dec.parametric
420 def test_display_data():
427 def test_display_data():
421 flush_channels()
428 flush_channels()
422
429
423 msg_id, reply = execute("from IPython.core.display import display; display(1)")
430 msg_id, reply = execute("from IPython.core.display import display; display(1)")
424
431
425 display = KM.sub_channel.get_msg(timeout=2)
432 display = KM.sub_channel.get_msg(timeout=2)
426 for tst in validate_message(display, 'display_data', parent=msg_id):
433 for tst in validate_message(display, 'display_data', parent=msg_id):
427 yield tst
434 yield tst
428 data = display['content']['data']
435 data = display['content']['data']
429 yield nt.assert_equals(data['text/plain'], u'1')
436 yield nt.assert_equals(data['text/plain'], u'1')
430
437
General Comments 0
You need to be logged in to leave comments. Login now