Python: 3.13 compat & sphinx minver bump

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmaVXSsACgkQfe+BBqr8
 OQ6tQw//blMWAbcaijg+GyesMrJGJ2xJx0G68DNfhGgpsTcRu9qnd3Q+s56c2pLq
 iJwxaRtTOaYvUhDdcsjpxKJXUIn2WnoqePb31lxXtB9DMxJW6egOvoEzYVpBqlER
 mFp4Feo8bi4/immHcnB8J05fJqGB5Rthp3Bl0s+QH6s2OKHl4rIKYNZTrxwrqKoF
 8vLg25MMHVzsojXPMfr6VTfxQ84OWXPvHTKMg5E0/OEK6FxGo3PSVTSpc6MtQJuV
 UPAWVqykfuiXC08xg9QpzEvcJGXhGjNDILWWxI+d/8e1rkTiDqOb0LvLhWsa7paO
 LOwsC863YpEPxH0utwfqNQKdTZx1VcnAss4uxULXBucnZ2J7OZp/xZ3xbJCHIbuN
 XRX7/bGKQl3KJ+d+fw5Nto0ANScU+uGaOMAb4tAT+0ChD3uVmkjS4h8D3BAoCBeO
 9PNtUkpaNGeRAg+iFrGKLTtEUUVsJNIKTlFLSEHRJUCI+/AvX+UvZeEVnlO+qf1/
 rz1chIbw6YgY60NEc7dy7aDhqa9hPTRSYwT79WoPUh74hIiwE3d4TJfL22n5H2jM
 0ryVPd+lIC7XqF+1FDx/PMxD0mhX2k++WjEpYldsZ2s3UQP5L8M8APKm6MHdMGhn
 rl0fPyVSveF7CMTvy1Y9BTycZHQAOH/9QMM1fm+6JBFgz52QsYg=
 =PLig
 -----END PGP SIGNATURE-----

Merge tag 'python-pull-request' of https://gitlab.com/jsnow/qemu into staging

Python: 3.13 compat & sphinx minver bump

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmaVXSsACgkQfe+BBqr8
# OQ6tQw//blMWAbcaijg+GyesMrJGJ2xJx0G68DNfhGgpsTcRu9qnd3Q+s56c2pLq
# iJwxaRtTOaYvUhDdcsjpxKJXUIn2WnoqePb31lxXtB9DMxJW6egOvoEzYVpBqlER
# mFp4Feo8bi4/immHcnB8J05fJqGB5Rthp3Bl0s+QH6s2OKHl4rIKYNZTrxwrqKoF
# 8vLg25MMHVzsojXPMfr6VTfxQ84OWXPvHTKMg5E0/OEK6FxGo3PSVTSpc6MtQJuV
# UPAWVqykfuiXC08xg9QpzEvcJGXhGjNDILWWxI+d/8e1rkTiDqOb0LvLhWsa7paO
# LOwsC863YpEPxH0utwfqNQKdTZx1VcnAss4uxULXBucnZ2J7OZp/xZ3xbJCHIbuN
# XRX7/bGKQl3KJ+d+fw5Nto0ANScU+uGaOMAb4tAT+0ChD3uVmkjS4h8D3BAoCBeO
# 9PNtUkpaNGeRAg+iFrGKLTtEUUVsJNIKTlFLSEHRJUCI+/AvX+UvZeEVnlO+qf1/
# rz1chIbw6YgY60NEc7dy7aDhqa9hPTRSYwT79WoPUh74hIiwE3d4TJfL22n5H2jM
# 0ryVPd+lIC7XqF+1FDx/PMxD0mhX2k++WjEpYldsZ2s3UQP5L8M8APKm6MHdMGhn
# rl0fPyVSveF7CMTvy1Y9BTycZHQAOH/9QMM1fm+6JBFgz52QsYg=
# =PLig
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 16 Jul 2024 03:32:27 AM AEST
# gpg:                using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# 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:
  docs: remove Sphinx 1.x compatibility code
  Python: bump minimum sphinx version to 3.4.3
  python: enable testing for 3.13
  iotests: Change imports for Python 3.13
  python: Do not use pylint 3.2.4 with python 3.8
  python: linter changes for pylint 3.x

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-07-16 06:45:23 +10:00
commit 959269e910
12 changed files with 41 additions and 112 deletions

