qemu-e2k/python/qemu/utils/__init__.py

124 lines
4.3 KiB
Python
Raw Normal View History

"""
QEMU development and testing utilities
This package provides a small handful of utilities for performing
various tasks not directly related to the launching of a VM.
"""
# Copyright (C) 2021 Red Hat Inc.
#
# Authors:
# John Snow <jsnow@redhat.com>
# Cleber Rosa <crosa@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
#
import os
import re
import shutil
import textwrap
from typing import Optional
# pylint: disable=import-error
from .accel import kvm_available, list_accel, tcg_available
__all__ = (
'add_visual_margin',
'get_info_usernet_hostfwd_port',
'kvm_available',
'list_accel',
'tcg_available',
)
def get_info_usernet_hostfwd_port(info_usernet_output: str) -> Optional[int]:
"""
Returns the port given to the hostfwd parameter via info usernet
:param info_usernet_output: output generated by hmp command "info usernet"
:return: the port number allocated by the hostfwd option
"""
for line in info_usernet_output.split('\r\n'):
regex = r'TCP.HOST_FORWARD.*127\.0\.0\.1\s+(\d+)\s+10\.'
match = re.search(regex, line)
if match is not None:
return int(match[1])
return None
# pylint: disable=too-many-arguments
def add_visual_margin(
content: str = '',
width: Optional[int] = None,
name: Optional[str] = None,
padding: int = 1,
upper_left: str = '',
lower_left: str = '',
horizontal: str = '',
vertical: str = '',
) -> str:
"""
Decorate and wrap some text with a visual decoration around it.
This function assumes that the text decoration characters are single
characters that display using a single monospace column.
Example
This is what this function looks like with text content that's
wrapped to 66 characters. The right-hand margin is left open to
accommodate the occasional unicode character that might make
predicting the total "visual" width of a line difficult. This
provides a visual distinction that's good-enough, though.
:param content: The text to wrap and decorate.
:param width:
The number of columns to use, including for the decoration
itself. The default (None) uses the the available width of the
current terminal, or a fallback of 72 lines. A negative number
subtracts a fixed-width from the default size. The default obeys
the COLUMNS environment variable, if set.
:param name: A label to apply to the upper-left of the box.
:param padding: How many columns of padding to apply inside.
:param upper_left: Upper-left single-width text decoration character.
:param lower_left: Lower-left single-width text decoration character.
:param horizontal: Horizontal single-width text decoration character.
:param vertical: Vertical single-width text decoration character.
"""
if width is None or width < 0:
avail = shutil.get_terminal_size(fallback=(72, 24))[0]
if width is None:
_width = avail
else:
_width = avail + width
else:
_width = width
prefix = vertical + (' ' * padding)
def _bar(name: Optional[str], top: bool = True) -> str:
ret = upper_left if top else lower_left
if name is not None:
ret += f"{horizontal} {name} "
filler_len = _width - len(ret)
ret += f"{horizontal * filler_len}"
return ret
def _wrap(line: str) -> str:
return os.linesep.join(
textwrap.wrap(
line, width=_width - padding, initial_indent=prefix,
subsequent_indent=prefix, replace_whitespace=False,
drop_whitespace=True, break_on_hyphens=False)
)
return os.linesep.join((
_bar(name, top=True),
os.linesep.join(_wrap(line) for line in content.splitlines()),
_bar(None, top=False),
))