pysnap.terminal package¶
Terminal interface components for PySnap.
Submodules¶
pysnap.terminal.clipboard module¶
Read the host clipboard for the Ctrl-] v paste of pysnap connect.
The clipboard is read only when the user asks for it. Copying and the usual paste are left to the terminal of the user; this paste helps where the terminal offers none from the keyboard, such as the Windows console without its Ctrl key shortcuts.
Windows: the Win32 clipboard API through
ctypes, no external program;macOS:
pbpaste;Linux and other systems:
wl-pasteunder Wayland, thenxcliporxselfor the X11 clipboard.
- exception pysnap.terminal.clipboard.ClipboardError[source]¶
Bases:
ExceptionReport that the host clipboard cannot be read.
- pysnap.terminal.clipboard.read_host_clipboard()[source]¶
Return the text in the host clipboard.
- Returns:
Clipboard text; empty when the clipboard holds no text.
- Raises:
ClipboardError – When no way to read the clipboard works.
- Return type:
str
pysnap.terminal.emulator module¶
Terminal emulation utilities built on top of pyte.
- class pysnap.terminal.emulator.SequenceFilter[source]¶
Bases:
objectRemove control sequences
pytecannot handle before it parses them.pyte0.8 fails on some sequences that current programs send, for example editors such as Vim with an xtermTERM:private CSI sequences other than DEC modes, such as
ESC [ ? 4 m, raiseTypeError;>,=and<prefixes are ignored, soESC [ > 4 ; 2 mswitches on underline;intermediate bytes (
ESC [ 0 % m) and colon sub-parameters (ESC [ 3 8 : 2 : : 1 : 2 : 3 m) end the sequence early and the rest is drawn as text;the payload of DCS, SOS, PM and APC strings is drawn as text.
The filter keeps the sequences
pytehandles, rewrites colon SGR parameters to the semicolon form and drops the rest, together with all control strings (including OSC: window titles are not used). Its state survives chunk boundaries, so a sequence split between two reads is handled like a whole one.
- class pysnap.terminal.emulator.ScrollRegionMixin[source]¶
Bases:
objectAdd the CSI
SandTscroll commands thatpyte0.8 lacks.Programs such as nano scroll their editing area with them when the terminal is an xterm. The scroll happens inside the scrolling margins and does not move the cursor; it reuses
indexandreverse_indexso that screens which track lines leaving the screen see them as usual.
- class pysnap.terminal.emulator.ScreenStream(*args, **kwargs)[source]¶
Bases:
ByteStreampytebyte stream that also dispatches CSISandT.- Parameters:
args (Any)
kwargs (Any)
- Return type:
Any
- csi = {'S': 'scroll_up', 'T': 'scroll_down'}¶
- class pysnap.terminal.emulator.AlternateScreenMixin[source]¶
Bases:
objectGive a
pytehistory screen the xterm alternate screen.Full-screen programs such as vim, nano and less switch to the alternate screen and back when they exit, so the shell screen reappears as it was. Lines scrolled on the alternate screen do not enter the history, as in xterm.
pyte0.8 has no alternate screen: it ignores these modes.- set_mode(*modes, **kwargs)[source]¶
Handle the alternate screen modes;
pyterecords all modes as usual.- Parameters:
modes (int)
kwargs (object)
- Return type:
None
- reset_mode(*modes, **kwargs)[source]¶
Leave the alternate screen;
pyterecords all modes as usual.- Parameters:
modes (int)
kwargs (object)
- Return type:
None
- index()[source]¶
Scroll without filling the history while the alternate screen is shown.
- Return type:
None
- reverse_index()[source]¶
Scroll back without touching the history on the alternate screen.
- Return type:
None
- pysnap.terminal.emulator.is_invisible_character(char)[source]¶
Return whether
pytewould stop drawing at this character.- Parameters:
char (str) – One character.
- Returns:
Truefor characters without width that do not combine with the previous character.- Return type:
bool
- class pysnap.terminal.emulator.TerminalEmulator(columns=80, lines=24, history=5000, invisible_replacement='')[source]¶
Bases:
objectWrap a
pyte.Screenand render it for the TUI.- Parameters:
columns (int)
lines (int)
history (int)
invisible_replacement (str)
- feed(data)[source]¶
Feed new bytes into the terminal parser.
Parsing while the local viewport is scrolled back would write into the manually rotated history buffers and lose lines, so the view first returns to the live bottom. This mirrors the common jump-to-bottom-on-output behavior of desktop terminals.
Control sequences
pytecannot handle are filtered first (seeSequenceFilter).- Parameters:
data (bytes) – Raw bytes read from the guest connection.
- Return type:
None
- resize(columns, lines)[source]¶
Resize the virtual screen.
- Parameters:
columns (int) – New terminal width.
lines (int) – New terminal height.
- Return type:
None
- scroll_up(lines=1)[source]¶
Scroll the local view toward older history lines.
The alternate screen of full-screen programs has no history, so nothing happens while it is shown.
- Parameters:
lines (int) – Number of lines to move upward.
- Return type:
None
- scroll_down(lines=1)[source]¶
Scroll the local view toward newer history lines.
- Parameters:
lines (int) – Number of lines to move downward.
- Return type:
None
- property bracketed_paste: bool[source]¶
Return whether the guest asked for bracketed paste (mode 2004).
pysnap.terminal.keymap module¶
Translate prompt_toolkit key presses into byte sequences for the guest.
- pysnap.terminal.keymap.key_press_to_bytes(key_press)[source]¶
Translate one key press into bytes for the VM serial console.
- Parameters:
key_press (prompt_toolkit.key_binding.key_processor.KeyPress) – Prompt-toolkit key press.
- Returns:
Bytes to send or
Nonewhen the key is unsupported.- Return type:
bytes | None
- pysnap.terminal.keymap.paste_to_bytes(text, *, bracketed)[source]¶
Return pasted text as the bytes a terminal sends for it.
Line breaks of any system (
CR LF,LF) becomeCR, the Enter key of a terminal, so a text copied on Windows does not give empty lines. When the guest asked for bracketed paste (ESC [ ? 2004 h, as bash and vim do), the text is put betweenESC [ 200 ~andESC [ 201 ~; markers inside the text are removed, so that it cannot end the paste early.- Parameters:
text (str) – Pasted text.
bracketed (bool) – Whether the guest enabled bracketed paste.
- Returns:
UTF-8 bytes for the guest.
- Return type:
bytes
pysnap.terminal.protocol module¶
Helpers for terminal control-sequence handling over serial TCP.
- class pysnap.terminal.protocol.TerminalQueryResponder(_buffer=<factory>)[source]¶
Bases:
objectRecognize terminal queries and synthesize compatible replies.
Raw serial consoles do not provide a PTY-style
SIGWINCHchannel into the guest system. PySnap therefore acts like a small terminal emulator and replies to xterm-compatible size queries that guest-side tools may emit.- Parameters:
_buffer (bytearray)
- collect_responses(data, *, emulator, columns, lines)[source]¶
Return terminal replies implied by one incoming byte chunk.
- Parameters:
data (bytes) – Newly received bytes from the guest.
emulator (TerminalEmulator) – Emulator holding the current cursor position.
columns (int) – Current visible terminal width.
lines (int) – Current visible terminal height.
- Returns:
Zero or more response payloads to send back to the guest.
- Return type:
list[bytes]
pysnap.terminal.session module¶
Interactive terminal session attached to a VM serial TCP console.
- class pysnap.terminal.session.SessionStatus(vm_name, vm_state='Changing', port_label='', message='Connecting...')[source]¶
Bases:
objectMutable session status shown in the status bar.
- Parameters:
vm_name (str)
vm_state (str)
port_label (str)
message (str)
- vm_name: str¶
- vm_state: str = 'Changing'¶
- port_label: str = ''¶
- message: str = 'Connecting...'¶
- class pysnap.terminal.session.PauseTracker(paused=False)[source]¶
Bases:
objectFollow pause and resume of the attached VM.
The session stays open while the VM is paused: keys are held back and the status bar says so. Any state other than running or paused ends it.
- Parameters:
paused (bool)
- class pysnap.terminal.session.SessionTransport(name, label, port, serial, opener)[source]¶
Bases:
objectHow a terminal session reaches the guest.
- Parameters:
name (str) –
"Serial"or"ssh", used in messages.label (str) – Status bar label such as
UART1:2326orssh:2400.port (int) – Host port, recorded in the session registry.
serial (bool) – Whether this is the COM1 console: it is woken with Enter, may be attached while paused and serves
report extractthrough the control channel.opener (Callable[[int, int], Awaitable[tuple[StreamReader, StreamWriter, Callable[[], Awaitable[None]] | None]]]) – Coroutine that connects for a terminal of the given columns and rows and returns a reader, a writer and an optional coroutine that cleans up afterwards.
- name: str¶
- label: str¶
- port: int¶
- serial: bool¶
- opener: Callable[[int, int], Awaitable[tuple[StreamReader, StreamWriter, Callable[[], Awaitable[None]] | None]]]¶
- classmethod for_serial(serial_port, *, timeout=None)[source]¶
Return the transport for the COM1 TCP server.
- Parameters:
serial_port (int) – Host TCP port of COM1.
timeout (float | None) – Connection timeout; the transport default without.
- Returns:
Serial transport.
- Return type:
- classmethod for_ssh(target, store)[source]¶
Return the transport for an ssh login shell.
- Parameters:
target (SshTarget) – ssh connection target.
store (SshKeyStore) – PySnap key store.
- Returns:
ssh transport.
- Return type:
- class pysnap.terminal.session.ScrollableTerminalControl(*args, **kwargs)[source]¶
Bases:
FormattedTextControlFormatted text control that scrolls the local history with the wheel.
- Parameters:
on_scroll_up (Callable[[], None] | None)
on_scroll_down (Callable[[], None] | None)
mouse_scrolling_enabled (bool)
- class pysnap.terminal.session.TerminalSession(service=None)[source]¶
Bases:
objectManage one interactive terminal connection to a VM.
- Parameters:
service (PySnapService | None)
pysnap.terminal.transport module¶
TCP transport helpers for VM serial console connections.
- pysnap.terminal.transport.open_serial_socket(host, port, timeout=30.0, retry_delay=0.25)[source]¶
Wait for and open a blocking TCP socket to the VM serial port.
- Parameters:
host (str) – Target host name.
port (int) – Target TCP port.
timeout (float) – Maximum time to wait.
retry_delay (float) – Delay between connection attempts.
- Returns:
Connected socket object.
- Raises:
PySnapError – If the TCP server does not become available in time.
- Return type:
socket
- pysnap.terminal.transport.serial_connection_probe(host, port, timeout=30.0, retry_delay=0.25)[source]¶
Open a short-lived serial TCP connection for automated checks.
The probe writes one newline to verify that the transport accepts client output and then keeps the connection open for the caller-managed context.
- Parameters:
host (str) – Target host name.
port (int) – Target TCP port.
timeout (float) – Maximum time to wait.
retry_delay (float) – Delay between connection attempts.
- Yields:
Connected socket object.
- Return type:
Iterator[socket]
- async pysnap.terminal.transport.open_serial_connection(host, port, timeout=30.0, retry_delay=0.25)[source]¶
Wait for and open a TCP connection to the VM serial port.
- Parameters:
host (str) – Target host name.
port (int) – Target TCP port.
timeout (float) – Maximum time to wait.
retry_delay (float) – Delay between connection attempts.
- Returns:
Reader and writer stream objects.
- Raises:
PySnapError – If the TCP server does not become available in time.
- Return type:
tuple[StreamReader, StreamWriter]