View File

@ -53,10 +53,9 @@ sys.path.insert(0, os.path.join(qemu_docdir, "../scripts"))
# If your documentation needs a minimal Sphinx version, state it here. # If your documentation needs a minimal Sphinx version, state it here.
# #
# Sphinx 1.5 and earlier can't build our docs because they are too # 3.4.3 is the oldest version of Sphinx that ships on a platform we
# picky about the syntax of the argument to the option:: directive # pledge build support for.
# (see Sphinx bugs #646, #3366). needs_sphinx = '3.4.3'
needs_sphinx = '1.6'
# Add any Sphinx extension module names here, as strings. They can be # Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom

View File

@ -24,16 +24,10 @@ from docutils import nodes
from docutils.statemachine import ViewList from docutils.statemachine import ViewList
from docutils.parsers.rst import directives, Directive from docutils.parsers.rst import directives, Directive
from sphinx.errors import ExtensionError from sphinx.errors import ExtensionError
from sphinx.util.docutils import switch_source_input
from sphinx.util.nodes import nested_parse_with_titles from sphinx.util.nodes import nested_parse_with_titles
import sphinx import sphinx
# Sphinx up to 1.6 uses AutodocReporter; 1.7 and later
# use switch_source_input. Check borrowed from kerneldoc.py.
Use_SSI = sphinx.__version__[:3] >= '1.7'
if Use_SSI:
from sphinx.util.docutils import switch_source_input
else:
from sphinx.ext.autodoc import AutodocReporter
__version__ = '1.0' __version__ = '1.0'
@ -185,16 +179,9 @@ class HxtoolDocDirective(Directive):
# of title_styles and section_level that kerneldoc.py does, # of title_styles and section_level that kerneldoc.py does,
# because nested_parse_with_titles() does that for us. # because nested_parse_with_titles() does that for us.
def do_parse(self, result, node): def do_parse(self, result, node):
if Use_SSI: with switch_source_input(self.state, result):
with switch_source_input(self.state, result): nested_parse_with_titles(self.state, result, node)
nested_parse_with_titles(self.state, result, node)
else:
save = self.state.memo.reporter
self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
try:
nested_parse_with_titles(self.state, result, node)
finally:
self.state.memo.reporter = save
def setup(app): def setup(app):
""" Register hxtool-doc directive with Sphinx""" """ Register hxtool-doc directive with Sphinx"""

View File

