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 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