88import re
99import tempfile
1010import time
11+ from typing import List , Optional , Dict , Tuple , Any , Callable , Union
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 on (self , pre_start_hook = None ):
263+ def on (self , pre_start_hook : Optional [ Callable [[], None ]] = None ) -> None :
263264 """Start the QEMU subprocess, accept the unix socket connection, run the
264265 pre_start_hook if applicable and start the emulator using a QMP Command"""
265266 if self .status :
@@ -295,7 +296,7 @@ def on(self, pre_start_hook=None):
295296 self .monitor_command ("cont" )
296297
297298 @step ()
298- def off (self ):
299+ def off (self ) -> None :
299300 """Stop the emulator using a monitor command and await the exitcode"""
300301 if not self .status :
301302 return
@@ -306,37 +307,38 @@ def off(self):
306307 self ._child = None
307308 self .status = 0
308309
309- def cycle (self ):
310+ def cycle (self ) -> None :
310311 """Cycle the emulator by restarting it"""
311312 self .off ()
312313 self .on ()
313314
314315 @step (result = True , args = ['command' , 'arguments' ])
315- def monitor_command (self , command , arguments = {}):
316+ def monitor_command (self , command : str , arguments : Dict [ str , Any ] = {}) -> Any :
316317 """Execute a monitor_command via the QMP"""
317318 if not self .status :
318319 raise ExecutionError (
319320 "Can't use monitor command on non-running target" )
320321 return self .qmp .execute (command , arguments )
321322
322- def _add_port_forward (self , proto , local_address , local_port , remote_address , remote_port ) :
323+ def _add_port_forward (self , proto : str , local_address : str , local_port : int , remote_address : str , remote_port : int ) -> None :
323324 self .monitor_command (
324325 "human-monitor-command" ,
325326 {"command-line" : f"hostfwd_add { proto } :{ local_address } :{ local_port } -{ remote_address } :{ remote_port } " },
326327 )
327328
328- def add_port_forward (self , proto , local_address , local_port , remote_address , remote_port ) :
329+ def add_port_forward (self , proto : str , local_address : str , local_port : int , remote_address : str , remote_port : int ) -> None :
329330 self ._add_port_forward (proto , local_address , local_port , remote_address , remote_port )
330- self ._forwarded_ports [(proto , local_address , local_port )] = (proto , local_address , local_port , remote_address , remote_port )
331+ self ._forwarded_ports [(proto , local_address , local_port )] = (
332+ proto , local_address , local_port , remote_address , remote_port )
331333
332- def remove_port_forward (self , proto , local_address , local_port ) :
334+ def remove_port_forward (self , proto : str , local_address : str , local_port : int ) -> None :
333335 del self ._forwarded_ports [(proto , local_address , local_port )]
334336 self .monitor_command (
335337 "human-monitor-command" ,
336338 {"command-line" : f"hostfwd_remove { proto } :{ local_address } :{ local_port } " },
337339 )
338340
339- def _read (self , size = 1 , timeout = 10 , max_size = None ):
341+ def _read (self , size : int = 1 , timeout : float = 10 , max_size : Optional [ int ] = None ) -> bytes :
340342 ready , _ , _ = select .select ([self ._clientsocket ], [], [], timeout )
341343 if ready :
342344 # Collect some more data
@@ -349,8 +351,8 @@ def _read(self, size=1, timeout=10, max_size=None):
349351 raise TIMEOUT (f"Timeout of { timeout :.2f} seconds exceeded" )
350352 return res
351353
352- def _write (self , data ) :
354+ def _write (self , data : bytes ) -> int :
353355 return self ._clientsocket .send (data )
354356
355- def __str__ (self ):
357+ def __str__ (self ) -> str :
356358 return f"QemuDriver({ self .target .name } )"
0 commit comments