diff options
Diffstat (limited to 'python')
-rw-r--r-- | python/Makefile | 12 | ||||
-rw-r--r-- | python/qemu/utils/__init__.py | 8 | ||||
-rw-r--r-- | python/qemu/utils/accel.py | 9 | ||||
-rw-r--r-- | python/qemu/utils/qom.py | 45 | ||||
-rw-r--r-- | python/qemu/utils/qom_common.py | 55 | ||||
-rwxr-xr-x | python/scripts/vendor.py | 4 | ||||
-rw-r--r-- | python/setup.cfg | 9 | ||||
-rw-r--r-- | python/tests/minreqs.txt | 33 | ||||
-rwxr-xr-x | python/tests/qapi-flake8.sh | 6 | ||||
-rwxr-xr-x | python/tests/qapi-isort.sh | 8 | ||||
-rwxr-xr-x | python/tests/qapi-mypy.sh | 4 | ||||
-rwxr-xr-x | python/tests/qapi-pylint.sh | 8 | ||||
-rw-r--r-- | python/wheels/meson-1.5.0-py3-none-any.whl | bin | 959846 -> 0 bytes | |||
-rw-r--r-- | python/wheels/meson-1.8.1-py3-none-any.whl | bin | 0 -> 1013001 bytes |
14 files changed, 166 insertions, 35 deletions
diff --git a/python/Makefile b/python/Makefile index 1fa4ba2..32aedce 100644 --- a/python/Makefile +++ b/python/Makefile @@ -9,13 +9,13 @@ help: @echo "make check-minreqs:" @echo " Run tests in the minreqs virtual environment." @echo " These tests use the oldest dependencies." - @echo " Requires: Python 3.8" - @echo " Hint (Fedora): 'sudo dnf install python3.8'" + @echo " Requires: Python 3.9" + @echo " Hint (Fedora): 'sudo dnf install python3.9'" @echo "" @echo "make check-tox:" @echo " Run tests against multiple python versions." @echo " These tests use the newest dependencies." - @echo " Requires: Python 3.8 - 3.11, and tox." + @echo " Requires: Python 3.9 - 3.11, and tox." @echo " Hint (Fedora): 'sudo dnf install python3-tox python3.11'" @echo " The variable QEMU_TOX_EXTRA_ARGS can be use to pass extra" @echo " arguments to tox". @@ -59,7 +59,7 @@ PIP_INSTALL = pip install --disable-pip-version-check min-venv: $(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate $(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate: setup.cfg tests/minreqs.txt @echo "VENV $(QEMU_MINVENV_DIR)" - @python3.8 -m venv $(QEMU_MINVENV_DIR) + @python3.9 -m venv $(QEMU_MINVENV_DIR) @( \ echo "ACTIVATE $(QEMU_MINVENV_DIR)"; \ . $(QEMU_MINVENV_DIR)/bin/activate; \ @@ -68,7 +68,7 @@ $(QEMU_MINVENV_DIR) $(QEMU_MINVENV_DIR)/bin/activate: setup.cfg tests/minreqs.tx echo "INSTALL -r tests/minreqs.txt $(QEMU_MINVENV_DIR)";\ $(PIP_INSTALL) -r tests/minreqs.txt 1>/dev/null; \ echo "INSTALL -e qemu $(QEMU_MINVENV_DIR)"; \ - $(PIP_INSTALL) -e . 1>/dev/null; \ + PIP_CONFIG_SETTINGS="editable_mode=compat" $(PIP_INSTALL) -e . 1>/dev/null; \ ) @touch $(QEMU_MINVENV_DIR) @@ -103,7 +103,7 @@ check-dev: dev-venv .PHONY: develop develop: - $(PIP_INSTALL) -e .[devel] + PIP_CONFIG_SETTINGS="editable_mode=compat" $(PIP_INSTALL) -e .[devel] .PHONY: check check: diff --git a/python/qemu/utils/__init__.py b/python/qemu/utils/__init__.py index 017cfdc..be5daa8 100644 --- a/python/qemu/utils/__init__.py +++ b/python/qemu/utils/__init__.py @@ -23,13 +23,19 @@ import textwrap from typing import Optional # pylint: disable=import-error -from .accel import kvm_available, list_accel, tcg_available +from .accel import ( + hvf_available, + kvm_available, + list_accel, + tcg_available, +) __all__ = ( 'VerboseProcessError', 'add_visual_margin', 'get_info_usernet_hostfwd_port', + 'hvf_available', 'kvm_available', 'list_accel', 'tcg_available', diff --git a/python/qemu/utils/accel.py b/python/qemu/utils/accel.py index 386ff64..f915b64 100644 --- a/python/qemu/utils/accel.py +++ b/python/qemu/utils/accel.py @@ -82,3 +82,12 @@ def tcg_available(qemu_bin: str) -> bool: @param qemu_bin (str): path to the QEMU binary """ return 'tcg' in list_accel(qemu_bin) + + +def hvf_available(qemu_bin: str) -> bool: + """ + Check if HVF is available. + + @param qemu_bin (str): path to the QEMU binary + """ + return 'hvf' in list_accel(qemu_bin) diff --git a/python/qemu/utils/qom.py b/python/qemu/utils/qom.py index 426a0f2..05e5f14 100644 --- a/python/qemu/utils/qom.py +++ b/python/qemu/utils/qom.py @@ -31,8 +31,7 @@ QOM commands: ## import argparse - -from qemu.qmp import ExecuteError +from typing import List from .qom_common import QOMCommand @@ -224,28 +223,34 @@ class QOMTree(QOMCommand): super().__init__(args) self.path = args.path - def _list_node(self, path: str) -> None: - print(path) - items = self.qom_list(path) - for item in items: - if item.child: - continue - try: - rsp = self.qmp.cmd('qom-get', path=path, - property=item.name) - print(f" {item.name}: {rsp} ({item.type})") - except ExecuteError as err: - print(f" {item.name}: <EXCEPTION: {err!s}> ({item.type})") - print('') - for item in items: - if not item.child: - continue + def _list_nodes(self, paths: List[str]) -> None: + all_paths_props = self.qom_list_get(paths) + i = 0 + + for props in all_paths_props: + path = paths[i] + i = i + 1 + print(path) if path == '/': path = '' - self._list_node(f"{path}/{item.name}") + newpaths = [] + + for item in props.properties: + if item.child: + newpaths += [f"{path}/{item.name}"] + else: + value = item.value + if value is None: + value = "<EXCEPTION: property could not be read>" + print(f" {item.name}: {value} ({item.type})") + + print('') + + if newpaths: + self._list_nodes(newpaths) def run(self) -> int: - self._list_node(self.path) + self._list_nodes([self.path]) return 0 diff --git a/python/qemu/utils/qom_common.py b/python/qemu/utils/qom_common.py index dd2c8b1..ab21a4d 100644 --- a/python/qemu/utils/qom_common.py +++ b/python/qemu/utils/qom_common.py @@ -65,6 +65,52 @@ class ObjectPropertyInfo: return self.type.startswith('link<') +class ObjectPropertyValue: + """ + Represents a property return from e.g. qom-tree-get + """ + def __init__(self, name: str, type_: str, value: object): + self.name = name + self.type = type_ + self.value = value + + @classmethod + def make(cls, value: Dict[str, Any]) -> 'ObjectPropertyValue': + """ + Build an ObjectPropertyValue from a Dict with an unknown shape. + """ + assert value.keys() >= {'name', 'type'} + assert value.keys() <= {'name', 'type', 'value'} + return cls(value['name'], value['type'], value.get('value')) + + @property + def child(self) -> bool: + """Is this property a child property?""" + return self.type.startswith('child<') + + +class ObjectPropertiesValues: + """ + Represents the return type from e.g. qom-list-get + """ + # pylint: disable=too-few-public-methods + + def __init__(self, properties: List[ObjectPropertyValue]) -> None: + self.properties = properties + + @classmethod + def make(cls, value: Dict[str, Any]) -> 'ObjectPropertiesValues': + """ + Build an ObjectPropertiesValues from a Dict with an unknown shape. + """ + assert value.keys() == {'properties'} + props = [ObjectPropertyValue(item['name'], + item['type'], + item.get('value')) + for item in value['properties']] + return cls(props) + + CommandT = TypeVar('CommandT', bound='QOMCommand') @@ -145,6 +191,15 @@ class QOMCommand: assert isinstance(rsp, list) return [ObjectPropertyInfo.make(x) for x in rsp] + def qom_list_get(self, paths: List[str]) -> List[ObjectPropertiesValues]: + """ + :return: a strongly typed list from the 'qom-list-get' command. + """ + rsp = self.qmp.cmd('qom-list-get', paths=paths) + # qom-list-get returns List[ObjectPropertiesValues] + assert isinstance(rsp, list) + return [ObjectPropertiesValues.make(x) for x in rsp] + @classmethod def command_runner( cls: Type[CommandT], diff --git a/python/scripts/vendor.py b/python/scripts/vendor.py index 0405e91..b47db00 100755 --- a/python/scripts/vendor.py +++ b/python/scripts/vendor.py @@ -41,8 +41,8 @@ def main() -> int: parser.parse_args() packages = { - "meson==1.5.0": - "52b34f4903b882df52ad0d533146d4b992c018ea77399f825579737672ae7b20", + "meson==1.8.1": + "374bbf71247e629475fc10b0bd2ef66fc418c2d8f4890572f74de0f97d0d42da", } vendor_dir = Path(__file__, "..", "..", "wheels").resolve() diff --git a/python/setup.cfg b/python/setup.cfg index cf5af7e..d7f5dc7 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -14,7 +14,6 @@ classifiers = Natural Language :: English Operating System :: OS Independent Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 @@ -23,7 +22,7 @@ classifiers = Typing :: Typed [options] -python_requires = >= 3.8 +python_requires = >= 3.9 packages = qemu.qmp qemu.machine @@ -47,6 +46,7 @@ devel = urwid >= 2.1.2 urwid-readline >= 0.13 Pygments >= 2.9.0 + sphinx >= 3.4.3 # Provides qom-fuse functionality fuse = @@ -78,8 +78,7 @@ exclude = __pycache__, [mypy] strict = True -python_version = 3.8 -warn_unused_configs = True +python_version = 3.9 namespace_packages = True warn_unused_ignores = False @@ -186,7 +185,7 @@ multi_line_output=3 # of python available on your system to run this test. [tox:tox] -envlist = py38, py39, py310, py311, py312, py313 +envlist = py39, py310, py311, py312, py313 skip_missing_interpreters = true [testenv] diff --git a/python/tests/minreqs.txt b/python/tests/minreqs.txt index a3f423e..cd2e2a8 100644 --- a/python/tests/minreqs.txt +++ b/python/tests/minreqs.txt @@ -1,5 +1,5 @@ # This file lists the ***oldest possible dependencies*** needed to run -# "make check" successfully under ***Python 3.8***. It is used primarily +# "make check" successfully under ***Python 3.9***. It is used primarily # by GitLab CI to ensure that our stated minimum versions in setup.cfg # are truthful and regularly validated. # @@ -11,6 +11,15 @@ # When adding new dependencies, pin the very oldest non-yanked version # on PyPI that allows the test suite to pass. +# For some reason, the presence of packaging==14.0 below requires us to +# also pin setuptools to version 70 or below. Otherwise, the +# installation of the QEMU package itself fails, failing to find +# setuptools. +setuptools<=70 + +# Dependencies for qapidoc/qapi_domain et al +sphinx==3.4.3 + # Dependencies for the TUI addon (Required for successful linting) urwid==2.1.2 urwid-readline==0.13 @@ -38,10 +47,32 @@ pyflakes==2.5.0 # Transitive mypy dependencies mypy-extensions==1.0.0 +tomli==1.1.0 typing-extensions==4.7.1 # Transitive pylint dependencies astroid==2.15.4 +dill==0.2 lazy-object-proxy==1.4.0 +platformdirs==2.2.0 toml==0.10.0 +tomlkit==0.10.1 wrapt==1.14.0 + +# Transitive sphinx dependencies +Jinja2==2.7 +MarkupSafe==1.1.0 +alabaster==0.7.1 +babel==1.3 +docutils==0.12 +imagesize==0.5.0 +packaging==14.0 +pytz==2011b0 +requests==2.5.0 +snowballstemmer==1.1 +sphinxcontrib-applehelp==1.0.0 +sphinxcontrib-devhelp==1.0.0 +sphinxcontrib-htmlhelp==1.0.0 +sphinxcontrib-jsmath==1.0.0 +sphinxcontrib-qthelp==1.0.0 +sphinxcontrib-serializinghtml==1.0.0 diff --git a/python/tests/qapi-flake8.sh b/python/tests/qapi-flake8.sh new file mode 100755 index 0000000..c69f9ea --- /dev/null +++ b/python/tests/qapi-flake8.sh @@ -0,0 +1,6 @@ +#!/bin/sh -e +# SPDX-License-Identifier: GPL-2.0-or-later + +python3 -m flake8 ../scripts/qapi/ \ + ../docs/sphinx/qapidoc.py \ + ../docs/sphinx/qapi_domain.py diff --git a/python/tests/qapi-isort.sh b/python/tests/qapi-isort.sh new file mode 100755 index 0000000..067c16d --- /dev/null +++ b/python/tests/qapi-isort.sh @@ -0,0 +1,8 @@ +#!/bin/sh -e +# SPDX-License-Identifier: GPL-2.0-or-later + +python3 -m isort --sp . -c ../scripts/qapi/ +# Force isort to recognize "compat" as a local module and not third-party +python3 -m isort --sp . -c -p compat \ + ../docs/sphinx/qapi_domain.py \ + ../docs/sphinx/qapidoc.py diff --git a/python/tests/qapi-mypy.sh b/python/tests/qapi-mypy.sh new file mode 100755 index 0000000..363dbaf --- /dev/null +++ b/python/tests/qapi-mypy.sh @@ -0,0 +1,4 @@ +#!/bin/sh -e +# SPDX-License-Identifier: GPL-2.0-or-later + +python3 -m mypy ../scripts/qapi diff --git a/python/tests/qapi-pylint.sh b/python/tests/qapi-pylint.sh new file mode 100755 index 0000000..8767d9d --- /dev/null +++ b/python/tests/qapi-pylint.sh @@ -0,0 +1,8 @@ +#!/bin/sh -e +# SPDX-License-Identifier: GPL-2.0-or-later + +SETUPTOOLS_USE_DISTUTILS=stdlib python3 -m pylint \ + --rcfile=../scripts/qapi/pylintrc \ + ../scripts/qapi/ \ + ../docs/sphinx/qapidoc.py \ + ../docs/sphinx/qapi_domain.py diff --git a/python/wheels/meson-1.5.0-py3-none-any.whl b/python/wheels/meson-1.5.0-py3-none-any.whl Binary files differdeleted file mode 100644 index c7edeb3..0000000 --- a/python/wheels/meson-1.5.0-py3-none-any.whl +++ /dev/null diff --git a/python/wheels/meson-1.8.1-py3-none-any.whl b/python/wheels/meson-1.8.1-py3-none-any.whl Binary files differnew file mode 100644 index 0000000..a885f0e --- /dev/null +++ b/python/wheels/meson-1.8.1-py3-none-any.whl |