4455
66import codecs
7+ import contextlib
78import re
89import select
910import datetime
1920from moler .helpers import all_chars_to_hex
2021from moler .helpers import non_printable_chars_to_hex
2122from moler .util import tracked_thread
23+ from moler .connection import Connection
24+ from typing import Tuple , List
2225
2326
2427class ThreadedTerminal (IOConnection ):
@@ -30,15 +33,15 @@ class ThreadedTerminal(IOConnection):
3033
3134 def __init__ (
3235 self ,
33- moler_connection ,
34- cmd = "/bin/bash" ,
35- select_timeout = 0.002 ,
36- read_buffer_size = 4096 ,
37- first_prompt = r"[%$#\]]+" ,
38- target_prompt = r"moler_bash#" ,
39- set_prompt_cmd = 'unset PROMPT_COMMAND; export PS1="moler_bash# "\n ' ,
40- dimensions = (100 , 300 ),
41- terminal_delayafterclose = 0.2 ,
36+ moler_connection : Connection ,
37+ cmd : str = "/bin/bash" ,
38+ select_timeout : float = 0.002 ,
39+ read_buffer_size : int = 4096 ,
40+ first_prompt : str = r"[%$#\]]+" ,
41+ target_prompt : str = r"moler_bash#" ,
42+ set_prompt_cmd : str = 'unset PROMPT_COMMAND; export PS1="moler_bash# "\n ' ,
43+ dimensions : Tuple [ int , int ] = (100 , 300 ),
44+ terminal_delayafterclose : float = 0.2 ,
4245 ):
4346 """# TODO: # 'export PS1="moler_bash\\ $ "\n ' would give moler_bash# for root and moler_bash$ for user
4447 :param moler_connection: Moler's connection to join with
@@ -51,7 +54,7 @@ def __init__(
5154 :param dimensions: dimensions of the psuedoterminal
5255 :param terminal_delayafterclose: delay for checking if terminal was properly closed
5356 """
54- super (ThreadedTerminal , self ).__init__ (moler_connection = moler_connection )
57+ super ().__init__ (moler_connection = moler_connection )
5558 self .debug_hex_on_non_printable_chars = (
5659 False # Set True to log incoming non printable chars as hex.
5760 )
@@ -60,7 +63,7 @@ def __init__(
6063 self ._shell_operable : threading .Event = threading .Event ()
6164 self ._export_sent = False
6265 self .pulling_thread = None
63- self .read_buffer = ""
66+ self .read_buffer : str = ""
6467
6568 self ._select_timeout = select_timeout
6669 self ._read_buffer_size = read_buffer_size
@@ -74,15 +77,16 @@ def __init__(
7477 )
7578 self ._terminal_delayafterclose = terminal_delayafterclose
7679
77- def open (self ):
80+ def open (self ) -> contextlib . closing :
7881 """Open ThreadedTerminal connection & start thread pulling data from it."""
79- ret = super (ThreadedTerminal , self ).open ()
82+ ret = super ().open ()
8083
8184 if not self ._terminal :
8285 self .moler_connection .open ()
8386 self ._terminal = PtyProcessUnicode .spawn (
8487 self ._cmd , dimensions = self .dimensions
8588 )
89+ assert self ._terminal is not None
8690 self ._terminal .delayafterclose = self ._terminal_delayafterclose
8791 # need to not replace not unicode data instead of raise exception
8892 self ._terminal .decoder = codecs .getincrementaldecoder ("utf-8" )(
@@ -112,12 +116,12 @@ def open(self):
112116
113117 return ret
114118
115- def close (self ):
119+ def close (self ) -> None :
116120 """Close ThreadedTerminal connection & stop pulling thread."""
117121 if self .pulling_thread :
118122 self .pulling_thread .join ()
119123 self .moler_connection .shutdown ()
120- super (ThreadedTerminal , self ).close ()
124+ super ().close ()
121125
122126 if self ._terminal and self ._terminal .isalive ():
123127 self ._notify_on_disconnect ()
@@ -131,19 +135,20 @@ def close(self):
131135 self .pulling_thread = None
132136 self .read_buffer = ""
133137
134- def send (self , data ) :
138+ def send (self , data : str ) -> None :
135139 """Write data into ThreadedTerminal connection."""
136140 if self ._terminal :
137141 self ._terminal .write (data )
138142
139143 @tracked_thread .log_exit_exception
140- def pull_data (self , pulling_done ) :
144+ def pull_data (self , pulling_done : threading . Event ) -> None :
141145 """Pull data from ThreadedTerminal connection."""
142146 logging .getLogger ("moler_threads" ).debug (f"ENTER { self } " )
143- heartbeat = tracked_thread .report_alive ()
144- reads = []
147+ heartbeat : bool = tracked_thread .report_alive ()
148+ reads : List [ int ] = []
145149
146150 while not pulling_done .is_set ():
151+ assert self ._terminal is not None
147152 if next (heartbeat ):
148153 logging .getLogger ("moler_threads" ).debug (f"ALIVE { self } " )
149154 try :
@@ -174,7 +179,7 @@ def pull_data(self, pulling_done):
174179 pulling_done .set ()
175180 logging .getLogger ("moler_threads" ).debug (f"EXIT { self } " )
176181
177- def _verify_shell_is_operable (self , data ) :
182+ def _verify_shell_is_operable (self , data : str ) -> None :
178183 self .read_buffer = self .read_buffer + data
179184 lines = self .read_buffer .splitlines ()
180185
0 commit comments