aboutsummaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/Makefile12
-rw-r--r--python/qemu/utils/__init__.py8
-rw-r--r--python/qemu/utils/accel.py9
-rw-r--r--python/qemu/utils/qom.py45
-rw-r--r--python/qemu/utils/qom_common.py55
-rwxr-xr-xpython/scripts/vendor.py4
-rw-r--r--python/setup.cfg9
-rw-r--r--python/tests/minreqs.txt33
-rwxr-xr-xpython/tests/qapi-flake8.sh6
-rwxr-xr-xpython/tests/qapi-isort.sh8
-rwxr-xr-xpython/tests/qapi-mypy.sh4
-rwxr-xr-xpython/tests/qapi-pylint.sh8
-rw-r--r--python/wheels/meson-1.5.0-py3-none-any.whlbin959846 -> 0 bytes
-rw-r--r--python/wheels/meson-1.8.1-py3-none-any.whlbin0 -> 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
deleted file mode 100644
index c7edeb3..0000000
--- a/python/wheels/meson-1.5.0-py3-none-any.whl
+++ /dev/null
Binary files differ
diff --git a/python/wheels/meson-1.8.1-py3-none-any.whl b/python/wheels/meson-1.8.1-py3-none-any.whl
new file mode 100644
index 0000000..a885f0e
--- /dev/null
+++ b/python/wheels/meson-1.8.1-py3-none-any.whl
Binary files differ