nixos/test-driver: target python 3.12
This commit is contained in:
parent
5b5f018586
commit
172a35f8ce
@ -17,6 +17,7 @@ find = {}
|
|||||||
test_driver = ["py.typed"]
|
test_driver = ["py.typed"]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
|
target-version = "py312"
|
||||||
line-length = 88
|
line-length = 88
|
||||||
|
|
||||||
lint.select = ["E", "F", "I", "U", "N"]
|
lint.select = ["E", "F", "I", "U", "N"]
|
||||||
|
@ -3,10 +3,10 @@ import re
|
|||||||
import signal
|
import signal
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
from collections.abc import Iterator
|
from collections.abc import Callable, Iterator
|
||||||
from contextlib import AbstractContextManager, contextmanager
|
from contextlib import AbstractContextManager, contextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Callable, Optional, Union
|
from typing import Any
|
||||||
|
|
||||||
from colorama import Fore, Style
|
from colorama import Fore, Style
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ class Driver:
|
|||||||
self,
|
self,
|
||||||
start_command: str | dict,
|
start_command: str | dict,
|
||||||
*,
|
*,
|
||||||
name: Optional[str] = None,
|
name: str | None = None,
|
||||||
keep_vm_state: bool = False,
|
keep_vm_state: bool = False,
|
||||||
) -> Machine:
|
) -> Machine:
|
||||||
# Legacy args handling
|
# Legacy args handling
|
||||||
@ -274,11 +274,11 @@ class Driver:
|
|||||||
|
|
||||||
def polling_condition(
|
def polling_condition(
|
||||||
self,
|
self,
|
||||||
fun_: Optional[Callable] = None,
|
fun_: Callable | None = None,
|
||||||
*,
|
*,
|
||||||
seconds_interval: float = 2.0,
|
seconds_interval: float = 2.0,
|
||||||
description: Optional[str] = None,
|
description: str | None = None,
|
||||||
) -> Union[Callable[[Callable], AbstractContextManager], AbstractContextManager]:
|
) -> Callable[[Callable], AbstractContextManager] | AbstractContextManager:
|
||||||
driver = self
|
driver = self
|
||||||
|
|
||||||
class Poll:
|
class Poll:
|
||||||
|
@ -12,11 +12,11 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from collections.abc import Iterable
|
from collections.abc import Callable, Iterable
|
||||||
from contextlib import _GeneratorContextManager, nullcontext
|
from contextlib import _GeneratorContextManager, nullcontext
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from typing import Any, Callable, Optional
|
from typing import Any
|
||||||
|
|
||||||
from test_driver.logger import AbstractLogger
|
from test_driver.logger import AbstractLogger
|
||||||
|
|
||||||
@ -249,12 +249,12 @@ class Machine:
|
|||||||
start_command: StartCommand
|
start_command: StartCommand
|
||||||
keep_vm_state: bool
|
keep_vm_state: bool
|
||||||
|
|
||||||
process: Optional[subprocess.Popen]
|
process: subprocess.Popen | None
|
||||||
pid: Optional[int]
|
pid: int | None
|
||||||
monitor: Optional[socket.socket]
|
monitor: socket.socket | None
|
||||||
qmp_client: Optional[QMPSession]
|
qmp_client: QMPSession | None
|
||||||
shell: Optional[socket.socket]
|
shell: socket.socket | None
|
||||||
serial_thread: Optional[threading.Thread]
|
serial_thread: threading.Thread | None
|
||||||
|
|
||||||
booted: bool
|
booted: bool
|
||||||
connected: bool
|
connected: bool
|
||||||
@ -274,7 +274,7 @@ class Machine:
|
|||||||
logger: AbstractLogger,
|
logger: AbstractLogger,
|
||||||
name: str = "machine",
|
name: str = "machine",
|
||||||
keep_vm_state: bool = False,
|
keep_vm_state: bool = False,
|
||||||
callbacks: Optional[list[Callable]] = None,
|
callbacks: list[Callable] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.out_dir = out_dir
|
self.out_dir = out_dir
|
||||||
self.tmp_dir = tmp_dir
|
self.tmp_dir = tmp_dir
|
||||||
@ -344,7 +344,7 @@ class Machine:
|
|||||||
return self.wait_for_monitor_prompt()
|
return self.wait_for_monitor_prompt()
|
||||||
|
|
||||||
def wait_for_unit(
|
def wait_for_unit(
|
||||||
self, unit: str, user: Optional[str] = None, timeout: int = 900
|
self, unit: str, user: str | None = None, timeout: int = 900
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Wait for a systemd unit to get into "active" state.
|
Wait for a systemd unit to get into "active" state.
|
||||||
@ -374,7 +374,7 @@ class Machine:
|
|||||||
):
|
):
|
||||||
retry(check_active, timeout)
|
retry(check_active, timeout)
|
||||||
|
|
||||||
def get_unit_info(self, unit: str, user: Optional[str] = None) -> dict[str, str]:
|
def get_unit_info(self, unit: str, user: str | None = None) -> dict[str, str]:
|
||||||
status, lines = self.systemctl(f'--no-pager show "{unit}"', user)
|
status, lines = self.systemctl(f'--no-pager show "{unit}"', user)
|
||||||
if status != 0:
|
if status != 0:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
@ -400,7 +400,7 @@ class Machine:
|
|||||||
self,
|
self,
|
||||||
unit: str,
|
unit: str,
|
||||||
property: str,
|
property: str,
|
||||||
user: Optional[str] = None,
|
user: str | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
status, lines = self.systemctl(
|
status, lines = self.systemctl(
|
||||||
f'--no-pager show "{unit}" --property="{property}"',
|
f'--no-pager show "{unit}" --property="{property}"',
|
||||||
@ -425,7 +425,7 @@ class Machine:
|
|||||||
assert match[1] == property, invalid_output_message
|
assert match[1] == property, invalid_output_message
|
||||||
return match[2]
|
return match[2]
|
||||||
|
|
||||||
def systemctl(self, q: str, user: Optional[str] = None) -> tuple[int, str]:
|
def systemctl(self, q: str, user: str | None = None) -> tuple[int, str]:
|
||||||
"""
|
"""
|
||||||
Runs `systemctl` commands with optional support for
|
Runs `systemctl` commands with optional support for
|
||||||
`systemctl --user`
|
`systemctl --user`
|
||||||
@ -481,7 +481,7 @@ class Machine:
|
|||||||
command: str,
|
command: str,
|
||||||
check_return: bool = True,
|
check_return: bool = True,
|
||||||
check_output: bool = True,
|
check_output: bool = True,
|
||||||
timeout: Optional[int] = 900,
|
timeout: int | None = 900,
|
||||||
) -> tuple[int, str]:
|
) -> tuple[int, str]:
|
||||||
"""
|
"""
|
||||||
Execute a shell command, returning a list `(status, stdout)`.
|
Execute a shell command, returning a list `(status, stdout)`.
|
||||||
@ -549,7 +549,7 @@ class Machine:
|
|||||||
|
|
||||||
return (rc, output.decode(errors="replace"))
|
return (rc, output.decode(errors="replace"))
|
||||||
|
|
||||||
def shell_interact(self, address: Optional[str] = None) -> None:
|
def shell_interact(self, address: str | None = None) -> None:
|
||||||
"""
|
"""
|
||||||
Allows you to directly interact with the guest shell. This should
|
Allows you to directly interact with the guest shell. This should
|
||||||
only be used during test development, not in production tests.
|
only be used during test development, not in production tests.
|
||||||
@ -596,7 +596,7 @@ class Machine:
|
|||||||
break
|
break
|
||||||
self.send_console(char.decode())
|
self.send_console(char.decode())
|
||||||
|
|
||||||
def succeed(self, *commands: str, timeout: Optional[int] = None) -> str:
|
def succeed(self, *commands: str, timeout: int | None = None) -> str:
|
||||||
"""
|
"""
|
||||||
Execute a shell command, raising an exception if the exit status is
|
Execute a shell command, raising an exception if the exit status is
|
||||||
not zero, otherwise returning the standard output. Similar to `execute`,
|
not zero, otherwise returning the standard output. Similar to `execute`,
|
||||||
@ -613,7 +613,7 @@ class Machine:
|
|||||||
output += out
|
output += out
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def fail(self, *commands: str, timeout: Optional[int] = None) -> str:
|
def fail(self, *commands: str, timeout: int | None = None) -> str:
|
||||||
"""
|
"""
|
||||||
Like `succeed`, but raising an exception if the command returns a zero
|
Like `succeed`, but raising an exception if the command returns a zero
|
||||||
status.
|
status.
|
||||||
@ -725,7 +725,7 @@ class Machine:
|
|||||||
with self.nested(f"waiting for {regexp} to appear on tty {tty}"):
|
with self.nested(f"waiting for {regexp} to appear on tty {tty}"):
|
||||||
retry(tty_matches, timeout)
|
retry(tty_matches, timeout)
|
||||||
|
|
||||||
def send_chars(self, chars: str, delay: Optional[float] = 0.01) -> None:
|
def send_chars(self, chars: str, delay: float | None = 0.01) -> None:
|
||||||
"""
|
"""
|
||||||
Simulate typing a sequence of characters on the virtual keyboard,
|
Simulate typing a sequence of characters on the virtual keyboard,
|
||||||
e.g., `send_chars("foobar\n")` will type the string `foobar`
|
e.g., `send_chars("foobar\n")` will type the string `foobar`
|
||||||
@ -799,10 +799,10 @@ class Machine:
|
|||||||
with self.nested(f"waiting for TCP port {port} on {addr} to be closed"):
|
with self.nested(f"waiting for TCP port {port} on {addr} to be closed"):
|
||||||
retry(port_is_closed, timeout)
|
retry(port_is_closed, timeout)
|
||||||
|
|
||||||
def start_job(self, jobname: str, user: Optional[str] = None) -> tuple[int, str]:
|
def start_job(self, jobname: str, user: str | None = None) -> tuple[int, str]:
|
||||||
return self.systemctl(f"start {jobname}", user)
|
return self.systemctl(f"start {jobname}", user)
|
||||||
|
|
||||||
def stop_job(self, jobname: str, user: Optional[str] = None) -> tuple[int, str]:
|
def stop_job(self, jobname: str, user: str | None = None) -> tuple[int, str]:
|
||||||
return self.systemctl(f"stop {jobname}", user)
|
return self.systemctl(f"stop {jobname}", user)
|
||||||
|
|
||||||
def wait_for_job(self, jobname: str) -> None:
|
def wait_for_job(self, jobname: str) -> None:
|
||||||
@ -1029,7 +1029,7 @@ class Machine:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def send_key(
|
def send_key(
|
||||||
self, key: str, delay: Optional[float] = 0.01, log: Optional[bool] = True
|
self, key: str, delay: float | None = 0.01, log: bool | None = True
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Simulate pressing keys on the virtual keyboard, e.g.,
|
Simulate pressing keys on the virtual keyboard, e.g.,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import time
|
import time
|
||||||
|
from collections.abc import Callable
|
||||||
from math import isfinite
|
from math import isfinite
|
||||||
from typing import Callable, Optional
|
|
||||||
|
|
||||||
from test_driver.logger import AbstractLogger
|
from test_driver.logger import AbstractLogger
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ class PollingConditionError(Exception):
|
|||||||
class PollingCondition:
|
class PollingCondition:
|
||||||
condition: Callable[[], bool]
|
condition: Callable[[], bool]
|
||||||
seconds_interval: float
|
seconds_interval: float
|
||||||
description: Optional[str]
|
description: str | None
|
||||||
logger: AbstractLogger
|
logger: AbstractLogger
|
||||||
|
|
||||||
last_called: float
|
last_called: float
|
||||||
@ -20,10 +20,10 @@ class PollingCondition:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
condition: Callable[[], Optional[bool]],
|
condition: Callable[[], bool | None],
|
||||||
logger: AbstractLogger,
|
logger: AbstractLogger,
|
||||||
seconds_interval: float = 2.0,
|
seconds_interval: float = 2.0,
|
||||||
description: Optional[str] = None,
|
description: str | None = None,
|
||||||
):
|
):
|
||||||
self.condition = condition # type: ignore
|
self.condition = condition # type: ignore
|
||||||
self.seconds_interval = seconds_interval
|
self.seconds_interval = seconds_interval
|
||||||
|
Loading…
Reference in New Issue
Block a user