@ -38,20 +38,14 @@ from docutils import nodes, statemachine
from docutils.statemachine import ViewList from docutils.statemachine import ViewList
from docutils.parsers.rst import directives, Directive from docutils.parsers.rst import directives, Directive
#
# AutodocReporter is only good up to Sphinx 1.7
#
import sphinx import sphinx
from sphinx.util import logging
from sphinx.util.docutils import switch_source_input
Use_SSI = sphinx.__version__[:3] >= '1.7'
if Use_SSI:
from sphinx.util.docutils import switch_source_input
else:
from sphinx.ext.autodoc import AutodocReporter
import kernellog
__version__ = '1.0' __version__ = '1.0'
logger = logging.getLogger('kerneldoc')
class KernelDocDirective(Directive): class KernelDocDirective(Directive):
"""Extract kernel-doc comments from the specified file""" """Extract kernel-doc comments from the specified file"""
@ -111,8 +105,7 @@ class KernelDocDirective(Directive):
cmd += [filename] cmd += [filename]
try: try:
kernellog.verbose(env.app, logger.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd)))
'calling kernel-doc \'%s\'' % (" ".join(cmd)))
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate() out, err = p.communicate()
@ -122,8 +115,10 @@ class KernelDocDirective(Directive):
if p.returncode != 0: if p.returncode != 0:
sys.stderr.write(err) sys.stderr.write(err)
kernellog.warn(env.app, logger.warning(
'kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode)) 'kernel-doc \'%s\' failed with return code %d' %
(" ".join(cmd), p.returncode)
)
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
elif env.config.kerneldoc_verbosity > 0: elif env.config.kerneldoc_verbosity > 0:
sys.stderr.write(err) sys.stderr.write(err)
@ -149,22 +144,13 @@ class KernelDocDirective(Directive):
return node.children return node.children
except Exception as e: # pylint: disable=W0703 except Exception as e: # pylint: disable=W0703
kernellog.warn(env.app, 'kernel-doc \'%s\' processing failed with: %s' % logger.warning('kernel-doc \'%s\' processing failed with: %s' %
(" ".join(cmd), str(e))) (" ".join(cmd), str(e)))
return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))] return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
def do_parse(self, result, node): def do_parse(self, result, node):
if Use_SSI: with switch_source_input(self.state, result):
with switch_source_input(self.state, result): self.state.nested_parse(result, 0, node, match_titles=1)
self.state.nested_parse(result, 0, node, match_titles=1)
else:
save = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
self.state.memo.title_styles, self.state.memo.section_level = [], 0
try:
self.state.nested_parse(result, 0, node, match_titles=1)
finally:
self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = save
def setup(app): def setup(app):

View File

@ -1,28 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Sphinx has deprecated its older logging interface, but the replacement
# only goes back to 1.6. So here's a wrapper layer to keep around for
# as long as we support 1.4.
#
import sphinx
if sphinx.__version__[:3] >= '1.6':
UseLogging = True
from sphinx.util import logging
logger = logging.getLogger('kerneldoc')
else:
UseLogging = False
def warn(app, message):
if UseLogging:
logger.warning(message)
else:
app.warn(message)
def verbose(app, message):
if UseLogging:
logger.verbose(message)
else:
app.verbose(message)

View File

@ -35,22 +35,11 @@ from qapi.error import QAPIError, QAPISemError
from qapi.gen import QAPISchemaVisitor from qapi.gen import QAPISchemaVisitor
from qapi.schema import QAPISchema from qapi.schema import QAPISchema
import sphinx
from sphinx.errors import ExtensionError from sphinx.errors import ExtensionError
from sphinx.util.docutils import switch_source_input
from sphinx.util.nodes import nested_parse_with_titles from sphinx.util.nodes import nested_parse_with_titles
# Sphinx up to 1.6 uses AutodocReporter; 1.7 and later
# use switch_source_input. Check borrowed from kerneldoc.py.
USE_SSI = sphinx.__version__[:3] >= "1.7"
if USE_SSI:
from sphinx.util.docutils import switch_source_input
else:
from sphinx.ext.autodoc import ( # pylint: disable=no-name-in-module
AutodocReporter,
)
__version__ = "1.0" __version__ = "1.0"
@ -539,24 +528,8 @@ class QAPIDocDirective(Directive):
subheadings (titles) without confusing the rendering of subheadings (titles) without confusing the rendering of
anything else. anything else.
""" """
# This is from kerneldoc.py -- it works around an API change in with switch_source_input(self.state, rstlist):
# Sphinx between 1.6 and 1.7. Unlike kerneldoc.py, we use nested_parse_with_titles(self.state, rstlist, node)
# sphinx.util.nodes.nested_parse_with_titles() rather than the
# plain self.state.nested_parse(), and so we can drop the saving
# of title_styles and section_level that kerneldoc.py does,
# because nested_parse_with_titles() does that for us.
if USE_SSI:
with switch_source_input(self.state, rstlist):
nested_parse_with_titles(self.state, rstlist, node)
else:
save = self.state.memo.reporter
self.state.memo.reporter = AutodocReporter(
rstlist, self.state.memo.reporter
)
try:
nested_parse_with_titles(self.state, rstlist, node)
finally:
self.state.memo.reporter = save
def setup(app): def setup(app):

