@@ -120,7 +120,7 @@ async def recv(self, multipart=False):
120
120
# _LOGGER.debug(f"recv: got cmd={cmd}, params={params}")
121
121
else :
122
122
parts .append (msg_body )
123
- if cmd == 0x0 or cmd == 0x2 :
123
+ if cmd in ( 0x0 , 0x2 ) :
124
124
# _LOGGER.debug(f"recv: got msg {parts}")
125
125
if not multipart :
126
126
return b'' .join (parts )
@@ -311,218 +311,205 @@ def encode(msg):
311
311
# else:
312
312
# _LOGGER.debug("send skipping msg_type %s since socket is None", msg_type)
313
313
314
- async def shell_handler (self , shell_socket , full_msg ):
314
+ async def shell_handler (self , shell_socket , wire_msg ):
315
315
"""Handle shell messages."""
316
- #
317
- # Jupyter extensions like black can send several execute requests back-to-back, so
318
- # we need to handle multiple messages separated by DELIM
319
- #
320
- msg_list = None
321
- for this_msg in full_msg :
322
- if this_msg == DELIM :
323
- if msg_list is None :
324
- msg_list = [[this_msg ]]
325
- else :
326
- msg_list .append ([this_msg ])
327
- else :
328
- msg_list [- 1 ].append (this_msg ) # pylint: disable=unsubscriptable-object
329
- for this_msg in msg_list : # pylint: disable=too-many-nested-blocks
330
- identities , msg = self .deserialize_wire_msg (this_msg )
331
- # _LOGGER.debug("shell received %s: %s", msg.get('header', {}).get('msg_type', 'UNKNOWN'), msg)
332
316
333
- content = {
334
- 'execution_state' : "busy" ,
335
- }
336
- await self .send (self .iopub_socket , 'status' , content , parent_header = msg ['header' ])
317
+ identities , msg = self .deserialize_wire_msg (wire_msg )
318
+ # _LOGGER.debug("shell received %s: %s", msg.get('header', {}).get('msg_type', 'UNKNOWN'), msg)
319
+ self .parent_header = msg ['header' ]
337
320
338
- self .parent_header = msg ['header' ]
339
-
340
- # process request:
321
+ content = {
322
+ 'execution_state' : "busy" ,
323
+ }
324
+ await self .send (self .iopub_socket , 'status' , content , parent_header = msg ['header' ])
341
325
342
- if msg ['header' ]["msg_type" ] == "execute_request" :
326
+ if msg ['header' ]["msg_type" ] == "execute_request" :
343
327
344
- content = {
345
- 'execution_count' : self .execution_count ,
346
- 'code' : msg ['content' ]["code" ],
347
- }
348
- await self .send (self .iopub_socket , 'execute_input' , content , parent_header = msg ['header' ])
328
+ content = {
329
+ 'execution_count' : self .execution_count ,
330
+ 'code' : msg ['content' ]["code" ],
331
+ }
332
+ await self .send (self .iopub_socket , 'execute_input' , content , parent_header = msg ['header' ])
349
333
350
- code = msg ['content' ]["code" ]
351
- self .ast_ctx .parse (code )
334
+ code = msg ['content' ]["code" ]
335
+ self .ast_ctx .parse (code )
336
+ exc = self .ast_ctx .get_exception_obj ()
337
+ if exc is None :
338
+ result = await self .ast_ctx .eval ()
352
339
exc = self .ast_ctx .get_exception_obj ()
353
- if exc is None :
354
- result = await self .ast_ctx .eval ()
355
- exc = self .ast_ctx .get_exception_obj ()
356
- if exc :
357
- traceback_mesg = self .ast_ctx .get_exception_long ().split ("\n " )
358
-
359
- if msg ['content' ].get ("store_history" , True ):
360
- self .execution_count += 1
361
-
362
- metadata = {
363
- "dependencies_met" : True ,
364
- "engine" : self .engine_id ,
365
- "status" : "error" ,
366
- "started" : datetime .datetime .now ().isoformat (),
367
- }
368
- content = {
369
- 'execution_count' : self .execution_count ,
370
- 'status' : 'error' ,
371
- 'ename' : type (exc ).__name__ , # Exception name, as a string
372
- 'evalue' : str (exc ), # Exception value, as a string
373
- 'traceback' : traceback_mesg ,
374
- }
375
- _LOGGER .debug ("Executing '%s' got exception: %s" , code , content )
376
- await self .send (shell_socket , 'execute_reply' , content , metadata = metadata ,
377
- parent_header = msg ['header' ], identities = identities )
378
- del content ["execution_count" ], content ["status" ]
379
- await self .send (self .iopub_socket , 'error' , content , parent_header = msg ['header' ])
380
-
381
- content = {
382
- 'execution_state' : "idle" ,
383
- }
384
- await self .send (self .iopub_socket , 'status' , content , parent_header = msg ['header' ])
385
- return
386
-
387
- # if True or isinstance(self.ast_ctx.ast, ast.Expr):
388
- _LOGGER .debug ("Executing: '%s' got result %s" , code , result )
389
- if result is not None :
390
- content = {
391
- 'execution_count' : self .execution_count ,
392
- 'data' : {"text/plain" : repr (result )},
393
- 'metadata' : {}
394
- }
395
- await self .send (self .iopub_socket , 'execute_result' , content , parent_header = msg ['header' ])
396
-
340
+ if exc :
341
+ traceback_mesg = self .ast_ctx .get_exception_long ().split ("\n " )
397
342
398
343
metadata = {
399
344
"dependencies_met" : True ,
400
345
"engine" : self .engine_id ,
401
- "status" : "ok " ,
346
+ "status" : "error " ,
402
347
"started" : datetime .datetime .now ().isoformat (),
403
348
}
404
349
content = {
405
- "status" : "ok" ,
406
- "execution_count" : self . execution_count ,
407
- "user_variables" : {},
408
- "payload" : [],
409
- "user_expressions" : {} ,
350
+ 'execution_count' : self . execution_count ,
351
+ 'status' : 'error' ,
352
+ 'ename' : type ( exc ). __name__ , # Exception name, as a string
353
+ 'evalue' : str ( exc ), # Exception value, as a string
354
+ 'traceback' : traceback_mesg ,
410
355
}
356
+ _LOGGER .debug ("Executing '%s' got exception: %s" , code , content )
411
357
await self .send (shell_socket , 'execute_reply' , content , metadata = metadata ,
412
358
parent_header = msg ['header' ], identities = identities )
413
- if msg [ ' content' ]. get ( "store_history" , True ):
414
- self .execution_count += 1
415
- elif msg [ 'header' ][ "msg_type" ] == "kernel_info_request" :
359
+ del content [ "execution_count" ], content [ "status" ]
360
+ await self .send ( self . iopub_socket , 'error' , content , parent_header = msg [ 'header' ])
361
+
416
362
content = {
417
- "protocol_version" : "5.3" ,
418
- "ipython_version" : [1 , 1 , 0 , "" ],
419
- "language_version" : [0 , 0 , 1 ],
420
- "language" : "python" ,
421
- "implementation" : "python" ,
422
- "implementation_version" : "3.7" ,
423
- "language_info" : {
424
- "name" : "python" ,
425
- "version" : "1.0" ,
426
- 'mimetype' : "" ,
427
- 'file_extension' : ".py" ,
428
- #'pygments_lexer': "",
429
- 'codemirror_mode' : "" ,
430
- 'nbconvert_exporter' : "" ,
431
- },
432
- "banner" : ""
363
+ 'execution_state' : "idle" ,
433
364
}
434
- await self .send (shell_socket , 'kernel_info_reply' , content , parent_header = msg ['header' ], identities = identities )
435
- elif msg ['header' ]["msg_type" ] == "complete_request" :
436
365
await self .send (self .iopub_socket , 'status' , content , parent_header = msg ['header' ])
366
+ if msg ['content' ].get ("store_history" , True ):
367
+ self .execution_count += 1
368
+ return
437
369
438
- code = msg ["content" ]["code" ]
439
- posn = msg ["content" ]["cursor_pos" ]
440
- match = self .completion_re .match (code [0 :posn ].lower ())
441
- if match :
442
- root = match [1 ].lower ()
443
- words = self .ast_ctx .state .completions (root )
444
- words = words .union (await self .ast_ctx .handler .service_completions (root ))
445
- words = words .union (await self .ast_ctx .handler .func_completions (root ))
446
- words = words .union (self .ast_ctx .completions (root ))
447
- else :
448
- root = ""
449
- words = set ()
450
- # _LOGGER.debug(f"complete_request code={code}, posn={posn}, root={root}, words={words}")
370
+ # if True or isinstance(self.ast_ctx.ast, ast.Expr):
371
+ _LOGGER .debug ("Executing: '%s' got result %s" , code , result )
372
+ if result is not None :
451
373
content = {
452
- "status" : "ok" ,
453
- "matches" : sorted (list (words )),
454
- "cursor_start" : msg ["content" ]["cursor_pos" ] - len (root ),
455
- "cursor_end" : msg ["content" ]["cursor_pos" ],
456
- "metadata" : {},
374
+ 'execution_count' : self .execution_count ,
375
+ 'data' : {"text/plain" : repr (result )},
376
+ 'metadata' : {}
457
377
}
458
- await self .send (shell_socket , 'complete_reply ' , content , parent_header = msg ['header' ], identities = identities )
378
+ await self .send (self . iopub_socket , 'execute_result ' , content , parent_header = msg ['header' ])
459
379
460
- elif msg ['header' ]["msg_type" ] == "is_complete_request" :
461
- code = msg ['content' ]["code" ]
462
- self .ast_ctx .parse (code )
463
- exc = self .ast_ctx .get_exception_obj ()
380
+ metadata = {
381
+ "dependencies_met" : True ,
382
+ "engine" : self .engine_id ,
383
+ "status" : "ok" ,
384
+ "started" : datetime .datetime .now ().isoformat (),
385
+ }
386
+ content = {
387
+ "status" : "ok" ,
388
+ "execution_count" : self .execution_count ,
389
+ "user_variables" : {},
390
+ "payload" : [],
391
+ "user_expressions" : {},
392
+ }
393
+ await self .send (shell_socket , 'execute_reply' , content , metadata = metadata ,
394
+ parent_header = msg ['header' ], identities = identities )
395
+ if msg ['content' ].get ("store_history" , True ):
396
+ self .execution_count += 1
397
+
398
+ elif msg ['header' ]["msg_type" ] == "kernel_info_request" :
399
+ content = {
400
+ "protocol_version" : "5.3" ,
401
+ "ipython_version" : [1 , 1 , 0 , "" ],
402
+ "language_version" : [0 , 0 , 1 ],
403
+ "language" : "python" ,
404
+ "implementation" : "python" ,
405
+ "implementation_version" : "3.7" ,
406
+ "language_info" : {
407
+ "name" : "python" ,
408
+ "version" : "1.0" ,
409
+ 'mimetype' : "" ,
410
+ 'file_extension' : ".py" ,
411
+ #'pygments_lexer': "",
412
+ 'codemirror_mode' : "" ,
413
+ 'nbconvert_exporter' : "" ,
414
+ },
415
+ "banner" : ""
416
+ }
417
+ await self .send (shell_socket , 'kernel_info_reply' , content , parent_header = msg ['header' ], identities = identities )
464
418
465
- # determine indent of last line
466
- indent = 0
467
- i = code .rfind ("\n " )
468
- if i >= 0 :
469
- while i + 1 < len (code ) and code [i + 1 ] == " " :
470
- i += 1
471
- indent += 1
472
- if exc is None :
473
- if indent == 0 :
474
- content = {
475
- # One of 'complete', 'incomplete', 'invalid', 'unknown'
476
- "status" : 'complete' ,
477
- # If status is 'incomplete', indent should contain the characters to use
478
- # to indent the next line. This is only a hint: frontends may ignore it
479
- # and use their own autoindentation rules. For other statuses, this
480
- # field does not exist.
481
- #"indent": str,
482
- }
483
- else :
484
- content = {
485
- "status" : 'incomplete' ,
486
- "indent" : " " * indent ,
487
- }
419
+ elif msg ['header' ]["msg_type" ] == "complete_request" :
420
+ await self .send (self .iopub_socket , 'status' , content , parent_header = msg ['header' ])
421
+
422
+ code = msg ["content" ]["code" ]
423
+ posn = msg ["content" ]["cursor_pos" ]
424
+ match = self .completion_re .match (code [0 :posn ].lower ())
425
+ if match :
426
+ root = match [1 ].lower ()
427
+ words = self .ast_ctx .state .completions (root )
428
+ words = words .union (await self .ast_ctx .handler .service_completions (root ))
429
+ words = words .union (await self .ast_ctx .handler .func_completions (root ))
430
+ words = words .union (self .ast_ctx .completions (root ))
431
+ else :
432
+ root = ""
433
+ words = set ()
434
+ # _LOGGER.debug(f"complete_request code={code}, posn={posn}, root={root}, words={words}")
435
+ content = {
436
+ "status" : "ok" ,
437
+ "matches" : sorted (list (words )),
438
+ "cursor_start" : msg ["content" ]["cursor_pos" ] - len (root ),
439
+ "cursor_end" : msg ["content" ]["cursor_pos" ],
440
+ "metadata" : {},
441
+ }
442
+ await self .send (shell_socket , 'complete_reply' , content , parent_header = msg ['header' ], identities = identities )
443
+
444
+ elif msg ['header' ]["msg_type" ] == "is_complete_request" :
445
+ code = msg ['content' ]["code" ]
446
+ self .ast_ctx .parse (code )
447
+ exc = self .ast_ctx .get_exception_obj ()
448
+
449
+ # determine indent of last line
450
+ indent = 0
451
+ i = code .rfind ("\n " )
452
+ if i >= 0 :
453
+ while i + 1 < len (code ) and code [i + 1 ] == " " :
454
+ i += 1
455
+ indent += 1
456
+ if exc is None :
457
+ if indent == 0 :
458
+ content = {
459
+ # One of 'complete', 'incomplete', 'invalid', 'unknown'
460
+ "status" : 'complete' ,
461
+ # If status is 'incomplete', indent should contain the characters to use
462
+ # to indent the next line. This is only a hint: frontends may ignore it
463
+ # and use their own autoindentation rules. For other statuses, this
464
+ # field does not exist.
465
+ #"indent": str,
466
+ }
488
467
else :
489
- #
490
- # if the syntax error is right at the end, then we label it incomplete,
491
- # otherwise it's invalid
492
- #
493
- if str (exc ).find ("EOF while" ) >= 0 :
494
- # if error is at ":" then increase indent
495
- if hasattr (exc , "lineno" ):
496
- line = code .split ("\n " )[exc .lineno - 1 ]
497
- if self .colon_end_re .match (line ):
498
- indent += 4
499
- content = {
500
- "status" : 'incomplete' ,
501
- "indent" : " " * indent ,
502
- }
503
- else :
504
- content = {
505
- "status" : 'invalid' ,
506
- }
507
- # _LOGGER.debug(f"is_complete_request code={code}, exc={exc}, content={content}")
508
- await self .send (shell_socket , 'is_complete_reply' , content , parent_header = msg ['header' ], identities = identities )
509
- elif msg ['header' ]["msg_type" ] == "comm_info_request" :
510
- content = {
511
- "comms" : {}
512
- }
513
- await self .send (shell_socket , 'comm_info_reply' , content , parent_header = msg ['header' ], identities = identities )
514
- elif msg ['header' ]["msg_type" ] == "history_request" :
515
- content = {
516
- "history" : []
517
- }
518
- await self .send (shell_socket , 'history_reply' , content , parent_header = msg ['header' ], identities = identities )
468
+ content = {
469
+ "status" : 'incomplete' ,
470
+ "indent" : " " * indent ,
471
+ }
519
472
else :
520
- _LOGGER .error ("unknown msg_type: %s" , msg ['header' ]["msg_type" ])
473
+ #
474
+ # if the syntax error is right at the end, then we label it incomplete,
475
+ # otherwise it's invalid
476
+ #
477
+ if str (exc ).find ("EOF while" ) >= 0 :
478
+ # if error is at ":" then increase indent
479
+ if hasattr (exc , "lineno" ):
480
+ line = code .split ("\n " )[exc .lineno - 1 ]
481
+ if self .colon_end_re .match (line ):
482
+ indent += 4
483
+ content = {
484
+ "status" : 'incomplete' ,
485
+ "indent" : " " * indent ,
486
+ }
487
+ else :
488
+ content = {
489
+ "status" : 'invalid' ,
490
+ }
491
+ # _LOGGER.debug(f"is_complete_request code={code}, exc={exc}, content={content}")
492
+ await self .send (shell_socket , 'is_complete_reply' , content , parent_header = msg ['header' ], identities = identities )
521
493
494
+ elif msg ['header' ]["msg_type" ] == "comm_info_request" :
522
495
content = {
523
- 'execution_state' : "idle" ,
496
+ "comms" : {}
524
497
}
525
- await self .send (self .iopub_socket , 'status' , content , parent_header = msg ['header' ])
498
+ await self .send (shell_socket , 'comm_info_reply' , content , parent_header = msg ['header' ], identities = identities )
499
+
500
+ elif msg ['header' ]["msg_type" ] == "history_request" :
501
+ content = {
502
+ "history" : []
503
+ }
504
+ await self .send (shell_socket , 'history_reply' , content , parent_header = msg ['header' ], identities = identities )
505
+
506
+ else :
507
+ _LOGGER .error ("unknown msg_type: %s" , msg ['header' ]["msg_type" ])
508
+
509
+ content = {
510
+ 'execution_state' : "idle" ,
511
+ }
512
+ await self .send (self .iopub_socket , 'status' , content , parent_header = msg ['header' ])
526
513
527
514
async def control_listen (self , reader , writer ):
528
515
"""Task that listens to control messages."""
0 commit comments