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