View File

@ -335,6 +335,7 @@ class QEMUMachine:
def _pre_launch(self) -> None: def _pre_launch(self) -> None:
if self._qmp_set: if self._qmp_set:
sock = None
if self._monitor_address is None: if self._monitor_address is None:
self._sock_pair = socket.socketpair() self._sock_pair = socket.socketpair()
os.set_inheritable(self._sock_pair[0].fileno(), True) os.set_inheritable(self._sock_pair[0].fileno(), True)

View File

@ -174,7 +174,7 @@ class QemuGuestAgentClient:
# On error exception will raise # On error exception will raise
except asyncio.TimeoutError: except asyncio.TimeoutError:
# On success command will timed out # On success command will timed out
return pass
def shutdown(self, mode: str = 'powerdown') -> None: def shutdown(self, mode: str = 'powerdown') -> None:
if mode not in ['powerdown', 'halt', 'reboot']: if mode not in ['powerdown', 'halt', 'reboot']:

View File

@ -19,6 +19,7 @@ classifiers =
Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12 Programming Language :: Python :: 3.12
Programming Language :: Python :: 3.13
Typing :: Typed Typing :: Typed
[options] [options]
@ -41,6 +42,7 @@ devel =
isort >= 5.1.2 isort >= 5.1.2
mypy >= 1.4.0 mypy >= 1.4.0
pylint >= 2.17.3 pylint >= 2.17.3
pylint != 3.2.4; python_version<"3.9"
tox >= 3.18.0 tox >= 3.18.0
urwid >= 2.1.2 urwid >= 2.1.2
urwid-readline >= 0.13 urwid-readline >= 0.13
@ -183,7 +185,7 @@ multi_line_output=3
# of python available on your system to run this test. # of python available on your system to run this test.
[tox:tox] [tox:tox]
envlist = py38, py39, py310, py311, py312 envlist = py38, py39, py310, py311, py312, py313
skip_missing_interpreters = true skip_missing_interpreters = true
[testenv] [testenv]

View File

@ -23,7 +23,7 @@ meson = { accepted = ">=1.1.0", installed = "1.2.3", canary = "meson" }
[docs] [docs]
# Please keep the installed versions in sync with docs/requirements.txt # Please keep the installed versions in sync with docs/requirements.txt
sphinx = { accepted = ">=1.6", installed = "5.3.0", canary = "sphinx-build" } sphinx = { accepted = ">=3.4.3", installed = "5.3.0", canary = "sphinx-build" }
sphinx_rtd_theme = { accepted = ">=0.5", installed = "1.1.1" } sphinx_rtd_theme = { accepted = ">=0.5", installed = "1.1.1" }
[avocado] [avocado]

View File

@ -14,6 +14,7 @@ ENV PACKAGES \
python3.10 \ python3.10 \
python3.11 \ python3.11 \
python3.12 \ python3.12 \
python3.13 \
python3.8 \ python3.8 \
python3.9 python3.9

View File

@ -25,7 +25,12 @@ import collections
import random import random
import subprocess import subprocess
import glob import glob
from typing import List, Dict, Any, Optional, ContextManager from typing import List, Dict, Any, Optional
if sys.version_info >= (3, 9):
from contextlib import AbstractContextManager as ContextManager
else:
from typing import ContextManager
DEF_GDB_OPTIONS = 'localhost:12345' DEF_GDB_OPTIONS = 'localhost:12345'

View File

@ -27,11 +27,14 @@ import json
import shutil import shutil
import sys import sys
from multiprocessing import Pool from multiprocessing import Pool
from typing import List, Optional, Any, Sequence, Dict, \ from typing import List, Optional, Any, Sequence, Dict
ContextManager
from testenv import TestEnv from testenv import TestEnv
if sys.version_info >= (3, 9):
from contextlib import AbstractContextManager as ContextManager
else:
from typing import ContextManager
def silent_unlink(path: Path) -> None: def silent_unlink(path: Path) -> None:
try: try: