88import  re 
99import  tempfile 
1010import  time 
11+ from  typing  import  List , Optional , Dict , Tuple , Any 
1112
1213import  attr 
1314from  pexpect  import  TIMEOUT 
@@ -95,18 +96,18 @@ class QEMUDriver(ConsoleExpectMixin, Driver, PowerProtocol, ConsoleProtocol):
9596        default = None ,
9697        validator = attr .validators .optional (attr .validators .instance_of (str )))
9798
98-     def  __attrs_post_init__ (self ):
99+     def  __attrs_post_init__ (self )  ->   None :
99100        super ().__attrs_post_init__ ()
100-         self .status  =  0 
101-         self .txdelay  =  None 
102-         self ._child  =  None 
103-         self ._tempdir  =  None 
104-         self ._socket  =  None 
105-         self ._clientsocket  =  None 
106-         self ._forwarded_ports  =  {}
101+         self .status :  int  =  0 
102+         self .txdelay :  Optional [ float ]  =  None 
103+         self ._child :  Optional [ subprocess . Popen ]  =  None 
104+         self ._tempdir :  Optional [ str ]  =  None 
105+         self ._socket :  Optional [ socket . socket ]  =  None 
106+         self ._clientsocket :  Optional [ socket . socket ]  =  None 
107+         self ._forwarded_ports :  Dict [ Tuple [ str ,  str ,  int ],  Tuple [ str ,  str ,  int ,  str ,  int ]]  =  {}
107108        atexit .register (self ._atexit )
108109
109-     def  _atexit (self ):
110+     def  _atexit (self )  ->   None :
110111        if  not  self ._child :
111112            return 
112113        self ._child .terminate ()
@@ -116,7 +117,7 @@ def _atexit(self):
116117            self ._child .kill ()
117118            self ._child .communicate (timeout = 1 )
118119
119-     def  get_qemu_version (self , qemu_bin ) :
120+     def  get_qemu_version (self , qemu_bin :  str )  ->   Tuple [ int ,  int ,  int ] :
120121        p  =  subprocess .run ([qemu_bin , "-version" ], stdout = subprocess .PIPE , encoding = "utf-8" )
121122        if  p .returncode  !=  0 :
122123            raise  ExecutionError (f"Unable to get QEMU version. QEMU exited with: { p .returncode }  " )
@@ -127,7 +128,7 @@ def get_qemu_version(self, qemu_bin):
127128
128129        return  (int (m .group ('major' )), int (m .group ('minor' )), int (m .group ('micro' )))
129130
130-     def  get_qemu_base_args (self ):
131+     def  get_qemu_base_args (self )  ->   List [ str ] :
131132        """Returns the base command line used for Qemu without the options 
132133        related to QMP. These options can be used to start an interactive 
133134        Qemu manually for debugging tests 
@@ -230,7 +231,7 @@ def get_qemu_base_args(self):
230231
231232        return  cmd 
232233
233-     def  on_activate (self ):
234+     def  on_activate (self )  ->   None :
234235        self ._tempdir  =  tempfile .mkdtemp (prefix = "labgrid-qemu-tmp-" )
235236        sockpath  =  f"{ self ._tempdir }  /serialrw" 
236237        self ._socket  =  socket .socket (socket .AF_UNIX , socket .SOCK_STREAM )
@@ -248,7 +249,7 @@ def on_activate(self):
248249        self ._cmd .append ("-serial" )
249250        self ._cmd .append ("chardev:serialsocket" )
250251
251-     def  on_deactivate (self ):
252+     def  on_deactivate (self )  ->   None :
252253        if  self .status :
253254            self .off ()
254255        if  self ._clientsocket :
@@ -259,7 +260,7 @@ def on_deactivate(self):
259260        shutil .rmtree (self ._tempdir )
260261
261262    @step () 
262-     def  prepare (self ):
263+     def  prepare (self )  ->   None :
263264        """Start the QEMU subprocess and accept the unix socket connection 
264265        if not already prepared.""" 
265266        if  self .status :
@@ -290,7 +291,7 @@ def prepare(self):
290291            self ._add_port_forward (* v ) 
291292
292293    @step () 
293-     def  on (self ):
294+     def  on (self )  ->   None :
294295        """Prepare the instance (only if not done already) and start the emulator 
295296        using a QMP Command""" 
296297        if  not  self ._child :
@@ -299,7 +300,7 @@ def on(self):
299300        self .monitor_command ("cont" )
300301
301302    @step () 
302-     def  off (self ):
303+     def  off (self )  ->   None :
303304        """Stop the emulator using a monitor command and await the exitcode""" 
304305        if  not  self .status :
305306            return 
@@ -310,37 +311,38 @@ def off(self):
310311        self ._child  =  None 
311312        self .status  =  0 
312313
313-     def  cycle (self ):
314+     def  cycle (self )  ->   None :
314315        """Cycle the emulator by restarting it""" 
315316        self .off ()
316317        self .on ()
317318
318319    @step (result = True , args = ['command' , 'arguments' ]) 
319-     def  monitor_command (self , command , arguments = {}):
320+     def  monitor_command (self , command :  str , arguments :  Dict [ str ,  Any ]  =   {})  ->   Any :
320321        """Execute a monitor_command via the QMP""" 
321322        if  not  self .status :
322323            raise  ExecutionError (
323324                "Can't use monitor command on non-running target" )
324325        return  self .qmp .execute (command , arguments )
325326
326-     def  _add_port_forward (self , proto , local_address , local_port , remote_address , remote_port ) :
327+     def  _add_port_forward (self , proto :  str , local_address :  str , local_port :  int , remote_address :  str , remote_port :  int )  ->   None :
327328        self .monitor_command (
328329            "human-monitor-command" ,
329330            {"command-line" : f"hostfwd_add { proto }  :{ local_address }  :{ local_port }  -{ remote_address }  :{ remote_port }  " },
330331        )
331332
332-     def  add_port_forward (self , proto , local_address , local_port , remote_address , remote_port ) :
333+     def  add_port_forward (self , proto :  str , local_address :  str , local_port :  int , remote_address :  str , remote_port :  int )  ->   None :
333334        self ._add_port_forward (proto , local_address , local_port , remote_address , remote_port )
334-         self ._forwarded_ports [(proto , local_address , local_port )] =  (proto , local_address , local_port , remote_address , remote_port )
335+         self ._forwarded_ports [(proto , local_address , local_port )] =  (
336+             proto , local_address , local_port , remote_address , remote_port )
335337
336-     def  remove_port_forward (self , proto , local_address , local_port ) :
338+     def  remove_port_forward (self , proto :  str , local_address :  str , local_port :  int )  ->   None :
337339        del  self ._forwarded_ports [(proto , local_address , local_port )]
338340        self .monitor_command (
339341            "human-monitor-command" ,
340342            {"command-line" : f"hostfwd_remove { proto }  :{ local_address }  :{ local_port }  " },
341343        )
342344
343-     def  _read (self , size = 1 , timeout = 10 , max_size = None ):
345+     def  _read (self , size :  int   =   1 , timeout :  float   =   10 , max_size :  Optional [ int ]  =   None )  ->   bytes :
344346        ready , _ , _  =  select .select ([self ._clientsocket ], [], [], timeout )
345347        if  ready :
346348            # Collect some more data 
@@ -353,8 +355,8 @@ def _read(self, size=1, timeout=10, max_size=None):
353355            raise  TIMEOUT (f"Timeout of { timeout :.2f}   seconds exceeded" )
354356        return  res 
355357
356-     def  _write (self , data ) :
358+     def  _write (self , data :  bytes )  ->   int :
357359        return  self ._clientsocket .send (data )
358360
359-     def  __str__ (self ):
361+     def  __str__ (self )  ->   str :
360362        return  f"QemuDriver({ self .target .name }  )" 
0 commit comments