Coverage for src/engines/wexpect.py: 100.00%
33 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-22 10:53 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-22 10:53 +0000
1#!/usr/bin/env python3
3# Coverage
4# pragma: windows cover file
6# Standard libraries
7# from os import environ
8from typing import List
10# Modules libraries
11# environ['WEXPECT_SPAWN_CLASS'] = 'SpawnPipe'
12from wexpect import EOF, spawn, TIMEOUT # pylint: disable=import-error
14# Components
15from .base import Base
17# Wexpect class
18class Wexpect(Base):
20 # Constructor
21 def __init__(self, command: str) -> None: # pylint: disable=super-init-not-called
23 # Spawn command
24 self._child = spawn(command)
26 # Acquire initial output
27 assert self._child is not None
28 try:
29 self._child.expect(EOF, timeout=0)
30 except TIMEOUT: # pragma: no cover
31 pass
33 # Configure timeout
34 self._child.timeout = 1
36 # Read
37 def _read(self) -> bytes | List[bytes | str] | str:
39 # Acquire output
40 assert self._child is not None
41 try:
42 output = self._child.read_nonblocking(size=1024)
43 if self._child.before: # pragma: no cover
44 output = self._child.before + output
45 except EOF:
46 output = self._child.before
47 except TIMEOUT: # pragma: no cover
48 output = self._child.before
50 # Handle output
51 if output: # pragma: no cover
53 # Stream line
54 assert isinstance(output, (bytes, str))
55 if '\n' in output:
56 return output
58 # Adapt lines
59 length = 80
60 return [output[i:i + length] for i in range(0, len(output), length)]
62 # Empty output
63 return []
65 # Send
66 def send(self, key: bytes | str) -> None:
68 # Send key
69 assert self._child is not None
70 try:
71 self._child.send(key)
72 except EOF:
73 pass
75 # Status
76 def status(self) -> int:
78 # Process terminated
79 assert self._child is not None
80 if self._child.exitstatus is None:
81 return 0 if self._child.flag_eof else 1
83 # Process status
84 return int(self._child.exitstatus) # pragma: no cover
86 # Terminate
87 def terminate(self, force: bool = False) -> None:
89 # Terminate process
90 if force:
91 assert self._child is not None
92 self._child.terminate()
94 # Wait process
95 else:
96 assert self._child is not None
97 self._child.wait()