summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2026-09-03 09:42:53 +0100
committerPeter Maydell <peter.maydell@linaro.org>2026-09-03 09:42:53 +0100
commit1a8f18541eef8761a709e44708758a4c08b50a15 (patch)
tree59331c717ca730432093402e46bbe6cc27c381be /docs
parentc513597761d6fc06690b5b7cf10dfb7ab05815d0 (diff)
parent4061c0e95c6e2736926ab8723606cddf582f58e6 (diff)
downloadqemu-1a8f18541eef8761a709e44708758a4c08b50a15.tar.gz
qemu-1a8f18541eef8761a709e44708758a4c08b50a15.zip
Merge tag 'python-pull-request' of https://gitlab.com/jsnow/qemu into staging
python upgrade to py312 # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCgAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmqYepEACgkQfe+BBqr8 # OQ6Nyg//SFe2COs76DIzWWTN21N/wo4pHAf6Q0nGGj2NKiPozN0aIAcKA9mw8ZXo # 6HQTjMJKOq4jnL9pYLNS2MzrhiJrvrR0gBymi0aD93EOAMtqXcLxgaCnpI4wFu8v # wosIehLduYMytrb80aY8oCbUOl+uTPOYHuDtUc7msBV5iqhFg56emjvOh7B+5SuE # iKc6ivljUVxoVat3pzKSZsxbVd+iYz3UI8cBPa8ISNkfxgCjUw/+t6cm3fBj+v8u # q0U2qVBfvMH6wPQ7qA+VZvwnf7UgTymbprGko17EkPZwgtKzM+k2Lr75GjfwLHx5 # i7sjKu7doWfRa7/+bNyYj+lZtCAcGJGZu6yuIE6vBj6eBB8LxGbw/zLU+p5Q+QJe # +np4dFLkK2rlBRNrg4o/66rCWO/b97F6GBtVOoNx44fWmXZfuKJxh0F6FCpvPvlf # fiAEHiSNmfmUXIeFGgq3OcP4ZB6BIGlHWA+F4U7gn1ZxGrtvZDImRdy0Qj2IjsL0 # lwBXSdS9FgX/lOe2oOGScZIepJsVhMVZ7y+u4g+//GLjLPO2JGLh3oZZdDXa6af8 # N//steftVLII0JWTB5z+6Hv3A5ek9AxiVSPPYLpTGcvp1Cgni+5BdiGqPs5554qC # Yh5/F0aafIJsMDSs9sO6U4X46DYp8/DSfJwr3Vn+Y9SSVgdSGlU= # =QZ+f # -----END PGP SIGNATURE----- # gpg: Signature made Wed Sep 2 20:35:45 2026 BST # gpg: using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full] # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * tag 'python-pull-request' of https://gitlab.com/jsnow/qemu: sphinx: drop qapidoc back-compat overboiled spaghetti dinner sphinx: drop fakedbusdoc sphinx: require sphinx 7.2.6 python: remove stale setup.cfg options python: remove distutils workarounds python: allow mypy to run as the current python version python: fix license configuration python: upgrade to Python3.12+ qapi: update type hint for objects_seen tests: update emsdk-wasm64-cross tests: add Python3.12 to centos9.docker tests: re-add opencv2 and numpy dependencies tests: drop python3-devel mapping tests: update netbsd dependencies tests: update libvirt-ci, lcitool tests: update vm tests to prefer locally-built QEMU Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'docs')
-rw-r--r--docs/conf.py11
-rw-r--r--docs/interop/dbus-display.rst14
-rw-r--r--docs/interop/dbus-vmstate.rst14
-rw-r--r--docs/interop/dbus-vnc.rst14
-rw-r--r--docs/requirements.txt2
-rw-r--r--docs/sphinx/compat.py230
-rw-r--r--docs/sphinx/fakedbusdoc.py30
-rw-r--r--docs/sphinx/qapi_domain.py53
8 files changed, 35 insertions, 333 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 7e35d2158d..914bae67d9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -51,14 +51,15 @@ sys.path.insert(0, os.path.join(qemu_docdir, "../scripts"))
# If your documentation needs a minimal Sphinx version, state it here.
#
-# 3.4.3 is the oldest version of Sphinx that ships on a platform we
+# 7.2.6 is the oldest version of Sphinx that ships on a platform we
# pledge build support for.
-needs_sphinx = '3.4.3'
+needs_sphinx = '7.2.6'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
+ 'dbusdoc',
'depfile',
'hxtool',
'kerneldoc',
@@ -67,12 +68,6 @@ extensions = [
'qmp_lexer',
]
-if sphinx.version_info[:3] > (4, 0, 0):
- tags.add('sphinx4')
- extensions += ['dbusdoc']
-else:
- extensions += ['fakedbusdoc']
-
# Add any paths that contain templates here, relative to this directory.
templates_path = [os.path.join(qemu_docdir, '_templates')]
diff --git a/docs/interop/dbus-display.rst b/docs/interop/dbus-display.rst
index 87648e91dc..c87a04c969 100644
--- a/docs/interop/dbus-display.rst
+++ b/docs/interop/dbus-display.rst
@@ -18,16 +18,4 @@ QEMU also implements the standard interfaces, such as
:local:
:depth: 1
-.. only:: sphinx4
-
- .. dbus-doc:: ui/dbus-display1.xml
-
-.. only:: not sphinx4
-
- .. warning::
- Sphinx 4 is required to build D-Bus documentation.
-
- This is the content of ``ui/dbus-display1.xml``:
-
- .. literalinclude:: ../../ui/dbus-display1.xml
- :language: xml
+.. dbus-doc:: ui/dbus-display1.xml
diff --git a/docs/interop/dbus-vmstate.rst b/docs/interop/dbus-vmstate.rst
index 5fb3f279e2..5f8c6d125d 100644
--- a/docs/interop/dbus-vmstate.rst
+++ b/docs/interop/dbus-vmstate.rst
@@ -23,16 +23,4 @@ dbus-vmstate object can be configured with the expected list of
helpers by setting its ``id-list`` property, with a comma-separated
``Id`` list.
-.. only:: sphinx4
-
- .. dbus-doc:: backends/dbus-vmstate1.xml
-
-.. only:: not sphinx4
-
- .. warning::
- Sphinx 4 is required to build D-Bus documentation.
-
- This is the content of ``backends/dbus-vmstate1.xml``:
-
- .. literalinclude:: ../../backends/dbus-vmstate1.xml
- :language: xml
+.. dbus-doc:: backends/dbus-vmstate1.xml
diff --git a/docs/interop/dbus-vnc.rst b/docs/interop/dbus-vnc.rst
index d2b77978f6..5ea4fd5718 100644
--- a/docs/interop/dbus-vnc.rst
+++ b/docs/interop/dbus-vnc.rst
@@ -11,16 +11,4 @@ Objects are exported under ``/org/qemu/Vnc1/``.
:local:
:depth: 1
-.. only:: sphinx4
-
- .. dbus-doc:: tools/qemu-vnc/qemu-vnc1.xml
-
-.. only:: not sphinx4
-
- .. warning::
- Sphinx 4 is required to build D-Bus documentation.
-
- This is the content of ``tools/qemu-vnc/qemu-vnc1.xml``:
-
- .. literalinclude:: ../../tools/qemu-vnc/qemu-vnc1.xml
- :language: xml
+.. dbus-doc:: tools/qemu-vnc/qemu-vnc1.xml
diff --git a/docs/requirements.txt b/docs/requirements.txt
index 87f7afcb2e..c10c4cf7c9 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -1,5 +1,5 @@
# Used by readthedocs.io
# Should be in sync with the "installed" key of pythondeps.toml
-sphinx==6.2.1
+sphinx==7.2.6
sphinx_rtd_theme==1.2.2
diff --git a/docs/sphinx/compat.py b/docs/sphinx/compat.py
deleted file mode 100644
index 9cf7fe006e..0000000000
--- a/docs/sphinx/compat.py
+++ /dev/null
@@ -1,230 +0,0 @@
-"""
-Sphinx cross-version compatibility goop
-"""
-
-import re
-from typing import (
- TYPE_CHECKING,
- Any,
- Callable,
- Optional,
- Type,
-)
-
-from docutils import nodes
-from docutils.nodes import Element, Node, Text
-from docutils.statemachine import StringList
-
-import sphinx
-from sphinx import addnodes, util
-from sphinx.directives import ObjectDescription
-from sphinx.environment import BuildEnvironment
-from sphinx.roles import XRefRole
-from sphinx.util import docfields
-from sphinx.util.docutils import (
- ReferenceRole,
- SphinxDirective,
- switch_source_input,
-)
-from sphinx.util.typing import TextlikeNode
-
-
-MAKE_XREF_WORKAROUND = sphinx.version_info[:3] < (4, 1, 0)
-
-
-SpaceNode: Callable[[str], Node]
-KeywordNode: Callable[[str, str], Node]
-
-if sphinx.version_info[:3] >= (4, 0, 0):
- SpaceNode = addnodes.desc_sig_space
- KeywordNode = addnodes.desc_sig_keyword
-else:
- SpaceNode = Text
- KeywordNode = addnodes.desc_annotation
-
-
-def nested_parse_with_titles(
- directive: SphinxDirective, content_node: Element
-) -> None:
- """
- This helper preserves error parsing context across sphinx versions.
- """
-
- # necessary so that the child nodes get the right source/line set
- content_node.document = directive.state.document
-
- try:
- # Modern sphinx (6.2.0+) supports proper offsetting for
- # nested parse error context management
- util.nodes.nested_parse_with_titles(
- directive.state,
- directive.content,
- content_node,
- content_offset=directive.content_offset,
- )
- except TypeError:
- # No content_offset argument. Fall back to SSI method.
- with switch_source_input(directive.state, directive.content):
- util.nodes.nested_parse_with_titles(
- directive.state, directive.content, content_node
- )
-
-
-# ###########################################
-# xref compatibility hacks for Sphinx < 4.1 #
-# ###########################################
-
-# When we require >= Sphinx 4.1, the following function and the
-# subsequent 3 compatibility classes can be removed. Anywhere in
-# qapi_domain that uses one of these Compat* types can be switched to
-# using the garden-variety lib-provided classes with no trickery.
-
-
-def _compat_make_xref( # pylint: disable=unused-argument
- self: sphinx.util.docfields.Field,
- rolename: str,
- domain: str,
- target: str,
- innernode: Type[TextlikeNode] = addnodes.literal_emphasis,
- contnode: Optional[Node] = None,
- env: Optional[BuildEnvironment] = None,
- inliner: Any = None,
- location: Any = None,
-) -> Node:
- """
- Compatibility workaround for Sphinx versions prior to 4.1.0.
-
- Older sphinx versions do not use the domain's XRefRole for parsing
- and formatting cross-references, so we need to perform this magick
- ourselves to avoid needing to write the parser/formatter in two
- separate places.
-
- This workaround isn't brick-for-brick compatible with modern Sphinx
- versions, because we do not have access to the parent directive's
- state during this parsing like we do in more modern versions.
-
- It's no worse than what pre-Sphinx 4.1.0 does, so... oh well!
- """
-
- # Yes, this function is gross. Pre-4.1 support is a miracle.
- # pylint: disable=too-many-locals
-
- assert env
- # Note: Sphinx's own code ignores the type warning here, too.
- if not rolename:
- return contnode or innernode(target, target) # type: ignore[call-arg]
-
- # Get the role instance, but don't *execute it* - we lack the
- # correct state to do so. Instead, we'll just use its public
- # methods to do our reference formatting, and emulate the rest.
- role = env.get_domain(domain).roles[rolename]
- assert isinstance(role, XRefRole)
-
- # XRefRole features not supported by this compatibility shim;
- # these were not supported in Sphinx 3.x either, so nothing of
- # value is really lost.
- assert not target.startswith("!")
- assert not re.match(ReferenceRole.explicit_title_re, target)
- assert not role.lowercase
- assert not role.fix_parens
-
- # Code below based mostly on sphinx.roles.XRefRole; run() and
- # create_xref_node()
- options = {
- "refdoc": env.docname,
- "refdomain": domain,
- "reftype": rolename,
- "refexplicit": False,
- "refwarn": role.warn_dangling,
- }
- refnode = role.nodeclass(target, **options)
- title, target = role.process_link(env, refnode, False, target, target)
- refnode["reftarget"] = target
- classes = ["xref", domain, f"{domain}-{rolename}"]
- refnode += role.innernodeclass(target, title, classes=classes)
-
- # This is the very gross part of the hack. Normally,
- # result_nodes takes a document object to which we would pass
- # self.inliner.document. Prior to Sphinx 4.1, we don't *have* an
- # inliner to pass, so we have nothing to pass here. However, the
- # actual implementation of role.result_nodes in this case
- # doesn't actually use that argument, so this winds up being
- # ... fine. Rest easy at night knowing this code only runs under
- # old versions of Sphinx, so at least it won't change in the
- # future on us and lead to surprising new failures.
- # Gross, I know.
- result_nodes, _messages = role.result_nodes(
- None, # type: ignore
- env,
- refnode,
- is_ref=True,
- )
- return nodes.inline(target, "", *result_nodes)
-
-
-class CompatField(docfields.Field):
- if MAKE_XREF_WORKAROUND:
- make_xref = _compat_make_xref
-
-
-class CompatGroupedField(docfields.GroupedField):
- if MAKE_XREF_WORKAROUND:
- make_xref = _compat_make_xref
-
-
-class CompatTypedField(docfields.TypedField):
- if MAKE_XREF_WORKAROUND:
- make_xref = _compat_make_xref
-
-
-# ################################################################
-# Nested parsing error location fix for Sphinx 5.3.0 < x < 6.2.0 #
-# ################################################################
-
-# When we require Sphinx 4.x, the TYPE_CHECKING hack where we avoid
-# subscripting ObjectDescription at runtime can be removed in favor of
-# just always subscripting the class.
-
-# When we require Sphinx > 6.2.0, the rest of this compatibility hack
-# can be dropped and QAPIObject can just inherit directly from
-# ObjectDescription[Signature].
-
-SOURCE_LOCATION_FIX = (5, 3, 0) <= sphinx.version_info[:3] < (6, 2, 0)
-
-Signature = str
-
-
-if TYPE_CHECKING:
- _BaseClass = ObjectDescription[Signature]
-else:
- _BaseClass = ObjectDescription
-
-
-class ParserFix(_BaseClass):
-
- _temp_content: StringList
- _temp_offset: int
- _temp_node: Optional[addnodes.desc_content]
-
- def before_content(self) -> None:
- # Work around a sphinx bug and parse the content ourselves.
- self._temp_content = self.content
- self._temp_offset = self.content_offset
- self._temp_node = None
-
- if SOURCE_LOCATION_FIX:
- self._temp_node = addnodes.desc_content()
- self.state.nested_parse(
- self.content, self.content_offset, self._temp_node
- )
- # Sphinx will try to parse the content block itself,
- # Give it nothingness to parse instead.
- self.content = StringList()
- self.content_offset = 0
-
- def transform_content(self, content_node: addnodes.desc_content) -> None:
- # Sphinx workaround: Inject our parsed content and restore state.
- if self._temp_node:
- content_node += self._temp_node.children
- self.content = self._temp_content
- self.content_offset = self._temp_offset
diff --git a/docs/sphinx/fakedbusdoc.py b/docs/sphinx/fakedbusdoc.py
deleted file mode 100644
index 2d2e6ef640..0000000000
--- a/docs/sphinx/fakedbusdoc.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# D-Bus XML documentation extension, compatibility gunk for <sphinx4
-#
-# Copyright (C) 2021, Red Hat Inc.
-#
-# SPDX-License-Identifier: LGPL-2.1-or-later
-#
-# Author: Marc-André Lureau <marcandre.lureau@redhat.com>
-"""dbus-doc is a Sphinx extension that provides documentation from D-Bus XML."""
-
-from docutils.parsers.rst import Directive
-from sphinx.application import Sphinx
-from typing import Any, Dict
-
-
-class FakeDBusDocDirective(Directive):
- has_content = True
- required_arguments = 1
-
- def run(self):
- return []
-
-
-def setup(app: Sphinx) -> Dict[str, Any]:
- """Register a fake dbus-doc directive with Sphinx"""
- app.add_directive("dbus-doc", FakeDBusDocDirective)
-
- return dict(
- parallel_read_safe = True,
- parallel_write_safe = True
- )
diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py
index f561dc465f..159857113a 100644
--- a/docs/sphinx/qapi_domain.py
+++ b/docs/sphinx/qapi_domain.py
@@ -30,20 +30,10 @@ from sphinx.domains import (
)
from sphinx.locale import _, __
from sphinx.roles import XRefRole
-from sphinx.util import logging
+from sphinx.util import docfields, logging
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_id, make_refnode
-from compat import (
- CompatField,
- CompatGroupedField,
- CompatTypedField,
- KeywordNode,
- ParserFix,
- Signature,
- SpaceNode,
-)
-
if TYPE_CHECKING:
from typing import (
@@ -157,7 +147,10 @@ class QAPIXRefRole(XRefRole):
return results, []
-class QAPIDescription(ParserFix):
+Signature = str
+
+
+class QAPIDescription(ObjectDescription[Signature]):
"""
Generic QAPI description.
@@ -315,7 +308,7 @@ class QAPIObject(QAPIDescription):
doc_field_types = [
# :feat name: descr
- CompatGroupedField(
+ docfields.GroupedField(
"feature",
label=_("Features"),
names=("feat",),
@@ -327,8 +320,8 @@ class QAPIObject(QAPIDescription):
"""Return a prefix to put before the object name in the signature."""
assert self.objtype
return [
- KeywordNode("", self.objtype.title()),
- SpaceNode(" "),
+ addnodes.desc_sig_keyword("", self.objtype.title()),
+ addnodes.desc_sig_space(" "),
]
def get_signature_suffix(self) -> List[nodes.Node]:
@@ -337,7 +330,7 @@ class QAPIObject(QAPIDescription):
if "since" in self.options:
ret += [
- SpaceNode(" "),
+ addnodes.desc_sig_space(" "),
addnodes.desc_sig_element(
"", f"(Since: {self.options['since']})"
),
@@ -376,7 +369,7 @@ class QAPIObject(QAPIDescription):
return sig
- def _add_infopips(self, contentnode: addnodes.desc_content) -> None:
+ def _add_infopips(self, content_node: addnodes.desc_content) -> None:
# Add various eye-catches and things that go below the signature
# bar, but precede the user-defined content.
infopips = nodes.container()
@@ -420,7 +413,7 @@ class QAPIObject(QAPIDescription):
)
if infopips.children:
- contentnode.insert(0, infopips)
+ content_node.insert(0, infopips)
def _validate_field(self, field: nodes.field) -> None:
"""Validate field lists in this QAPI Object Description."""
@@ -470,7 +463,17 @@ class QAPIObject(QAPIDescription):
)
logger.warning(msg, location=field)
- def transform_content(self, content_node: addnodes.desc_content) -> None:
+ def transform_content(
+ self,
+ # Sphinx changed the name of the content_node parameter
+ # sometime after Sphinx 7.2.6, so no matter which name we
+ # choose, either our minimum tests or our bleeding edge tests
+ # will complain about the parameter rename. Use the eventual
+ # name and silence the error for our minreq tests.
+ #
+ # pylint: disable=arguments-renamed
+ content_node: addnodes.desc_content
+ ) -> None:
# This hook runs after before_content and the nested parse, but
# before the DocFieldTransformer is executed.
super().transform_content(content_node)
@@ -485,7 +488,7 @@ class QAPIObject(QAPIDescription):
self._validate_field(field)
-class SpecialTypedField(CompatTypedField):
+class SpecialTypedField(docfields.TypedField):
def make_field(self, *args: Any, **kwargs: Any) -> nodes.field:
ret = super().make_field(*args, **kwargs)
@@ -518,14 +521,14 @@ class QAPICommand(QAPIObject):
can_collapse=False,
),
# :error: descr
- CompatField(
+ docfields.Field(
"error",
label=_("Errors"),
names=("error", "errors"),
has_arg=False,
),
# :return TypeName: descr
- CompatGroupedField(
+ docfields.GroupedField(
"returnvalue",
label=_("Return"),
rolename="type",
@@ -533,7 +536,7 @@ class QAPICommand(QAPIObject):
can_collapse=True,
),
# :return-nodesc: TypeName
- CompatField(
+ docfields.Field(
"returnvalue",
label=_("Return"),
names=("return-nodesc",),
@@ -551,7 +554,7 @@ class QAPIEnum(QAPIObject):
doc_field_types.extend(
[
# :value name: descr
- CompatGroupedField(
+ docfields.GroupedField(
"value",
label=_("Values"),
names=("value",),
@@ -568,7 +571,7 @@ class QAPIAlternate(QAPIObject):
doc_field_types.extend(
[
# :alt type name: descr
- CompatTypedField(
+ docfields.TypedField(
"alternative",
label=_("Alternatives"),
names=("alt",),