@@ -191,6 +191,9 @@ async def forward_data_task(
191191 while True :
192192 data = await reader .read (8192 )
193193 if len (data ) == 0 :
194+ print (
195+ f"{ PKG_NAME } : { self .name } { dir_str } : read EOF; shutdown with exit_status={ exit_status } "
196+ )
194197 await exit_q .put (exit_status )
195198 return
196199 if self .verbose >= 4 :
@@ -210,17 +213,15 @@ async def forward_data_task(
210213# exit since Jupyter thinks the kernel has stopped. We sit in the
211214# middle of the heartbeat loop so we know when the kernel is stopped.
212215#
213- async def kernel_run (config_filename : str , verbose : int ) -> None :
216+ async def kernel_run (config : dict , verbose : int ) -> None :
214217 """Start a new pyscript kernel."""
215218 port_names = ["hb_port" , "stdin_port" , "shell_port" , "iopub_port" , "control_port" ]
216219 hass_host = CONFIG_SETTINGS ["hass_host" ]
217220 hass_url = CONFIG_SETTINGS ["hass_url" ].rstrip ("/" )
218221 hass_proxy = CONFIG_SETTINGS ["hass_proxy" ]
219222
220223 connector = proxy .ProxyConnector .from_url (hass_proxy ) if hass_proxy else None
221- headers = {
222- "Authorization" : f'Bearer { CONFIG_SETTINGS ["hass_token" ]} ' ,
223- }
224+ headers = {"Authorization" : f'Bearer { CONFIG_SETTINGS ["hass_token" ]} ' }
224225 session = aiohttp .ClientSession (connector = connector , headers = headers , raise_for_status = True )
225226
226227 async def do_request (
@@ -237,17 +238,13 @@ async def do_request(
237238 print (
238239 f"{ PKG_NAME } : request failed with { err .status } : { err .message } (url={ err .request_info .url } )"
239240 )
241+ await session .close ()
240242 sys .exit (1 )
241243 except Exception as err :
242244 print (f"{ PKG_NAME } : got error { err } (url={ url } )" )
245+ await session .close ()
243246 sys .exit (1 )
244247
245- with open (config_filename , "r" ) as fdesc :
246- config = json .load (fdesc )
247-
248- if verbose >= 1 :
249- print (f"{ PKG_NAME } : got jupyter client config={ config } " )
250-
251248 #
252249 # The kernel generates its own port numbers since it might be on another host,
253250 # so we delete the client ports. Also, it needs the name of a state variable to
@@ -349,18 +346,74 @@ async def do_request(
349346 sys .exit (exit_status )
350347
351348
349+ def remove_quotes (string ):
350+ """Strip leading/trailing quotes from string, which VSCode strangely adds to arguments."""
351+ if string [0 ] == string [- 1 ] and string [0 ] in ('"' , "'" ):
352+ return string [1 :- 1 ]
353+ if len (string ) > 1 and string [0 ] == "b" and string [1 ] == string [- 1 ] and string [1 ] in ('"' , "'" ):
354+ return string [2 :- 1 ]
355+ return string
356+
357+
352358def main () -> None :
353359 """Main function: start a new pyscript kernel."""
360+
354361 parser = argparse .ArgumentParser (prog = PKG_NAME )
355- parser .add_argument ("config_file" , type = str , help = "json kernel config file generated by Jupyter" )
356362 parser .add_argument (
357- "-v" , "--verbose" , action = "count" , help = "increase output verbosity (repeat up to 4x)" ,
363+ "-v" , "--verbose" , action = "count" , help = "increase verbosity (repeat up to 4x)" , default = 0
358364 )
359365 parser .add_argument (
360366 "-k" , "--kernel-name" , type = str , help = "kernel name" , default = "pyscript" , dest = "kernel_name"
361367 )
368+ parser .add_argument ("-f" , "--f" , type = str , help = "json config file" , dest = "config_file" )
369+ parser .add_argument ("--ip" , type = str , help = "ip address" )
370+ parser .add_argument ("--stdin" , type = int , help = "stdin port" )
371+ parser .add_argument ("--control" , type = int , help = "control port" )
372+ parser .add_argument ("--hb" , type = int , help = "hb port" )
373+ parser .add_argument ("--shell" , type = int , help = "shell port" )
374+ parser .add_argument ("--iopub" , type = int , help = "iopub port" )
375+ parser .add_argument (
376+ "--Session.signature_scheme" , dest = "signature_scheme" , type = str , help = "signature scheme"
377+ )
378+ parser .add_argument ("--Session.key" , type = str , dest = "key" , help = "session key" )
379+ parser .add_argument ("--transport" , type = str , help = "transport" )
380+
362381 args = parser .parse_args ()
363382
364383 load_config (args .kernel_name )
365384
366- asyncio .run (kernel_run (args .config_file , args .verbose if args .verbose else 0 ))
385+ if args .config_file is not None and args .ip is None and args .stdin is None :
386+ #
387+ # read the json config file (-f or --f) to get the connection parameters
388+ #
389+ with open (args .config_file , "r" ) as fdesc :
390+ config = json .load (fdesc )
391+ else :
392+ #
393+ # no json config file, so use the command-line arguments instead
394+ #
395+ config = {
396+ "ip" : args .ip ,
397+ "stdin_port" : args .stdin ,
398+ "control_port" : args .control ,
399+ "hb_port" : args .hb ,
400+ "iopub_port" : args .iopub ,
401+ "shell_port" : args .shell ,
402+ "transport" : remove_quotes (args .transport ),
403+ "signature_scheme" : remove_quotes (args .signature_scheme ),
404+ "key" : remove_quotes (args .key ),
405+ }
406+ missing = []
407+ for arg , value in sorted (config .items ()):
408+ if value is None :
409+ missing .append (arg )
410+ if missing :
411+ print (
412+ f"{ PKG_NAME } : missing arguments: --{ ', --' .join (missing )} , (or specify --f config_file instead)"
413+ )
414+ sys .exit (1 )
415+
416+ if args .verbose >= 1 :
417+ print (f"{ PKG_NAME } : got jupyter client config={ config } " )
418+
419+ asyncio .run (kernel_run (config , args .verbose ))
0 commit comments