@@ -7,51 +7,53 @@ def do_repl_main_loop(
77 state , console_in , console_out_write , * , escape_non_printable , code_to_inject , file_to_inject
88):
99 while True :
10- console_in .waitchar (state .transport .serial )
11- c = console_in .readchar ()
12- if c :
13- if c in (b"\x1d " , b"\x18 " ): # ctrl-] or ctrl-x, quit
14- break
15- elif c == b"\x04 " : # ctrl-D
16- # special handling needed for ctrl-D if filesystem is mounted
17- state .transport .write_ctrl_d (console_out_write )
18- elif c == b"\x0a " and code_to_inject is not None : # ctrl-j, inject code
19- state .transport .serial .write (code_to_inject )
20- elif c == b"\x0b " and file_to_inject is not None : # ctrl-k, inject script
21- console_out_write (bytes ("Injecting %s\r \n " % file_to_inject , "utf8" ))
22- state .transport .enter_raw_repl (soft_reset = False )
23- with open (file_to_inject , "rb" ) as f :
24- pyfile = f .read ()
25- try :
26- state .transport .exec_raw_no_follow (pyfile )
27- except TransportError as er :
28- console_out_write (b"Error:\r \n " )
29- console_out_write (er )
30- state .transport .exit_raw_repl ()
31- else :
32- state .transport .serial .write (c )
33-
3410 try :
11+ console_in .waitchar (state .transport .serial )
12+ c = console_in .readchar ()
13+ if c :
14+ if c in (b"\x1d " , b"\x18 " ): # ctrl-] or ctrl-x, quit
15+ break
16+ elif c == b"\x04 " : # ctrl-D
17+ # special handling needed for ctrl-D if filesystem is mounted
18+ state .transport .write_ctrl_d (console_out_write )
19+ elif c == b"\x0a " and code_to_inject is not None : # ctrl-j, inject code
20+ state .transport .serial .write (code_to_inject )
21+ elif c == b"\x0b " and file_to_inject is not None : # ctrl-k, inject script
22+ console_out_write (bytes ("Injecting %s\r \n " % file_to_inject , "utf8" ))
23+ state .transport .enter_raw_repl (soft_reset = False )
24+ with open (file_to_inject , "rb" ) as f :
25+ pyfile = f .read ()
26+ try :
27+ state .transport .exec_raw_no_follow (pyfile )
28+ except TransportError as er :
29+ console_out_write (b"Error:\r \n " )
30+ console_out_write (er )
31+ state .transport .exit_raw_repl ()
32+ else :
33+ state .transport .serial .write (c )
34+
3535 n = state .transport .serial .inWaiting ()
36- except OSError as er :
37- if er .args [0 ] == 5 : # IO error, device disappeared
38- print ("device disconnected" )
39- break
36+ if n > 0 :
37+ dev_data_in = state .transport .serial .read (n )
38+ if dev_data_in is not None :
39+ if escape_non_printable :
40+ # Pass data through to the console, with escaping of non-printables.
41+ console_data_out = bytearray ()
42+ for c in dev_data_in :
43+ if c in (8 , 9 , 10 , 13 , 27 ) or 32 <= c <= 126 :
44+ console_data_out .append (c )
45+ else :
46+ console_data_out .extend (b"[%02x]" % c )
47+ else :
48+ console_data_out = dev_data_in
49+ console_out_write (console_data_out )
4050
41- if n > 0 :
42- dev_data_in = state .transport .serial .read (n )
43- if dev_data_in is not None :
44- if escape_non_printable :
45- # Pass data through to the console, with escaping of non-printables.
46- console_data_out = bytearray ()
47- for c in dev_data_in :
48- if c in (8 , 9 , 10 , 13 , 27 ) or 32 <= c <= 126 :
49- console_data_out .append (c )
50- else :
51- console_data_out .extend (b"[%02x]" % c )
52- else :
53- console_data_out = dev_data_in
54- console_out_write (console_data_out )
51+ except OSError as er :
52+ if _is_disconnect_exception (er ):
53+ return True
54+ else :
55+ raise
56+ return False
5557
5658
5759def do_repl (state , args ):
@@ -86,7 +88,7 @@ def console_out_write(b):
8688 capture_file .flush ()
8789
8890 try :
89- do_repl_main_loop (
91+ return do_repl_main_loop (
9092 state ,
9193 console ,
9294 console_out_write ,
@@ -98,3 +100,22 @@ def console_out_write(b):
98100 console .exit ()
99101 if capture_file is not None :
100102 capture_file .close ()
103+
104+
105+ def _is_disconnect_exception (exception ):
106+ """
107+ Check if an exception indicates device disconnect.
108+
109+ Returns True if the exception indicates the device has disconnected,
110+ False otherwise.
111+ """
112+ if isinstance (exception , OSError ):
113+ if hasattr (exception , 'args' ) and len (exception .args ) > 0 :
114+ # IO error, device disappeared
115+ if exception .args [0 ] == 5 :
116+ return True
117+ # Check for common disconnect messages in the exception string
118+ exception_str = str (exception )
119+ disconnect_indicators = ["Write timeout" , "Device disconnected" , "ClearCommError failed" ]
120+ return any (indicator in exception_str for indicator in disconnect_indicators )
121+ return False
0 commit comments