This patch changes type hints that have built-in equivalents as of
Python 3.9. The versions we currently use, imported from the typing
module, have been deprecated since 3.9 and may be removed at any time -
though to my knowledge, they are not scheduled for removal in 3.14.

The type hints to update are:

typing.Dict  => dict
typing.List  => list
typing.Tuple => tuple
typing.Set   => set
typing.Type  => type

I performed this change the dumb way (I couldn't work out for the life
of me how to beg ls-files to exclude subprojects and empty directories,
desipte it having an option which claims to do precisely that. Suggest a
nicer way to do this if you'd like.)

git ls-files | grep -v 'roms/' | grep -v 'subprojects/' | grep -v 
'tests/lcitool/libvirt-ci' | xargs sed -i -e 's/Dict\[/dict\[/g'
git ls-files | grep -v 'roms/' | grep -v 'subprojects/' | grep -v 
'tests/lcitool/libvirt-ci' | xargs sed -i -e 's/List\[/list\[/g'
git ls-files | grep -v 'roms/' | grep -v 'subprojects/' | grep -v 
'tests/lcitool/libvirt-ci' | xargs sed -i -e 's/Tuple\[/tuple\[/g'
git ls-files | grep -v 'roms/' | grep -v 'subprojects/' | grep -v 
'tests/lcitool/libvirt-ci' | xargs sed -i -e 's/Set\[/set\[/g'
git ls-files | grep -v 'roms/' | grep -v 'subprojects/' | grep -v 
'tests/lcitool/libvirt-ci' | xargs sed -i -e 's/Type\[/type\[/g'

I then used "git add -p" and excluded changes by hand that weren't
appropriate. I then reviewed all of the changed files by hand to review
the imports and update them accordingly.

Signed-off-by: John Snow <js...@redhat.com>
---
 docs/sphinx/compat.py                         |   3 +-
 docs/sphinx/dbusdoc.py                        |   9 +-
 docs/sphinx/dbusdomain.py                     |  29 ++---
 docs/sphinx/fakedbusdoc.py                    |   4 +-
 docs/sphinx/qapi_domain.py                    |  68 +++++------
 docs/sphinx/qapidoc.py                        |   7 +-
 python/qemu/machine/machine.py                |  30 ++---
 python/qemu/machine/qtest.py                  |  12 +-
 python/qemu/qmp/events.py                     |  15 +--
 python/qemu/qmp/legacy.py                     |  13 +-
 python/qemu/qmp/message.py                    |   7 +-
 python/qemu/qmp/models.py                     |   3 +-
 python/qemu/qmp/protocol.py                   |   8 +-
 python/qemu/qmp/qmp_client.py                 |   6 +-
 python/qemu/qmp/qmp_shell.py                  |  10 +-
 python/qemu/qmp/qmp_tui.py                    |  21 ++--
 python/qemu/utils/accel.py                    |   4 +-
 python/qemu/utils/qemu_ga_client.py           |   3 +-
 python/qemu/utils/qom_common.py               |  17 +--
 python/qemu/utils/qom_fuse.py                 |   3 +-
 python/scripts/mkvenv.py                      |  14 +--
 .../codeconverter/codeconverter/patching.py   |  44 +++----
 .../codeconverter/codeconverter/qom_macros.py |  36 +++---
 .../codeconverter/qom_type_info.py            |  16 +--
 scripts/compare-machine-types.py              |  40 +++---
 scripts/qapi/commands.py                      |  13 +-
 scripts/qapi/common.py                        |   9 +-
 scripts/qapi/events.py                        |   8 +-
 scripts/qapi/expr.py                          |  20 ++-
 scripts/qapi/gen.py                           |  12 +-
 scripts/qapi/introspect.py                    |  42 +++----
 scripts/qapi/parser.py                        |  37 +++---
 scripts/qapi/schema.py                        | 114 +++++++++---------
 scripts/qapi/source.py                        |  10 +-
 scripts/qapi/types.py                         |  20 +--
 scripts/qapi/visit.py                         |  14 +--
 scripts/rust/rustc_args.py                    |   6 +-
 scripts/u2f-setup-gen.py                      |   3 +-
 tests/functional/qemu_test/ports.py           |   3 +-
 tests/functional/test_acpi_bits.py            |   3 +-
 tests/qemu-iotests/151                        |   4 +-
 tests/qemu-iotests/297                        |   5 +-
 tests/qemu-iotests/300                        |   4 +-
 tests/qemu-iotests/fat16.py                   |  10 +-
 tests/qemu-iotests/findtests.py               |  12 +-
 tests/qemu-iotests/iotests.py                 |  38 +++---
 tests/qemu-iotests/linters.py                 |   6 +-
 tests/qemu-iotests/testenv.py                 |   6 +-
 tests/qemu-iotests/testrunner.py              |  12 +-
 .../qemu-iotests/tests/stream-under-throttle  |   3 +-
 50 files changed, 375 insertions(+), 461 deletions(-)

diff --git a/docs/sphinx/compat.py b/docs/sphinx/compat.py
index 9cf7fe006e4..50002b6fea7 100644
--- a/docs/sphinx/compat.py
+++ b/docs/sphinx/compat.py
@@ -8,7 +8,6 @@
     Any,
     Callable,
     Optional,
-    Type,
 )
 
 from docutils import nodes
@@ -85,7 +84,7 @@ def _compat_make_xref(  # pylint: disable=unused-argument
     rolename: str,
     domain: str,
     target: str,
-    innernode: Type[TextlikeNode] = addnodes.literal_emphasis,
+    innernode: type[TextlikeNode] = addnodes.literal_emphasis,
     contnode: Optional[Node] = None,
     env: Optional[BuildEnvironment] = None,
     inliner: Any = None,
diff --git a/docs/sphinx/dbusdoc.py b/docs/sphinx/dbusdoc.py
index be284ed08fd..5bff49b41d2 100644
--- a/docs/sphinx/dbusdoc.py
+++ b/docs/sphinx/dbusdoc.py
@@ -13,14 +13,9 @@
     TYPE_CHECKING,
     Any,
     Callable,
-    Dict,
     Iterator,
-    List,
     Optional,
     Sequence,
-    Set,
-    Tuple,
-    Type,
     TypeVar,
     Union,
 )
@@ -116,7 +111,7 @@ def add_interface(self, iface):
         self.indent = self.indent[:-3]
 
 
-def parse_generated_content(state: RSTState, content: StringList) -> 
List[Node]:
+def parse_generated_content(state: RSTState, content: StringList) -> 
list[Node]:
     """Parse a generated content by Documenter."""
     with switch_source_input(state, content):
         node = nodes.paragraph()
@@ -157,7 +152,7 @@ def run(self):
         return result
 
 
-def setup(app: Sphinx) -> Dict[str, Any]:
+def setup(app: Sphinx) -> dict[str, Any]:
     """Register dbus-doc directive with Sphinx"""
     app.add_config_value("dbusdoc_srctree", None, "env")
     app.add_directive("dbus-doc", DBusDocDirective)
diff --git a/docs/sphinx/dbusdomain.py b/docs/sphinx/dbusdomain.py
index 9872fd5bf6a..75a6b5590bc 100644
--- a/docs/sphinx/dbusdomain.py
+++ b/docs/sphinx/dbusdomain.py
@@ -8,13 +8,10 @@
 
 from typing import (
     Any,
-    Dict,
     Iterable,
     Iterator,
-    List,
     NamedTuple,
     Optional,
-    Tuple,
     cast,
 )
 
@@ -87,7 +84,7 @@ def handle_signature(self, sig: str, signode: desc_signature) 
-> str:
         signode += addnodes.desc_name(sig, sig)
         return sig
 
-    def run(self) -> List[Node]:
+    def run(self) -> list[Node]:
         _, node = super().run()
         name = self.arguments[0]
         section = nodes.section(ids=[name + "-section"])
@@ -113,7 +110,7 @@ class DBusMethod(DBusMember):
         }
     )
 
-    doc_field_types: List[Field] = [
+    doc_field_types: list[Field] = [
         TypedField(
             "arg",
             label=_("Arguments"),
@@ -171,7 +168,7 @@ class DBusSignal(DBusMethod):
     Implementation of ``dbus:signal``.
     """
 
-    doc_field_types: List[Field] = [
+    doc_field_types: list[Field] = [
         TypedField(
             "arg",
             label=_("Arguments"),
@@ -203,7 +200,7 @@ class DBusProperty(DBusMember):
         }
     )
 
-    doc_field_types: List[Field] = []
+    doc_field_types: list[Field] = []
 
     def get_index_text(self, ifacename: str, name: str) -> str:
         return _("%s (%s property)") % (name, ifacename)
@@ -244,7 +241,7 @@ def handle_signature(self, sig: str, signode: 
desc_signature) -> str:
         signode += addnodes.desc_sig_keyword_type(ty, ty)
         return sig
 
-    def run(self) -> List[Node]:
+    def run(self) -> list[Node]:
         self.name = "dbus:member"
         return super().run()
 
@@ -281,10 +278,10 @@ class DBusIndex(Index):
 
     def generate(
         self, docnames: Iterable[str] = None
-    ) -> Tuple[List[Tuple[str, List[IndexEntry]]], bool]:
-        content: Dict[str, List[IndexEntry]] = {}
+    ) -> tuple[list[tuple[str, list[IndexEntry]]], bool]:
+        content: dict[str, list[IndexEntry]] = {}
         # list of prefixes to ignore
-        ignores: List[str] = self.domain.env.config["dbus_index_common_prefix"]
+        ignores: list[str] = self.domain.env.config["dbus_index_common_prefix"]
         ignores = sorted(ignores, key=len, reverse=True)
 
         ifaces = sorted(
@@ -329,7 +326,7 @@ class DBusDomain(Domain):
 
     name = "dbus"
     label = "D-Bus"
-    object_types: Dict[str, ObjType] = {
+    object_types: dict[str, ObjType] = {
         "interface": ObjType(_("interface"), "iface", "obj"),
         "method": ObjType(_("method"), "meth", "obj"),
         "signal": ObjType(_("signal"), "sig", "obj"),
@@ -347,7 +344,7 @@ class DBusDomain(Domain):
         "sig": DBusXRef(),
         "prop": DBusXRef(),
     }
-    initial_data: Dict[str, Dict[str, Tuple[Any]]] = {
+    initial_data: dict[str, dict[str, tuple[Any]]] = {
         "objects": {},  # fullname -> ObjectEntry
     }
     indices = [
@@ -355,7 +352,7 @@ class DBusDomain(Domain):
     ]
 
     @property
-    def objects(self) -> Dict[str, ObjectEntry]:
+    def objects(self) -> dict[str, ObjectEntry]:
         return self.data.setdefault("objects", {})  # fullname -> ObjectEntry
 
     def note_object(
@@ -368,7 +365,7 @@ def clear_doc(self, docname: str) -> None:
             if obj.docname == docname:
                 del self.objects[fullname]
 
-    def find_obj(self, typ: str, name: str) -> Optional[Tuple[str, 
ObjectEntry]]:
+    def find_obj(self, typ: str, name: str) -> Optional[tuple[str, 
ObjectEntry]]:
         # skip parens
         if name[-2:] == "()":
             name = name[:-2]
@@ -396,7 +393,7 @@ def resolve_xref(
                 builder, fromdocname, objdef.docname, objdef.node_id, contnode
             )
 
-    def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
+    def get_objects(self) -> Iterator[tuple[str, str, str, str, str, int]]:
         for refname, obj in self.objects.items():
             yield (refname, refname, obj.objtype, obj.docname, obj.node_id, 1)
 
diff --git a/docs/sphinx/fakedbusdoc.py b/docs/sphinx/fakedbusdoc.py
index 2d2e6ef6403..29da1b3d93d 100644
--- a/docs/sphinx/fakedbusdoc.py
+++ b/docs/sphinx/fakedbusdoc.py
@@ -9,7 +9,7 @@
 
 from docutils.parsers.rst import Directive
 from sphinx.application import Sphinx
-from typing import Any, Dict
+from typing import Any
 
 
 class FakeDBusDocDirective(Directive):
@@ -20,7 +20,7 @@ def run(self):
         return []
 
 
-def setup(app: Sphinx) -> Dict[str, Any]:
+def setup(app: Sphinx) -> dict[str, Any]:
     """Register a fake dbus-doc directive with Sphinx"""
     app.add_directive("dbus-doc", FakeDBusDocDirective)
 
diff --git a/docs/sphinx/qapi_domain.py b/docs/sphinx/qapi_domain.py
index ebc46a72c61..665f0953b44 100644
--- a/docs/sphinx/qapi_domain.py
+++ b/docs/sphinx/qapi_domain.py
@@ -9,14 +9,7 @@
 
 import re
 import types
-from typing import (
-    TYPE_CHECKING,
-    List,
-    NamedTuple,
-    Tuple,
-    Type,
-    cast,
-)
+from typing import TYPE_CHECKING, NamedTuple, cast
 
 from docutils import nodes
 from docutils.parsers.rst import directives
@@ -49,7 +42,6 @@
     from typing import (
         AbstractSet,
         Any,
-        Dict,
         Iterable,
         Optional,
         Union,
@@ -68,7 +60,7 @@
 
 def _unpack_field(
     field: nodes.Node,
-) -> Tuple[nodes.field_name, nodes.field_body]:
+) -> tuple[nodes.field_name, nodes.field_body]:
     """
     docutils helper: unpack a field node in a type-safe manner.
     """
@@ -140,11 +132,11 @@ def result_nodes(
         env: BuildEnvironment,
         node: Element,
         is_ref: bool,
-    ) -> Tuple[List[nodes.Node], List[nodes.system_message]]:
+    ) -> tuple[list[nodes.Node], list[nodes.system_message]]:
 
         # node here is the pending_xref node (or whatever nodeclass was
         # configured at XRefRole class instantiation time).
-        results: List[nodes.Node] = [node]
+        results: list[nodes.Node] = [node]
 
         if node.get("qapi:array"):
             results.insert(0, nodes.literal("[", "["))
@@ -178,13 +170,13 @@ def handle_signature(self, sig: str, signode: 
desc_signature) -> Signature:
         # subclasses will handle this.
         return sig
 
-    def get_index_text(self, name: Signature) -> Tuple[str, str]:
+    def get_index_text(self, name: Signature) -> tuple[str, str]:
         """Return the text for the index entry of the object."""
 
         # NB: this is used for the global index, not the QAPI index.
         return ("single", f"{name} (QMP {self.objtype})")
 
-    def _get_context(self) -> Tuple[str, str]:
+    def _get_context(self) -> tuple[str, str]:
         namespace = self.options.get(
             "namespace", self.env.ref_context.get("qapi:namespace", "")
         )
@@ -240,7 +232,7 @@ def add_target_and_index(
                 )
 
     @staticmethod
-    def split_fqn(name: str) -> Tuple[str, str, str]:
+    def split_fqn(name: str) -> tuple[str, str, str]:
         if ":" in name:
             ns, name = name.split(":")
         else:
@@ -255,7 +247,7 @@ def split_fqn(name: str) -> Tuple[str, str, str]:
 
     def _object_hierarchy_parts(
         self, sig_node: desc_signature
-    ) -> Tuple[str, ...]:
+    ) -> tuple[str, ...]:
         if "fullname" not in sig_node:
             return ()
         return self.split_fqn(sig_node["fullname"])
@@ -264,7 +256,7 @@ def _toc_entry_name(self, sig_node: desc_signature) -> str:
         # This controls the name in the TOC and on the sidebar.
 
         # This is the return type of _object_hierarchy_parts().
-        toc_parts = cast(Tuple[str, ...], sig_node.get("_toc_parts", ()))
+        toc_parts = cast(tuple[str, ...], sig_node.get("_toc_parts", ()))
         if not toc_parts:
             return ""
 
@@ -323,7 +315,7 @@ class QAPIObject(QAPIDescription):
         ),
     ]
 
-    def get_signature_prefix(self) -> List[nodes.Node]:
+    def get_signature_prefix(self) -> list[nodes.Node]:
         """Return a prefix to put before the object name in the signature."""
         assert self.objtype
         return [
@@ -331,9 +323,9 @@ def get_signature_prefix(self) -> List[nodes.Node]:
             SpaceNode(" "),
         ]
 
-    def get_signature_suffix(self) -> List[nodes.Node]:
+    def get_signature_suffix(self) -> list[nodes.Node]:
         """Return a suffix to put after the object name in the signature."""
-        ret: List[nodes.Node] = []
+        ret: list[nodes.Node] = []
 
         if "since" in self.options:
             ret += [
@@ -383,7 +375,7 @@ def _add_infopips(self, contentnode: addnodes.desc_content) 
-> None:
         infopips.attributes["classes"].append("qapi-infopips")
 
         def _add_pip(
-            source: str, content: Union[str, List[nodes.Node]], classname: str
+            source: str, content: Union[str, list[nodes.Node]], classname: str
         ) -> None:
             node = nodes.container(source)
             if isinstance(content, str):
@@ -626,7 +618,7 @@ class QAPIModule(QAPIDescription):
           Lorem ipsum, dolor sit amet ...
     """
 
-    def run(self) -> List[Node]:
+    def run(self) -> list[Node]:
         modname = self.arguments[0].strip()
         self.env.ref_context["qapi:module"] = modname
         ret = super().run()
@@ -641,11 +633,11 @@ def run(self) -> List[Node]:
         ret.extend(desc_node.children[1].children)
 
         # Re-home node_ids so anchor refs still work:
-        node_ids: List[str]
+        node_ids: list[str]
         if node_ids := [
             node_id
             for el in desc_node.children[0].traverse(nodes.Element)
-            for node_id in cast(List[str], el.get("ids", ()))
+            for node_id in cast(list[str], el.get("ids", ()))
         ]:
             target_node = nodes.target(ids=node_ids)
             ret.insert(1, target_node)
@@ -657,7 +649,7 @@ class QAPINamespace(SphinxDirective):
     has_content = False
     required_arguments = 1
 
-    def run(self) -> List[Node]:
+    def run(self) -> list[Node]:
         namespace = self.arguments[0].strip()
         self.env.ref_context["qapi:namespace"] = namespace
 
@@ -679,9 +671,9 @@ class QAPIIndex(Index):
     def generate(
         self,
         docnames: Optional[Iterable[str]] = None,
-    ) -> Tuple[List[Tuple[str, List[IndexEntry]]], bool]:
+    ) -> tuple[list[tuple[str, list[IndexEntry]]], bool]:
         assert isinstance(self.domain, QAPIDomain)
-        content: Dict[str, List[IndexEntry]] = {}
+        content: dict[str, list[IndexEntry]] = {}
         collapse = False
 
         for objname, obj in self.domain.objects.items():
@@ -733,7 +725,7 @@ class QAPIDomain(Domain):
     # e.g., the :qapi:type: cross-reference role can refer to enum,
     # struct, union, or alternate objects; but :qapi:obj: can refer to
     # anything. Each object also gets its own targeted cross-reference role.
-    object_types: Dict[str, ObjType] = {
+    object_types: dict[str, ObjType] = {
         "module": ObjType(_("module"), "mod", "any"),
         "command": ObjType(_("command"), "cmd", "any"),
         "event": ObjType(_("event"), "event", "any"),
@@ -771,7 +763,7 @@ class QAPIDomain(Domain):
 
     # Moved into the data property at runtime;
     # this is the internal index of reference-able objects.
-    initial_data: Dict[str, Dict[str, Tuple[Any]]] = {
+    initial_data: dict[str, dict[str, tuple[Any]]] = {
         "objects": {},  # fullname -> ObjectEntry
     }
 
@@ -781,14 +773,14 @@ class QAPIDomain(Domain):
     ]
 
     @property
-    def objects(self) -> Dict[str, ObjectEntry]:
+    def objects(self) -> dict[str, ObjectEntry]:
         ret = self.data.setdefault("objects", {})
         return ret  # type: ignore[no-any-return]
 
     def setup(self) -> None:
         namespaces = set(self.env.app.config.qapi_namespaces)
         for namespace in namespaces:
-            new_index: Type[QAPIIndex] = types.new_class(
+            new_index: type[QAPIIndex] = types.new_class(
                 f"{namespace}Index", bases=(QAPIIndex,)
             )
             new_index.name = f"{namespace.lower()}-index"
@@ -838,7 +830,7 @@ def clear_doc(self, docname: str) -> None:
                 del self.objects[fullname]
 
     def merge_domaindata(
-        self, docnames: AbstractSet[str], otherdata: Dict[str, Any]
+        self, docnames: AbstractSet[str], otherdata: dict[str, Any]
     ) -> None:
         for fullname, obj in otherdata["objects"].items():
             if obj.docname in docnames:
@@ -853,7 +845,7 @@ def merge_domaindata(
 
     def find_obj(
         self, namespace: str, modname: str, name: str, typ: Optional[str]
-    ) -> List[Tuple[str, ObjectEntry]]:
+    ) -> list[tuple[str, ObjectEntry]]:
         """
         Find a QAPI object for "name", maybe using contextual information.
 
@@ -890,7 +882,7 @@ def find_obj(
 
         if typ is None:
             # :any: lookup, search everything:
-            objtypes: List[str] = list(self.object_types)
+            objtypes: list[str] = list(self.object_types)
         else:
             # type is specified and will be a role (e.g. obj, mod, cmd)
             # convert this to eligible object types (e.g. command, module)
@@ -901,7 +893,7 @@ def find_obj(
         # search!
         # ##
 
-        def _search(needle: str) -> List[str]:
+        def _search(needle: str) -> list[str]:
             if (
                 needle
                 and needle in self.objects
@@ -1015,8 +1007,8 @@ def resolve_any_xref(
         target: str,
         node: pending_xref,
         contnode: Element,
-    ) -> List[Tuple[str, nodes.reference]]:
-        results: List[Tuple[str, nodes.reference]] = []
+    ) -> list[tuple[str, nodes.reference]]:
+        results: list[tuple[str, nodes.reference]] = []
         matches = self.find_obj(
             node.get("qapi:namespace"), node.get("qapi:module"), target, None
         )
@@ -1031,7 +1023,7 @@ def resolve_any_xref(
         return results
 
 
-def setup(app: Sphinx) -> Dict[str, Any]:
+def setup(app: Sphinx) -> dict[str, Any]:
     app.setup_extension("sphinx.directives")
     app.add_config_value(
         "qapi_allowed_fields",
diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py
index 8011ac9efaf..ff102a8cab3 100644
--- a/docs/sphinx/qapidoc.py
+++ b/docs/sphinx/qapidoc.py
@@ -71,7 +71,6 @@
     from typing import (
         Any,
         Generator,
-        List,
         Optional,
         Sequence,
         Union,
@@ -674,7 +673,7 @@ def _highlightlang(self) -> addnodes.highlightlang:
         )
         return node
 
-    def admonition_wrap(self, *content: nodes.Node) -> List[nodes.Node]:
+    def admonition_wrap(self, *content: nodes.Node) -> list[nodes.Node]:
         title = "Example:"
         if "title" in self.options:
             title = f"{title} {self.options['title']}"
@@ -687,7 +686,7 @@ def admonition_wrap(self, *content: nodes.Node) -> 
List[nodes.Node]:
         )
         return [admon]
 
-    def run_annotated(self) -> List[nodes.Node]:
+    def run_annotated(self) -> list[nodes.Node]:
         lang_node = self._highlightlang()
 
         content_node: nodes.Element = nodes.section()
@@ -708,7 +707,7 @@ def run_annotated(self) -> List[nodes.Node]:
 
         return content_node.children
 
-    def run(self) -> List[nodes.Node]:
+    def run(self) -> list[nodes.Node]:
         annotated = "annotated" in self.options
 
         if annotated:
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index ebb58d5b68c..52a2d735d32 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -31,12 +31,8 @@
 from typing import (
     Any,
     BinaryIO,
-    Dict,
-    List,
     Optional,
     Sequence,
-    Tuple,
-    Type,
     TypeVar,
 )
 
@@ -156,9 +152,9 @@ def __init__(self,
         self._qmp_timer = qmp_timer
 
         self._name = name or f"{id(self):x}"
-        self._sock_pair: Optional[Tuple[socket.socket, socket.socket]] = None
+        self._sock_pair: Optional[tuple[socket.socket, socket.socket]] = None
         self._cons_sock_pair: Optional[
-            Tuple[socket.socket, socket.socket]] = None
+            tuple[socket.socket, socket.socket]] = None
         self._temp_dir: Optional[str] = None
         self._base_temp_dir = base_temp_dir
         self._log_dir = log_dir
@@ -176,11 +172,11 @@ def __init__(self,
         self._qemu_log_path: Optional[str] = None
         self._qemu_log_file: Optional[BinaryIO] = None
         self._popen: Optional['subprocess.Popen[bytes]'] = None
-        self._events: List[QMPMessage] = []
+        self._events: list[QMPMessage] = []
         self._iolog: Optional[str] = None
         self._qmp_set = True   # Enable QMP monitor by default.
         self._qmp_connection: Optional[QEMUMonitorProtocol] = None
-        self._qemu_full_args: Tuple[str, ...] = ()
+        self._qemu_full_args: tuple[str, ...] = ()
         self._launched = False
         self._machine: Optional[str] = None
         self._console_index = 0
@@ -188,7 +184,7 @@ def __init__(self,
         self._console_device_type: Optional[str] = None
         self._console_socket: Optional[socket.socket] = None
         self._console_file: Optional[socket.SocketIO] = None
-        self._remove_files: List[str] = []
+        self._remove_files: list[str] = []
         self._user_killed = False
         self._quit_issued = False
 
@@ -196,7 +192,7 @@ def __enter__(self: _T) -> _T:
         return self
 
     def __exit__(self,
-                 exc_type: Optional[Type[BaseException]],
+                 exc_type: Optional[type[BaseException]],
                  exc_val: Optional[BaseException],
                  exc_tb: Optional[TracebackType]) -> None:
         self.shutdown()
@@ -292,7 +288,7 @@ def _load_io_log(self) -> None:
                 self._iolog = iolog.read()
 
     @property
-    def _base_args(self) -> List[str]:
+    def _base_args(self) -> list[str]:
         args = ['-display', 'none', '-vga', 'none']
 
         if self._qmp_set:
@@ -324,7 +320,7 @@ def _base_args(self) -> List[str]:
         return args
 
     @property
-    def args(self) -> List[str]:
+    def args(self) -> list[str]:
         """Returns the list of arguments given to the QEMU binary."""
         return self._args
 
@@ -685,14 +681,14 @@ def _qmp(self) -> QEMUMonitorProtocol:
 
     @classmethod
     def _qmp_args(cls, conv_keys: bool,
-                  args: Dict[str, Any]) -> Dict[str, object]:
+                  args: dict[str, Any]) -> dict[str, object]:
         if conv_keys:
             return {k.replace('_', '-'): v for k, v in args.items()}
 
         return args
 
     def qmp(self, cmd: str,
-            args_dict: Optional[Dict[str, object]] = None,
+            args_dict: Optional[dict[str, object]] = None,
             conv_keys: Optional[bool] = None,
             **args: Any) -> QMPMessage:
         """
@@ -714,7 +710,7 @@ def qmp(self, cmd: str,
         return ret
 
     def cmd(self, cmd: str,
-            args_dict: Optional[Dict[str, object]] = None,
+            args_dict: Optional[dict[str, object]] = None,
             conv_keys: Optional[bool] = None,
             **args: Any) -> QMPReturnValue:
         """
@@ -745,7 +741,7 @@ def get_qmp_event(self, wait: bool = False) -> 
Optional[QMPMessage]:
             return self._events.pop(0)
         return self._qmp.pull_event(wait=wait)
 
-    def get_qmp_events(self, wait: bool = False) -> List[QMPMessage]:
+    def get_qmp_events(self, wait: bool = False) -> list[QMPMessage]:
         """
         Poll for queued QMP events and return a list of dicts
         """
@@ -800,7 +796,7 @@ def event_wait(self, name: str,
         return self.events_wait([(name, match)], timeout)
 
     def events_wait(self,
-                    events: Sequence[Tuple[str, Any]],
+                    events: Sequence[tuple[str, Any]],
                     timeout: float = 60.0) -> Optional[QMPMessage]:
         """
         events_wait waits for and returns a single named event from QMP.
diff --git a/python/qemu/machine/qtest.py b/python/qemu/machine/qtest.py
index 4f5ede85b23..2582d89cc5e 100644
--- a/python/qemu/machine/qtest.py
+++ b/python/qemu/machine/qtest.py
@@ -19,13 +19,7 @@
 
 import os
 import socket
-from typing import (
-    List,
-    Optional,
-    Sequence,
-    TextIO,
-    Tuple,
-)
+from typing import Optional, Sequence, TextIO
 
 from qemu.qmp import SocketAddrT
 
@@ -145,10 +139,10 @@ def __init__(self,
                          qmp_timer=qmp_timer)
         self._qtest: Optional[QEMUQtestProtocol] = None
         self._qtest_sock_pair: Optional[
-            Tuple[socket.socket, socket.socket]] = None
+            tuple[socket.socket, socket.socket]] = None
 
     @property
-    def _base_args(self) -> List[str]:
+    def _base_args(self) -> list[str]:
         args = super()._base_args
         assert self._qtest_sock_pair is not None
         fd = self._qtest_sock_pair[0].fileno()
diff --git a/python/qemu/qmp/events.py b/python/qemu/qmp/events.py
index cfb5f0ac621..93ae808b2ac 100644
--- a/python/qemu/qmp/events.py
+++ b/python/qemu/qmp/events.py
@@ -455,10 +455,7 @@ def accept(self, event) -> bool:
     Callable,
     Iterable,
     Iterator,
-    List,
     Optional,
-    Set,
-    Tuple,
     Union,
 )
 
@@ -504,10 +501,10 @@ def __init__(
         self._queue: 'asyncio.Queue[Message]' = asyncio.Queue()
 
         # Intended as a historical record, NOT a processing queue or backlog.
-        self._history: List[Message] = []
+        self._history: list[Message] = []
 
         #: Primary event filter, based on one or more event names.
-        self.names: Set[str] = set()
+        self.names: set[str] = set()
         if isinstance(names, str):
             self.names.add(names)
         elif names is not None:
@@ -517,7 +514,7 @@ def __init__(
         self.event_filter: Optional[EventFilter] = event_filter
 
     def __repr__(self) -> str:
-        args: List[str] = []
+        args: list[str] = []
         if self.names:
             args.append(f"names={self.names!r}")
         if self.event_filter:
@@ -532,7 +529,7 @@ def __repr__(self) -> str:
         return f"{type(self).__name__}{state}({argstr})"
 
     @property
-    def history(self) -> Tuple[Message, ...]:
+    def history(self) -> tuple[Message, ...]:
         """
         A read-only history of all events seen so far.
 
@@ -596,7 +593,7 @@ def empty(self) -> bool:
         """
         return self._queue.empty()
 
-    def clear(self) -> List[Message]:
+    def clear(self) -> list[Message]:
         """
         Clear this listener of all pending events.
 
@@ -650,7 +647,7 @@ class Events:
     property.
     """
     def __init__(self) -> None:
-        self._listeners: List[EventListener] = []
+        self._listeners: list[EventListener] = []
 
         #: Default, all-events `EventListener`. See `qmp.events` for more info.
         self.events: EventListener = EventListener()
diff --git a/python/qemu/qmp/legacy.py b/python/qemu/qmp/legacy.py
index 9606e731864..de859a99f72 100644
--- a/python/qemu/qmp/legacy.py
+++ b/python/qemu/qmp/legacy.py
@@ -27,10 +27,7 @@
 from typing import (
     Any,
     Awaitable,
-    Dict,
-    List,
     Optional,
-    Type,
     TypeVar,
     Union,
 )
@@ -41,13 +38,13 @@
 
 
 #: QMPMessage is an entire QMP message of any kind.
-QMPMessage = Dict[str, Any]
+QMPMessage = dict[str, Any]
 
 #: QMPReturnValue is the 'return' value of a command.
 QMPReturnValue = object
 
 #: QMPObject is any object in a QMP message.
-QMPObject = Dict[str, object]
+QMPObject = dict[str, object]
 
 # QMPMessage can be outgoing commands or incoming events/returns.
 # QMPReturnValue is usually a dict/json object, but due to QAPI's
@@ -121,7 +118,7 @@ def __enter__(self: _T) -> _T:
         return self
 
     def __exit__(self,
-                 exc_type: Optional[Type[BaseException]],
+                 exc_type: Optional[type[BaseException]],
                  exc_val: Optional[BaseException],
                  exc_tb: Optional[TracebackType]) -> None:
         # Implement context manager exit function.
@@ -202,7 +199,7 @@ def cmd_obj(self, qmp_cmd: QMPMessage) -> QMPMessage:
         )
 
     def cmd_raw(self, name: str,
-                args: Optional[Dict[str, object]] = None) -> QMPMessage:
+                args: Optional[dict[str, object]] = None) -> QMPMessage:
         """
         Build a QMP command and send it to the QMP Monitor.
 
@@ -260,7 +257,7 @@ def pull_event(self,
             )
         )
 
-    def get_events(self, wait: Union[bool, float] = False) -> List[QMPMessage]:
+    def get_events(self, wait: Union[bool, float] = False) -> list[QMPMessage]:
         """
         Get a list of QMP events and clear all pending events.
 
diff --git a/python/qemu/qmp/message.py b/python/qemu/qmp/message.py
index dabb8ec360e..d9234fa2453 100644
--- a/python/qemu/qmp/message.py
+++ b/python/qemu/qmp/message.py
@@ -8,7 +8,6 @@
 import json
 from json import JSONDecodeError
 from typing import (
-    Dict,
     Iterator,
     Mapping,
     MutableMapping,
@@ -71,7 +70,7 @@ def __init__(self,
                  value: Union[bytes, Mapping[str, object]] = b'{}', *,
                  eager: bool = True):
         self._data: Optional[bytes] = None
-        self._obj: Optional[Dict[str, object]] = None
+        self._obj: Optional[dict[str, object]] = None
 
         if isinstance(value, bytes):
             self._data = value
@@ -125,7 +124,7 @@ def __bytes__(self) -> bytes:
     # Conversion Methods
 
     @property
-    def _object(self) -> Dict[str, object]:
+    def _object(self) -> dict[str, object]:
         """
         A `dict` representing this QMP message.
 
@@ -150,7 +149,7 @@ def _serialize(cls, value: object) -> bytes:
         return json.dumps(value, separators=(',', ':')).encode('utf-8')
 
     @classmethod
-    def _deserialize(cls, data: bytes) -> Dict[str, object]:
+    def _deserialize(cls, data: bytes) -> dict[str, object]:
         """
         Deserialize JSON `bytes` into a native Python `dict`.
 
diff --git a/python/qemu/qmp/models.py b/python/qemu/qmp/models.py
index 19dbe8781f4..0e4a3c4e5ed 100644
--- a/python/qemu/qmp/models.py
+++ b/python/qemu/qmp/models.py
@@ -11,7 +11,6 @@
 import copy
 from typing import (
     Any,
-    Dict,
     Mapping,
     Optional,
     Sequence,
@@ -72,7 +71,7 @@ def __init__(self, raw: Mapping[str, Any]):
         self._check_member('QMP', abc.Mapping, "JSON object")
         self.QMP = QMPGreeting(self._raw['QMP'])
 
-    def _asdict(self) -> Dict[str, object]:
+    def _asdict(self) -> dict[str, object]:
         """
         For compatibility with the iotests sync QMP wrapper.
 
diff --git a/python/qemu/qmp/protocol.py b/python/qemu/qmp/protocol.py
index 26486889d02..43aefd7b01a 100644
--- a/python/qemu/qmp/protocol.py
+++ b/python/qemu/qmp/protocol.py
@@ -28,9 +28,7 @@
     Awaitable,
     Callable,
     Generic,
-    List,
     Optional,
-    Tuple,
     TypeVar,
     Union,
     cast,
@@ -50,7 +48,7 @@
 _U = TypeVar('_U')
 _TaskFN = Callable[[], Awaitable[None]]  # aka ``async def func() -> None``
 
-InternetAddrT = Tuple[str, int]
+InternetAddrT = tuple[str, int]
 UnixAddrT = str
 SocketAddrT = Union[UnixAddrT, InternetAddrT]
 
@@ -248,7 +246,7 @@ def __init__(self, name: Optional[str] = None) -> None:
         self._writer_task: Optional[asyncio.Future[None]] = None
 
         # Aggregate of the above two tasks, used for Exception management.
-        self._bh_tasks: Optional[asyncio.Future[Tuple[None, None]]] = None
+        self._bh_tasks: Optional[asyncio.Future[tuple[None, None]]] = None
 
         #: Disconnect task. The disconnect implementation runs in a task
         #: so that asynchronous disconnects (initiated by the
@@ -744,7 +742,7 @@ async def _wait_disconnect(self) -> None:
         assert self.runstate == Runstate.DISCONNECTING
         assert self._dc_task
 
-        aws: List[Awaitable[object]] = [self._dc_task]
+        aws: list[Awaitable[object]] = [self._dc_task]
         if self._bh_tasks:
             aws.insert(0, self._bh_tasks)
         all_defined_tasks = asyncio.gather(*aws)
diff --git a/python/qemu/qmp/qmp_client.py b/python/qemu/qmp/qmp_client.py
index 55508ff73f3..515784ab552 100644
--- a/python/qemu/qmp/qmp_client.py
+++ b/python/qemu/qmp/qmp_client.py
@@ -12,8 +12,6 @@
 import socket
 import struct
 from typing import (
-    Dict,
-    List,
     Mapping,
     Optional,
     Union,
@@ -262,7 +260,7 @@ def __init__(self, name: Optional[str] = None) -> None:
         self._execute_id = 0
 
         # Incoming RPC reply messages.
-        self._pending: Dict[
+        self._pending: dict[
             Union[str, None],
             'asyncio.Queue[QMPClient._PendingT]'
         ] = {}
@@ -339,7 +337,7 @@ async def _negotiate(self) -> None:
         """
         self.logger.debug("Negotiating capabilities ...")
 
-        arguments: Dict[str, List[str]] = {}
+        arguments: dict[str, list[str]] = {}
         if self._greeting and 'oob' in self._greeting.QMP.capabilities:
             arguments.setdefault('enable', []).append('oob')
         msg = self.make_execute_msg('qmp_capabilities', arguments=arguments)
diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/qmp/qmp_shell.py
index c39ba4be165..7265bd1120e 100644
--- a/python/qemu/qmp/qmp_shell.py
+++ b/python/qemu/qmp/qmp_shell.py
@@ -134,9 +134,7 @@
 import sys
 from typing import (
     IO,
-    Dict,
     Iterator,
-    List,
     NoReturn,
     Optional,
     Sequence,
@@ -165,9 +163,9 @@ class QMPCompleter:
     QMPCompleter provides a readline library tab-complete behavior.
     """
     # NB: Python 3.9+ will probably allow us to subclass list[str] directly,
-    # but pylint as of today does not know that List[str] is simply 'list'.
+    # but pylint as of today does not know that list[str] is simply 'list'.
     def __init__(self) -> None:
-        self._matches: List[str] = []
+        self._matches: list[str] = []
 
     def append(self, value: str) -> None:
         """Append a new valid completion to the list of possibilities."""
@@ -229,7 +227,7 @@ def __init__(self, address: SocketAddrT,
         self._greeting: Optional[QMPMessage] = None
         self._completer = QMPCompleter()
         self._transmode = False
-        self._actions: List[QMPMessage] = []
+        self._actions: list[QMPMessage] = []
         self._histfile = os.path.join(os.path.expanduser('~'),
                                       '.qmp-shell_history')
         self.pretty = pretty
@@ -246,7 +244,7 @@ def close(self) -> None:
 
     def _fill_completion(self) -> None:
         try:
-            cmds = cast(List[Dict[str, str]], self.cmd('query-commands'))
+            cmds = cast(list[dict[str, str]], self.cmd('query-commands'))
             for cmd in cmds:
                 self._completer.append(cmd['name'])
         except ExecuteError:
diff --git a/python/qemu/qmp/qmp_tui.py b/python/qemu/qmp/qmp_tui.py
index 12bdc17c99e..0cf91e83670 100644
--- a/python/qemu/qmp/qmp_tui.py
+++ b/python/qemu/qmp/qmp_tui.py
@@ -22,14 +22,7 @@
 from logging import Handler, LogRecord
 import signal
 import sys
-from typing import (
-    List,
-    Optional,
-    Tuple,
-    Type,
-    Union,
-    cast,
-)
+from typing import Optional, Union, cast
 
 
 try:
@@ -120,7 +113,7 @@ def format_json(msg: str) -> str:
 
 
 def has_handler_type(logger: logging.Logger,
-                     handler_type: Type[Handler]) -> bool:
+                     handler_type: type[Handler]) -> bool:
     """
     The Logger class has no interface to check if a certain type of handler is
     installed or not. So we provide an interface to do so.
@@ -151,7 +144,7 @@ class App(QMPClient):
     :param retry_delay:
         The delay(sec) before each retry
     """
-    def __init__(self, address: Union[str, Tuple[str, int]], num_retries: int,
+    def __init__(self, address: Union[str, tuple[str, int]], num_retries: int,
                  retry_delay: Optional[int]) -> None:
         urwid.register_signal(type(self), UPDATE_MSG)
         self.window = Window(self)
@@ -448,11 +441,11 @@ class Editor(urwid_readline.ReadlineEdit):
     def __init__(self, parent: App) -> None:
         super().__init__(caption='> ', multiline=True)
         self.parent = parent
-        self.history: List[str] = []
+        self.history: list[str] = []
         self.last_index: int = -1
         self.show_history: bool = False
 
-    def keypress(self, size: Tuple[int, int], key: str) -> Optional[str]:
+    def keypress(self, size: tuple[int, int], key: str) -> Optional[str]:
         """
         Handles the keypress on this widget.
 
@@ -530,7 +523,7 @@ def __init__(self, parent: App) -> None:
         super().__init__(self.history)
 
     def add_to_history(self,
-                       history: Union[str, List[Tuple[str, str]]]) -> None:
+                       history: Union[str, list[tuple[str, str]]]) -> None:
         """
         Appends a message to the list and set the focus to the last appended
         message.
@@ -541,7 +534,7 @@ def add_to_history(self,
         self.history.append(urwid.Text(history))
         self.history.set_focus(len(self.history) - 1)
 
-    def mouse_event(self, size: Tuple[int, int], _event: str, button: float,
+    def mouse_event(self, size: tuple[int, int], _event: str, button: float,
                     _x: int, _y: int, focus: bool) -> None:
         # Unfortunately there are no urwid constants that represent the mouse
         # events.
diff --git a/python/qemu/utils/accel.py b/python/qemu/utils/accel.py
index 386ff640ca8..eddb01628a3 100644
--- a/python/qemu/utils/accel.py
+++ b/python/qemu/utils/accel.py
@@ -17,7 +17,7 @@
 import logging
 import os
 import subprocess
-from typing import List, Optional
+from typing import Optional
 
 
 LOG = logging.getLogger(__name__)
@@ -31,7 +31,7 @@
 }
 
 
-def list_accel(qemu_bin: str) -> List[str]:
+def list_accel(qemu_bin: str) -> list[str]:
     """
     List accelerators enabled in the QEMU binary.
 
diff --git a/python/qemu/utils/qemu_ga_client.py 
b/python/qemu/utils/qemu_ga_client.py
index cf0fcf9a8bb..48b94e5d83b 100644
--- a/python/qemu/utils/qemu_ga_client.py
+++ b/python/qemu/utils/qemu_ga_client.py
@@ -45,7 +45,6 @@
 from typing import (
     Any,
     Callable,
-    Dict,
     Optional,
     Sequence,
 )
@@ -159,7 +158,7 @@ def fsfreeze(self, cmd: str) -> object:
         # Can be int (freeze, thaw) or GuestFsfreezeStatus (status)
         return getattr(self.qga, 'fsfreeze' + '_' + cmd)()
 
-    def fstrim(self, minimum: int) -> Dict[str, object]:
+    def fstrim(self, minimum: int) -> dict[str, object]:
         # returns GuestFilesystemTrimResponse
         ret = getattr(self.qga, 'fstrim')(minimum=minimum)
         assert isinstance(ret, dict)
diff --git a/python/qemu/utils/qom_common.py b/python/qemu/utils/qom_common.py
index dd2c8b1908c..245c5cedfa3 100644
--- a/python/qemu/utils/qom_common.py
+++ b/python/qemu/utils/qom_common.py
@@ -18,14 +18,7 @@
 import argparse
 import os
 import sys
-from typing import (
-    Any,
-    Dict,
-    List,
-    Optional,
-    Type,
-    TypeVar,
-)
+from typing import Any, Optional, TypeVar
 
 from qemu.qmp import QMPError
 from qemu.qmp.legacy import QEMUMonitorProtocol
@@ -44,7 +37,7 @@ def __init__(self, name: str, type_: str,
         self.default_value = default_value
 
     @classmethod
-    def make(cls, value: Dict[str, Any]) -> 'ObjectPropertyInfo':
+    def make(cls, value: dict[str, Any]) -> 'ObjectPropertyInfo':
         """
         Build an ObjectPropertyInfo from a Dict with an unknown shape.
         """
@@ -136,18 +129,18 @@ def run(self) -> int:
         """
         raise NotImplementedError
 
-    def qom_list(self, path: str) -> List[ObjectPropertyInfo]:
+    def qom_list(self, path: str) -> list[ObjectPropertyInfo]:
         """
         :return: a strongly typed list from the 'qom-list' command.
         """
         rsp = self.qmp.cmd('qom-list', path=path)
-        # qom-list returns List[ObjectPropertyInfo]
+        # qom-list returns list[ObjectPropertyInfo]
         assert isinstance(rsp, list)
         return [ObjectPropertyInfo.make(x) for x in rsp]
 
     @classmethod
     def command_runner(
-            cls: Type[CommandT],
+            cls: type[CommandT],
             args: argparse.Namespace
     ) -> int:
         """
diff --git a/python/qemu/utils/qom_fuse.py b/python/qemu/utils/qom_fuse.py
index cf7e344bd53..36819b7d623 100644
--- a/python/qemu/utils/qom_fuse.py
+++ b/python/qemu/utils/qom_fuse.py
@@ -38,7 +38,6 @@
 import sys
 from typing import (
     IO,
-    Dict,
     Iterator,
     Mapping,
     Optional,
@@ -79,7 +78,7 @@ def configure_parser(cls, parser: argparse.ArgumentParser) -> 
None:
     def __init__(self, args: argparse.Namespace):
         super().__init__(args)
         self.mount = args.mount
-        self.ino_map: Dict[str, int] = {}
+        self.ino_map: dict[str, int] = {}
         self.ino_count = 1
 
     def run(self) -> int:
diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index 8ac5b0b2a05..d026ac17ff3 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -78,11 +78,9 @@
 from types import SimpleNamespace
 from typing import (
     Any,
-    Dict,
     Iterator,
     Optional,
     Sequence,
-    Tuple,
     Union,
 )
 import venv
@@ -510,7 +508,7 @@ def diagnose(
     online: bool,
     wheels_dir: Optional[Union[str, Path]],
     prog: Optional[str],
-) -> Tuple[str, bool]:
+) -> tuple[str, bool]:
     """
     Offer a summary to the user as to why a package failed to be installed.
 
@@ -623,7 +621,7 @@ def pip_install(
     )
 
 
-def _make_version_constraint(info: Dict[str, str], install: bool) -> str:
+def _make_version_constraint(info: dict[str, str], install: bool) -> str:
     """
     Construct the version constraint part of a PEP 508 dependency
     specification (for example '>=0.61.5') from the accepted and
@@ -648,10 +646,10 @@ def _make_version_constraint(info: Dict[str, str], 
install: bool) -> str:
 
 
 def _do_ensure(
-    group: Dict[str, Dict[str, str]],
+    group: dict[str, dict[str, str]],
     online: bool = False,
     wheels_dir: Optional[Union[str, Path]] = None,
-) -> Optional[Tuple[str, bool]]:
+) -> Optional[tuple[str, bool]]:
     """
     Use pip to ensure we have the packages specified in @group.
 
@@ -716,7 +714,7 @@ def _do_ensure(
     return None
 
 
-def _parse_groups(file: str) -> Dict[str, Dict[str, Any]]:
+def _parse_groups(file: str) -> dict[str, dict[str, Any]]:
     if not HAVE_TOMLLIB:
         if sys.version_info < (3, 11):
             raise Ouch("found no usable tomli, please install it")
@@ -756,7 +754,7 @@ def ensure_group(
 
     parsed_deps = _parse_groups(file)
 
-    to_install: Dict[str, Dict[str, str]] = {}
+    to_install: dict[str, dict[str, str]] = {}
     for group in groups:
         try:
             to_install.update(parsed_deps[group])
diff --git a/scripts/codeconverter/codeconverter/patching.py 
b/scripts/codeconverter/codeconverter/patching.py
index 9e92505d394..2646811b037 100644
--- a/scripts/codeconverter/codeconverter/patching.py
+++ b/scripts/codeconverter/codeconverter/patching.py
@@ -5,7 +5,7 @@
 #
 # This work is licensed under the terms of the GNU GPL, version 2.  See
 # the COPYING file in the top-level directory.
-from typing import IO, Match, NamedTuple, Optional, Literal, Iterable, Type, 
Dict, List, Any, TypeVar, NewType, Tuple, Union
+from typing import IO, Match, NamedTuple, Optional, Literal, Iterable, Any, 
TypeVar, NewType, Union
 from pathlib import Path
 from itertools import chain
 from tempfile import NamedTemporaryFile
@@ -181,14 +181,14 @@ def domatch(klass, content: str, pos=0, endpos=-1) -> 
Optional[Match]:
             content = content[:endpos]
         return klass.compiled_re().match(content, pos)
 
-    def group_finditer(self, klass: Type['FileMatch'], group: Union[str, int]) 
-> Iterable['FileMatch']:
+    def group_finditer(self, klass: type['FileMatch'], group: Union[str, int]) 
-> Iterable['FileMatch']:
         assert self.file.original_content
         return (klass(self.file, m)
                 for m in klass.finditer(self.file.original_content,
                                         self.match.start(group),
                                         self.match.end(group)))
 
-    def try_group_match(self, klass: Type['FileMatch'], group: Union[str, 
int]) -> Optional['FileMatch']:
+    def try_group_match(self, klass: type['FileMatch'], group: Union[str, 
int]) -> Optional['FileMatch']:
         assert self.file.original_content
         m = klass.domatch(self.file.original_content,
                           self.match.start(group),
@@ -213,12 +213,12 @@ class FullMatch(FileMatch):
     """
     regexp = r'(?s).*' # (?s) is re.DOTALL
 
-def all_subclasses(c: Type[FileMatch]) -> Iterable[Type[FileMatch]]:
+def all_subclasses(c: type[FileMatch]) -> Iterable[type[FileMatch]]:
     for sc in c.__subclasses__():
         yield sc
         yield from all_subclasses(sc)
 
-def match_class_dict() -> Dict[str, Type[FileMatch]]:
+def match_class_dict() -> dict[str, type[FileMatch]]:
     d = dict((t.__name__, t) for t in all_subclasses(FileMatch))
     return d
 
@@ -239,7 +239,7 @@ def apply_patches(s: str, patches: Iterable[Patch]) -> str:
     """
     r = StringIO()
     last = 0
-    def patch_sort_key(item: Tuple[int, Patch]) -> Tuple[int, int, int]:
+    def patch_sort_key(item: tuple[int, Patch]) -> tuple[int, int, int]:
         """Patches are sorted by byte position,
         patches at the same byte position are applied in the order
         they were generated.
@@ -263,22 +263,22 @@ def patch_sort_key(item: Tuple[int, Patch]) -> Tuple[int, 
int, int]:
 
 class RegexpScanner:
     def __init__(self) -> None:
-        self.match_index: Dict[Type[Any], List[FileMatch]] = {}
-        self.match_name_index: Dict[Tuple[Type[Any], str, str], 
Optional[FileMatch]] = {}
+        self.match_index: dict[type[Any], list[FileMatch]] = {}
+        self.match_name_index: dict[tuple[type[Any], str, str], 
Optional[FileMatch]] = {}
 
-    def _matches_of_type(self, klass: Type[Any]) -> Iterable[FileMatch]:
+    def _matches_of_type(self, klass: type[Any]) -> Iterable[FileMatch]:
         raise NotImplementedError()
 
-    def matches_of_type(self, t: Type[T]) -> List[T]:
+    def matches_of_type(self, t: type[T]) -> list[T]:
         if t not in self.match_index:
             self.match_index[t] = list(self._matches_of_type(t))
         return self.match_index[t] # type: ignore
 
-    def find_matches(self, t: Type[T], name: str, group: str='name') -> 
List[T]:
+    def find_matches(self, t: type[T], name: str, group: str='name') -> 
list[T]:
         indexkey = (t, name, group)
         if indexkey in self.match_name_index:
             return self.match_name_index[indexkey] # type: ignore
-        r: List[T] = []
+        r: list[T] = []
         for m in self.matches_of_type(t):
             assert isinstance(m, FileMatch)
             if m.getgroup(group) == name:
@@ -286,7 +286,7 @@ def find_matches(self, t: Type[T], name: str, group: 
str='name') -> List[T]:
         self.match_name_index[indexkey] = r # type: ignore
         return r
 
-    def find_match(self, t: Type[T], name: str, group: str='name') -> 
Optional[T]:
+    def find_match(self, t: type[T], name: str, group: str='name') -> 
Optional[T]:
         l = self.find_matches(t, name, group)
         if not l:
             return None
@@ -307,7 +307,7 @@ def __init__(self, files: 'FileList', filename: 
os.PathLike, force:bool=False) -
         super().__init__()
         self.allfiles = files
         self.filename = Path(filename)
-        self.patches: List[Patch] = []
+        self.patches: list[Patch] = []
         self.force = force
 
     def __repr__(self) -> str:
@@ -321,7 +321,7 @@ def line_col(self, start: int) -> LineAndColumn:
         """Return line and column for a match object inside original_content"""
         return line_col(self.original_content, start)
 
-    def _matches_of_type(self, klass: Type[Any]) -> List[FileMatch]:
+    def _matches_of_type(self, klass: type[Any]) -> list[FileMatch]:
         """Build FileMatch objects for each match of regexp"""
         if not hasattr(klass, 'regexp') or klass.regexp is None:
             return []
@@ -333,7 +333,7 @@ def _matches_of_type(self, klass: Type[Any]) -> 
List[FileMatch]:
             klass.__name__,' '.join(names(matches)))
         return matches
 
-    def find_match(self, t: Type[T], name: str, group: str='name') -> 
Optional[T]:
+    def find_match(self, t: type[T], name: str, group: str='name') -> 
Optional[T]:
         for m in self.matches_of_type(t):
             assert isinstance(m, FileMatch)
             if m.getgroup(group) == name:
@@ -358,7 +358,7 @@ def all_matches(self) -> Iterable[FileMatch]:
         return (m for l in lists
                   for m in l)
 
-    def gen_patches(self, matches: List[FileMatch]) -> None:
+    def gen_patches(self, matches: list[FileMatch]) -> None:
         for m in matches:
             DBG("Generating patches for %r", m)
             for i,p in enumerate(m.gen_patches()):
@@ -367,7 +367,7 @@ def gen_patches(self, matches: List[FileMatch]) -> None:
                     self.line_col(p.start), self.line_col(p.end), 
p.replacement)
                 self.patches.append(p)
 
-    def scan_for_matches(self, class_names: Optional[List[str]]=None) -> 
Iterable[FileMatch]:
+    def scan_for_matches(self, class_names: Optional[list[str]]=None) -> 
Iterable[FileMatch]:
         DBG("class names: %r", class_names)
         class_dict = match_class_dict()
         if class_names is None:
@@ -413,7 +413,7 @@ def ref(self):
 class FileList(RegexpScanner):
     def __init__(self):
         super().__init__()
-        self.files: List[FileInfo] = []
+        self.files: list[FileInfo] = []
 
     def extend(self, *args, **kwargs):
         self.files.extend(*args, **kwargs)
@@ -421,7 +421,7 @@ def extend(self, *args, **kwargs):
     def __iter__(self):
         return iter(self.files)
 
-    def _matches_of_type(self, klass: Type[Any]) -> Iterable[FileMatch]:
+    def _matches_of_type(self, klass: type[Any]) -> Iterable[FileMatch]:
         return chain(*(f._matches_of_type(klass) for f in self.files))
 
     def find_file(self, name: str) -> Optional[FileInfo]:
@@ -432,7 +432,7 @@ def find_file(self, name: str) -> Optional[FileInfo]:
         else:
             return None
 
-    def one_pass(self, class_names: List[str]) -> int:
+    def one_pass(self, class_names: list[str]) -> int:
         total_patches = 0
         for f in self.files:
             INFO("Scanning file %s", f.filename)
@@ -448,7 +448,7 @@ def one_pass(self, class_names: List[str]) -> int:
                     logger.exception("%s: failed to patch file", f.filename)
         return total_patches
 
-    def patch_content(self, max_passes, class_names: List[str]) -> None:
+    def patch_content(self, max_passes, class_names: list[str]) -> None:
         """Multi-pass content patching loop
 
         We run multiple passes because there are rules that will
diff --git a/scripts/codeconverter/codeconverter/qom_macros.py 
b/scripts/codeconverter/codeconverter/qom_macros.py
index 2b0c8224a18..9942c6274c8 100644
--- a/scripts/codeconverter/codeconverter/qom_macros.py
+++ b/scripts/codeconverter/codeconverter/qom_macros.py
@@ -68,7 +68,7 @@ def __str__(self) -> str:
         s = ', '.join('%s=%s' % (f,v) for f,v in values if v is not None)
         return f'{s}'
 
-    def check_consistency(self) -> List[str]:
+    def check_consistency(self) -> list[str]:
         """Check if identifiers are consistent with each other,
         return list of problems (or empty list if everything seems consistent)
         """
@@ -235,7 +235,7 @@ def find_typedef(f: FileInfo, name: Optional[str]) -> 
Optional[TypedefMatch]:
         NAMED('qom_typename', RE_IDENTIFIER), r'\s*\)\n',
         n='?', name='check_args'))
 
-EXPECTED_CHECKER_SUFFIXES: List[Tuple[CheckerMacroName, str]] = [
+EXPECTED_CHECKER_SUFFIXES: list[tuple[CheckerMacroName, str]] = [
     ('OBJECT_GET_CLASS', '_GET_CLASS'),
     ('OBJECT_CLASS_CHECK', '_CLASS'),
 ]
@@ -267,7 +267,7 @@ def sanity_check(self) -> None:
         if self.typedefname and self.find_typedef() is None:
             self.warn("typedef used by %s not found", self.name)
 
-    def find_matching_macros(self) -> List['TypeCheckMacro']:
+    def find_matching_macros(self) -> list['TypeCheckMacro']:
         """Find other check macros that generate the same macro names
 
         The returned list will always be sorted.
@@ -280,7 +280,7 @@ def find_matching_macros(self) -> List['TypeCheckMacro']:
                    and (my_ids.uppercase == m.type_identifiers.uppercase
                         or my_ids.typename == m.type_identifiers.typename)]
 
-    def merge_ids(self, matches: List['TypeCheckMacro']) -> 
Optional[TypeIdentifiers]:
+    def merge_ids(self, matches: list['TypeCheckMacro']) -> 
Optional[TypeIdentifiers]:
         """Try to merge info about type identifiers from all matches in a 
list"""
         if not matches:
             return None
@@ -580,10 +580,10 @@ def gen_patches(self) -> Iterable[Patch]:
             return
 
         # group checkers by uppercase name:
-        decl_types: List[Type[TypeDeclaration]] = [DeclareInstanceChecker, 
DeclareInstanceType,
+        decl_types: list[type[TypeDeclaration]] = [DeclareInstanceChecker, 
DeclareInstanceType,
                                                    DeclareClassCheckers, 
DeclareClassType,
                                                    DeclareObjCheckers]
-        checker_dict: Dict[str, List[TypeDeclaration]] = {}
+        checker_dict: dict[str, list[TypeDeclaration]] = {}
         for t in decl_types:
             for m in self.file.matches_of_type(t):
                 checker_dict.setdefault(m.group('uppercase'), []).append(m)
@@ -602,9 +602,9 @@ def gen_patches(self) -> Iterable[Patch]:
             field_dict = dict((f, v.pop() if v else None) for f,v in 
fvalues.items())
             yield from self.gen_patches_for_type(uppercase, checkers, 
field_dict)
 
-    def find_conflicts(self, uppercase: str, checkers: List[TypeDeclaration]) 
-> bool:
+    def find_conflicts(self, uppercase: str, checkers: list[TypeDeclaration]) 
-> bool:
         """Look for conflicting declarations that would make it unsafe to add 
new ones"""
-        conflicting: List[FileMatch] = []
+        conflicting: list[FileMatch] = []
         # conflicts in the same file:
         conflicting.extend(chain(self.file.find_matches(DefineDirective, 
uppercase),
                                  
self.file.find_matches(DeclareInterfaceChecker, uppercase, 'uppercase'),
@@ -633,8 +633,8 @@ def find_conflicts(self, uppercase: str, checkers: 
List[TypeDeclaration]) -> boo
         return False
 
     def gen_patches_for_type(self, uppercase: str,
-                             checkers: List[TypeDeclaration],
-                             fields: Dict[str, Optional[str]]) -> 
Iterable[Patch]:
+                             checkers: list[TypeDeclaration],
+                             fields: dict[str, Optional[str]]) -> 
Iterable[Patch]:
         """Should be reimplemented by subclasses"""
         return
         yield
@@ -643,8 +643,8 @@ class DeclareVoidTypes(TypeDeclarationFixup):
     """Add DECLARE_*_TYPE(..., void) when there's no declared type"""
     regexp = RE_FILE_BEGIN
     def gen_patches_for_type(self, uppercase: str,
-                             checkers: List[TypeDeclaration],
-                             fields: Dict[str, Optional[str]]) -> 
Iterable[Patch]:
+                             checkers: list[TypeDeclaration],
+                             fields: dict[str, Optional[str]]) -> 
Iterable[Patch]:
         if self.find_conflicts(uppercase, checkers):
             return
 
@@ -671,8 +671,8 @@ def gen_patches_for_type(self, uppercase: str,
 class AddDeclareTypeName(TypeDeclarationFixup):
     """Add DECLARE_TYPE_NAME declarations if necessary"""
     def gen_patches_for_type(self, uppercase: str,
-                             checkers: List[TypeDeclaration],
-                             fields: Dict[str, Optional[str]]) -> 
Iterable[Patch]:
+                             checkers: list[TypeDeclaration],
+                             fields: dict[str, Optional[str]]) -> 
Iterable[Patch]:
         typename = fields.get('typename')
         if typename is None:
             self.warn("typename unavailable")
@@ -753,7 +753,7 @@ def find_typename_uppercase(files: FileList, typename: str) 
-> Optional[str]:
 
 def find_type_checkers(files:FileList, name:str, group:str='uppercase') -> 
Iterable[TypeCheckerDeclaration]:
     """Find usage of DECLARE*CHECKER macro"""
-    c: Type[TypeCheckerDeclaration]
+    c: type[TypeCheckerDeclaration]
     for c in (DeclareInstanceChecker, DeclareClassCheckers, 
DeclareObjCheckers, ObjectDeclareType, ObjectDeclareSimpleType):
         yield from files.find_matches(c, name=name, group=group)
 
@@ -774,8 +774,8 @@ class InitialIncludes(FileMatch):
                  n='*', name='includes'))
 
 class SymbolUserList(NamedTuple):
-    definitions: List[FileMatch]
-    users: List[FileMatch]
+    definitions: list[FileMatch]
+    users: list[FileMatch]
 
 class MoveSymbols(FileMatch):
     """Handle missing symbols
@@ -789,7 +789,7 @@ def gen_patches(self) -> Iterator[Patch]:
             self.debug("skipping object.h")
             return
 
-        index: Dict[RequiredIdentifier, SymbolUserList] = {}
+        index: dict[RequiredIdentifier, SymbolUserList] = {}
         definition_classes = [SimpleTypedefMatch, FullStructTypedefMatch, 
ConstantDefine, Include]
         user_classes = [TypeCheckMacro, DeclareObjCheckers, 
DeclareInstanceChecker, DeclareClassCheckers, InterfaceCheckMacro]
 
diff --git a/scripts/codeconverter/codeconverter/qom_type_info.py 
b/scripts/codeconverter/codeconverter/qom_type_info.py
index 22a25560760..efcf791f3cf 100644
--- a/scripts/codeconverter/codeconverter/qom_type_info.py
+++ b/scripts/codeconverter/codeconverter/qom_type_info.py
@@ -25,7 +25,7 @@
 RE_TYPEINFO_START = S(r'^[ \t]*', M(r'(static|const)\s+', name='modifiers'), 
r'TypeInfo\s+',
                       NAMED('name', RE_IDENTIFIER), r'\s*=\s*{[ \t]*\n')
 
-ParsedArray = List[str]
+ParsedArray = list[str]
 ParsedInitializerValue = Union[str, ParsedArray]
 class InitializerValue(NamedTuple):
     raw: str
@@ -59,7 +59,7 @@ def parsed(self) -> ParsedInitializerValue:
             return array.parsed()
         return parsed
 
-TypeInfoInitializers = Dict[str, FieldInitializer]
+TypeInfoInitializers = dict[str, FieldInitializer]
 
 class TypeDefinition(FileMatch):
     """
@@ -343,7 +343,7 @@ def gen_patches(self) -> Iterable[Patch]:
 
         ok = True
 
-        #checkers: List[TypeCheckerDeclaration] = 
list(find_type_checkers(self.allfiles, uppercase))
+        #checkers: list[TypeCheckerDeclaration] = 
list(find_type_checkers(self.allfiles, uppercase))
         #for c in checkers:
         #    c.info("instance type checker declaration (%s) is here", 
c.group('uppercase'))
         #if not checkers:
@@ -448,7 +448,7 @@ class ObjectDefineType(TypeDefinition):
                r'\s*\);?\n?')
 
 def find_type_definitions(files: FileList, uppercase: str) -> 
Iterable[TypeDefinition]:
-    types: List[Type[TypeDefinition]] = [TypeInfoVar, ObjectDefineType, 
ObjectDefineTypeExtended]
+    types: list[type[TypeDefinition]] = [TypeInfoVar, ObjectDefineType, 
ObjectDefineTypeExtended]
     for t in types:
         for m in files.matches_of_type(t):
             m.debug("uppercase: %s", m.uppercase)
@@ -459,8 +459,8 @@ def find_type_definitions(files: FileList, uppercase: str) 
-> Iterable[TypeDefin
 class AddDeclareVoidClassType(TypeDeclarationFixup):
     """Will add DECLARE_CLASS_TYPE(..., void) if possible"""
     def gen_patches_for_type(self, uppercase: str,
-                             checkers: List[TypeDeclaration],
-                             fields: Dict[str, Optional[str]]) -> 
Iterable[Patch]:
+                             checkers: list[TypeDeclaration],
+                             fields: dict[str, Optional[str]]) -> 
Iterable[Patch]:
         defs = list(find_type_definitions(self.allfiles, uppercase))
         if len(defs) > 1:
             self.warn("multiple definitions for %s", uppercase)
@@ -554,7 +554,7 @@ def gen_patches(self) -> Iterable[Patch]:
             if not self.file.force:
                 return
 
-        decl_types: List[Type[TypeDeclaration]] = [DeclareClassCheckers, 
DeclareObjCheckers]
+        decl_types: list[type[TypeDeclaration]] = [DeclareClassCheckers, 
DeclareObjCheckers]
         class_decls = [m for t in decl_types
                        for m in self.allfiles.find_matches(t, uppercase, 
'uppercase')]
 
@@ -634,7 +634,7 @@ def gen_patches(self) -> Iterable[Patch]:
             if not self.file.force:
                 return
 
-        decl_types: List[Type[TypeDeclaration]] = [DeclareClassCheckers, 
DeclareObjCheckers]
+        decl_types: list[type[TypeDeclaration]] = [DeclareClassCheckers, 
DeclareObjCheckers]
         class_decls = [m for t in decl_types
                        for m in self.allfiles.find_matches(t, uppercase, 
'uppercase')]
         if class_decls:
diff --git a/scripts/compare-machine-types.py b/scripts/compare-machine-types.py
index 2af3995eb82..b47ab058645 100755
--- a/scripts/compare-machine-types.py
+++ b/scripts/compare-machine-types.py
@@ -31,7 +31,7 @@
 from argparse import ArgumentParser, RawTextHelpFormatter, Namespace
 import pandas as pd
 from contextlib import ExitStack
-from typing import Optional, List, Dict, Generator, Tuple, Union, Any, Set
+from typing import Optional, Generator, Union, Any
 
 try:
     qemu_dir = path.abspath(path.dirname(path.dirname(__file__)))
@@ -81,7 +81,7 @@ def is_child_of(self, parent: 'Driver') -> bool:
 
         return False
 
-    def set_implementations(self, implementations: List['Driver']) -> None:
+    def set_implementations(self, implementations: list['Driver']) -> None:
         self.implementations = implementations
 
 
@@ -89,7 +89,7 @@ class QEMUObject(Driver):
     def __init__(self, vm: QEMUMachine, name: str) -> None:
         super().__init__(vm, name, True)
 
-    def set_implementations(self, implementations: List[Driver]) -> None:
+    def set_implementations(self, implementations: list[Driver]) -> None:
         self.implementations = implementations
 
         # each implementation of the abstract driver has to use property getter
@@ -105,7 +105,7 @@ def set_implementations(self, implementations: 
List[Driver]) -> None:
 class QEMUDevice(QEMUObject):
     def __init__(self, vm: QEMUMachine) -> None:
         super().__init__(vm, 'device')
-        self.cached: Dict[str, List[Dict[str, Any]]] = {}
+        self.cached: dict[str, list[dict[str, Any]]] = {}
 
     def get_prop(self, driver: str, prop_name: str) -> str:
         if driver not in self.cached:
@@ -121,7 +121,7 @@ def get_prop(self, driver: str, prop_name: str) -> str:
 class QEMUx86CPU(QEMUObject):
     def __init__(self, vm: QEMUMachine) -> None:
         super().__init__(vm, 'x86_64-cpu')
-        self.cached: Dict[str, Dict[str, Any]] = {}
+        self.cached: dict[str, dict[str, Any]] = {}
 
     def get_prop(self, driver: str, prop_name: str) -> str:
         if not driver.endswith('-x86_64-cpu'):
@@ -141,7 +141,7 @@ def get_prop(self, driver: str, prop_name: str) -> str:
 class QEMUMemoryBackend(QEMUObject):
     def __init__(self, vm: QEMUMachine) -> None:
         super().__init__(vm, 'memory-backend')
-        self.cached: Dict[str, List[Dict[str, Any]]] = {}
+        self.cached: dict[str, list[dict[str, Any]]] = {}
 
     def get_prop(self, driver: str, prop_name: str) -> str:
         if driver not in self.cached:
@@ -172,7 +172,7 @@ class VMPropertyGetter:
     """It implements the relationship between drivers and how to get their
     properties"""
     def __init__(self, vm: QEMUMachine) -> None:
-        self.drivers: Dict[str, Driver] = {}
+        self.drivers: dict[str, Driver] = {}
 
         qom_all_types = vm.cmd('qom-list-types', abstract=True)
         self.drivers = {t['name']: new_driver(vm, t['name'],
@@ -201,7 +201,7 @@ def get_prop(self, driver: str, prop: str) -> str:
 
         return drv.get_prop(driver, prop)
 
-    def get_implementations(self, driver: str) -> List[str]:
+    def get_implementations(self, driver: str) -> list[str]:
         return [impl.name for impl in self.drivers[driver].implementations]
 
 
@@ -211,10 +211,10 @@ class Machine:
     implementations)
     """
     # raw_mt_dict - dict produced by `query-machines`
-    def __init__(self, raw_mt_dict: Dict[str, Any],
+    def __init__(self, raw_mt_dict: dict[str, Any],
                  qemu_drivers: VMPropertyGetter) -> None:
         self.name = raw_mt_dict['name']
-        self.compat_props: Dict[str, Any] = {}
+        self.compat_props: dict[str, Any] = {}
         # properties are applied sequentially and can rewrite values like in
         # QEMU. Also it has to resolve class relationships to apply appropriate
         # values from abstract class to all implementations
@@ -239,7 +239,7 @@ class Configuration():
     """Class contains all necessary components to generate table and is used
     to compare different binaries"""
     def __init__(self, vm: QEMUMachine,
-                 req_mt: List[str], all_mt: bool) -> None:
+                 req_mt: list[str], all_mt: bool) -> None:
         self._vm = vm
         self._binary = vm.binary
         self._qemu_args = args.qemu_args.split(' ')
@@ -247,11 +247,11 @@ def __init__(self, vm: QEMUMachine,
         self._qemu_drivers = VMPropertyGetter(vm)
         self.req_mt = get_req_mt(self._qemu_drivers, vm, req_mt, all_mt)
 
-    def get_implementations(self, driver_name: str) -> List[str]:
+    def get_implementations(self, driver_name: str) -> list[str]:
         return self._qemu_drivers.get_implementations(driver_name)
 
-    def get_table(self, req_props: List[Tuple[str, str]]) -> pd.DataFrame:
-        table: List[pd.DataFrame] = []
+    def get_table(self, req_props: list[tuple[str, str]]) -> pd.DataFrame:
+        table: list[pd.DataFrame] = []
         for mt in self.req_mt:
             name = f'{self._binary}\n{mt.name}'
             column = []
@@ -339,7 +339,7 @@ def parse_args() -> Namespace:
     return parser.parse_args()
 
 
-def mt_comp(mt: Machine) -> Tuple[str, int, int, int]:
+def mt_comp(mt: Machine) -> tuple[str, int, int, int]:
     """Function to compare and sort machine by names.
     It returns socket_name, major version, minor version, revision"""
     # none, microvm, x-remote and etc.
@@ -353,7 +353,7 @@ def mt_comp(mt: Machine) -> Tuple[str, int, int, int]:
 
 
 def get_mt_definitions(qemu_drivers: VMPropertyGetter,
-                       vm: QEMUMachine) -> List[Machine]:
+                       vm: QEMUMachine) -> list[Machine]:
     """Constructs list of machine definitions (primarily compat_props) via
     info from QEMU"""
     raw_mt_defs = vm.cmd('query-machines', compat_props=True)
@@ -366,7 +366,7 @@ def get_mt_definitions(qemu_drivers: VMPropertyGetter,
 
 
 def get_req_mt(qemu_drivers: VMPropertyGetter, vm: QEMUMachine,
-               req_mt: Optional[List[str]], all_mt: bool) -> List[Machine]:
+               req_mt: Optional[list[str]], all_mt: bool) -> list[Machine]:
     """Returns list of requested by user machines"""
     mt_defs = get_mt_definitions(qemu_drivers, vm)
     if all_mt:
@@ -384,12 +384,12 @@ def get_req_mt(qemu_drivers: VMPropertyGetter, vm: 
QEMUMachine,
     return matched_mt
 
 
-def get_affected_props(configs: List[Configuration]) -> Generator[Tuple[str,
+def get_affected_props(configs: list[Configuration]) -> Generator[tuple[str,
                                                                         str],
                                                                   None, None]:
     """Helps to go through all affected in machine definitions drivers
     and properties"""
-    driver_props: Dict[str, Set[Any]] = {}
+    driver_props: dict[str, set[Any]] = {}
     for config in configs:
         for mt in config.req_mt:
             compat_props = mt.compat_props
@@ -437,7 +437,7 @@ def simplify_table(table: pd.DataFrame) -> pd.DataFrame:
 # driver2 | property3 |  value5  |  value6  | ...
 #   ...   |    ...    |   ...    |   ...    | ...
 #
-def fill_prop_table(configs: List[Configuration],
+def fill_prop_table(configs: list[Configuration],
                     is_raw: bool) -> pd.DataFrame:
     req_props = list(get_affected_props(configs))
     if not req_props:
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index 79142273828..cd3a665319a 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -13,12 +13,7 @@
 See the COPYING file in the top-level directory.
 """
 
-from typing import (
-    Dict,
-    List,
-    Optional,
-    Set,
-)
+from typing import Optional
 
 from .common import c_name, mcgen
 from .gen import (
@@ -276,7 +271,7 @@ def gen_marshal(name: str,
 
 
 def gen_register_command(name: str,
-                         features: List[QAPISchemaFeature],
+                         features: list[QAPISchemaFeature],
                          success_response: bool,
                          allow_oob: bool,
                          allow_preconfig: bool,
@@ -308,7 +303,7 @@ def __init__(self, prefix: str, gen_tracing: bool):
             prefix, 'qapi-commands',
             ' * Schema-defined QAPI/QMP commands', None, __doc__,
             gen_tracing=gen_tracing)
-        self._visited_ret_types: Dict[QAPIGenC, Set[QAPISchemaType]] = {}
+        self._visited_ret_types: dict[QAPIGenC, set[QAPISchemaType]] = {}
         self._gen_tracing = gen_tracing
 
     def _begin_user_module(self, name: str) -> None:
@@ -375,7 +370,7 @@ def visit_command(self,
                       name: str,
                       info: Optional[QAPISourceInfo],
                       ifcond: QAPISchemaIfCond,
-                      features: List[QAPISchemaFeature],
+                      features: list[QAPISchemaFeature],
                       arg_type: Optional[QAPISchemaObjectType],
                       ret_type: Optional[QAPISchemaType],
                       gen: bool,
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index d7c8aa3365c..2c55b70a8bd 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -14,7 +14,6 @@
 import re
 from typing import (
     Any,
-    Dict,
     Match,
     Optional,
     Sequence,
@@ -199,11 +198,11 @@ def guardend(name: str) -> str:
                  name=c_fname(name).upper())
 
 
-def gen_ifcond(ifcond: Optional[Union[str, Dict[str, Any]]],
+def gen_ifcond(ifcond: Optional[Union[str, dict[str, Any]]],
                cond_fmt: str, not_fmt: str,
                all_operator: str, any_operator: str) -> str:
 
-    def do_gen(ifcond: Union[str, Dict[str, Any]],
+    def do_gen(ifcond: Union[str, dict[str, Any]],
                need_parens: bool) -> str:
         if isinstance(ifcond, str):
             return cond_fmt % ifcond
@@ -226,11 +225,11 @@ def gen_infix(operator: str, operands: Sequence[Any]) -> 
str:
     return do_gen(ifcond, False)
 
 
-def cgen_ifcond(ifcond: Optional[Union[str, Dict[str, Any]]]) -> str:
+def cgen_ifcond(ifcond: Optional[Union[str, dict[str, Any]]]) -> str:
     return gen_ifcond(ifcond, 'defined(%s)', '!%s', ' && ', ' || ')
 
 
-def docgen_ifcond(ifcond: Optional[Union[str, Dict[str, Any]]]) -> str:
+def docgen_ifcond(ifcond: Optional[Union[str, dict[str, Any]]]) -> str:
     # TODO Doc generated for conditions needs polish
     return gen_ifcond(ifcond, '%s', 'not %s', ' and ', ' or ')
 
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index d179b0ed695..8584d69f33a 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -12,7 +12,7 @@
 See the COPYING file in the top-level directory.
 """
 
-from typing import List, Optional
+from typing import Optional
 
 from .common import c_enum_const, c_name, mcgen
 from .gen import QAPISchemaModularCVisitor, build_params, ifcontext
@@ -80,7 +80,7 @@ def gen_param_var(typ: QAPISchemaObjectType) -> str:
 
 def gen_event_send(name: str,
                    arg_type: Optional[QAPISchemaObjectType],
-                   features: List[QAPISchemaFeature],
+                   features: list[QAPISchemaFeature],
                    boxed: bool,
                    event_enum_name: str,
                    event_emit: str) -> str:
@@ -180,7 +180,7 @@ def __init__(self, prefix: str):
             prefix, 'qapi-events',
             ' * Schema-defined QAPI/QMP events', None, __doc__)
         self._event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
-        self._event_enum_members: List[QAPISchemaEnumMember] = []
+        self._event_enum_members: list[QAPISchemaEnumMember] = []
         self._event_emit_name = c_name(prefix + 'qapi_event_emit')
 
     def _begin_user_module(self, name: str) -> None:
@@ -230,7 +230,7 @@ def visit_event(self,
                     name: str,
                     info: Optional[QAPISourceInfo],
                     ifcond: QAPISchemaIfCond,
-                    features: List[QAPISchemaFeature],
+                    features: list[QAPISchemaFeature],
                     arg_type: Optional[QAPISchemaObjectType],
                     boxed: bool) -> None:
         with ifcontext(ifcond, self._genh, self._genc):
diff --git a/scripts/qapi/expr.py b/scripts/qapi/expr.py
index cae0a083591..144e3dfaa32 100644
--- a/scripts/qapi/expr.py
+++ b/scripts/qapi/expr.py
@@ -33,9 +33,7 @@
 
 import re
 from typing import (
-    Dict,
     Iterable,
-    List,
     Optional,
     Union,
     cast,
@@ -183,11 +181,11 @@ def check_defn_name_str(name: str, info: QAPISourceInfo, 
meta: str) -> None:
                 info, "%s name should not end in 'List'" % meta)
 
 
-def check_keys(value: Dict[str, object],
+def check_keys(value: dict[str, object],
                info: QAPISourceInfo,
                source: str,
-               required: List[str],
-               optional: List[str]) -> None:
+               required: list[str],
+               optional: list[str]) -> None:
     """
     Ensure that a dict has a specific set of keys.
 
@@ -247,7 +245,7 @@ def check_flags(expr: QAPIExpression) -> None:
             expr.info, "flags 'allow-oob' and 'coroutine' are incompatible")
 
 
-def check_if(expr: Dict[str, object],
+def check_if(expr: dict[str, object],
              info: QAPISourceInfo, source: str) -> None:
     """
     Validate the ``if`` member of an object.
@@ -319,8 +317,8 @@ def normalize_members(members: object) -> None:
     ``{'type': value}``.
 
     :forms:
-      :sugared: ``Dict[str, Union[str, TypeRef]]``
-      :canonical: ``Dict[str, TypeRef]``
+      :sugared: ``dict[str, Union[str, TypeRef]]``
+      :canonical: ``dict[str, TypeRef]``
 
     :param members: The members value to normalize.
 
@@ -416,8 +414,8 @@ def check_features(features: Optional[object],
     Any ``str`` element will be normalized to ``{'name': element}``.
 
     :forms:
-      :sugared: ``List[Union[str, Feature]]``
-      :canonical: ``List[Feature]``
+      :sugared: ``list[Union[str, Feature]]``
+      :canonical: ``list[Feature]``
 
     :param features: The features member value to validate.
     :param info: QAPI schema source file information.
@@ -592,7 +590,7 @@ def check_event(expr: QAPIExpression) -> None:
         check_type_name_or_implicit(args, expr.info, "'data'", None)
 
 
-def check_exprs(exprs: List[QAPIExpression]) -> List[QAPIExpression]:
+def check_exprs(exprs: list[QAPIExpression]) -> list[QAPIExpression]:
     """
     Validate and normalize a list of parsed QAPI schema expressions.
 
diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
index d3c56d45c89..53b267228e5 100644
--- a/scripts/qapi/gen.py
+++ b/scripts/qapi/gen.py
@@ -15,13 +15,7 @@
 import os
 import re
 import sys
-from typing import (
-    Dict,
-    Iterator,
-    Optional,
-    Sequence,
-    Tuple,
-)
+from typing import Iterator, Optional, Sequence
 
 from .common import (
     c_enum_const,
@@ -136,7 +130,7 @@ def build_params(arg_type: Optional[QAPISchemaObjectType],
 class QAPIGenCCode(QAPIGen):
     def __init__(self, fname: str):
         super().__init__(fname)
-        self._start_if: Optional[Tuple[QAPISchemaIfCond, str, str]] = None
+        self._start_if: Optional[tuple[QAPISchemaIfCond, str, str]] = None
 
     def start_if(self, ifcond: QAPISchemaIfCond) -> None:
         assert self._start_if is None
@@ -264,7 +258,7 @@ def __init__(self,
         self._builtin_blurb = builtin_blurb
         self._pydoc = pydoc
         self._current_module: Optional[str] = None
-        self._module: Dict[str, Tuple[QAPIGenC, QAPIGenH,
+        self._module: dict[str, tuple[QAPIGenC, QAPIGenH,
                                       Optional[QAPIGenTrace]]] = {}
         self._main_module: Optional[str] = None
         self._gen_tracing = gen_tracing
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 89ee5d5f176..037ed35d3f4 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -14,9 +14,7 @@
 from dataclasses import dataclass
 from typing import (
     Any,
-    Dict,
     Generic,
-    List,
     Optional,
     Sequence,
     TypeVar,
@@ -52,7 +50,7 @@
 # Un-annotated values may be:
 #     Scalar: str, bool, None.
 #     Non-scalar: List, Dict
-# _value = Union[str, bool, None, Dict[str, JSONValue], List[JSONValue]]
+# _value = Union[str, bool, None, dict[str, JSONValue], list[JSONValue]]
 #
 # With optional annotations, the type of all values is:
 # JSONValue = Union[_Value, Annotated[_Value]]
@@ -61,7 +59,7 @@
 # mark the imprecision in the type model where we'd otherwise use JSONValue.
 _Stub = Any
 _Scalar = Union[str, bool, None]
-_NonScalar = Union[Dict[str, _Stub], List[_Stub]]
+_NonScalar = Union[dict[str, _Stub], list[_Stub]]
 _Value = Union[_Scalar, _NonScalar]
 JSONValue = Union[_Value, 'Annotated[_Value]']
 
@@ -69,12 +67,12 @@
 # lack precise types for them here. Python 3.6 does not offer
 # TypedDict constructs, so they are broadly typed here as simple
 # Python Dicts.
-SchemaInfo = Dict[str, object]
-SchemaInfoEnumMember = Dict[str, object]
-SchemaInfoObject = Dict[str, object]
-SchemaInfoObjectVariant = Dict[str, object]
-SchemaInfoObjectMember = Dict[str, object]
-SchemaInfoCommand = Dict[str, object]
+SchemaInfo = dict[str, object]
+SchemaInfoEnumMember = dict[str, object]
+SchemaInfoObject = dict[str, object]
+SchemaInfoObjectVariant = dict[str, object]
+SchemaInfoObjectMember = dict[str, object]
+SchemaInfoCommand = dict[str, object]
 
 
 _ValueT = TypeVar('_ValueT', bound=_Value)
@@ -175,9 +173,9 @@ def __init__(self, prefix: str, unmask: bool):
             ' * QAPI/QMP schema introspection', __doc__)
         self._unmask = unmask
         self._schema: Optional[QAPISchema] = None
-        self._trees: List[Annotated[SchemaInfo]] = []
-        self._used_types: List[QAPISchemaType] = []
-        self._name_map: Dict[str, str] = {}
+        self._trees: list[Annotated[SchemaInfo]] = []
+        self._used_types: list[QAPISchemaType] = []
+        self._name_map: dict[str, str] = {}
         self._genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "%(prefix)sqapi-introspect.h"
@@ -248,10 +246,10 @@ def _use_type(self, typ: QAPISchemaType) -> str:
 
     @staticmethod
     def _gen_features(features: Sequence[QAPISchemaFeature]
-                      ) -> List[Annotated[str]]:
+                      ) -> list[Annotated[str]]:
         return [Annotated(f.name, f.ifcond) for f in features]
 
-    def _gen_tree(self, name: str, mtype: str, obj: Dict[str, object],
+    def _gen_tree(self, name: str, mtype: str, obj: dict[str, object],
                   ifcond: QAPISchemaIfCond = QAPISchemaIfCond(),
                   features: Sequence[QAPISchemaFeature] = ()) -> None:
         """
@@ -313,8 +311,8 @@ def visit_builtin_type(self, name: str, info: 
Optional[QAPISourceInfo],
 
     def visit_enum_type(self, name: str, info: Optional[QAPISourceInfo],
                         ifcond: QAPISchemaIfCond,
-                        features: List[QAPISchemaFeature],
-                        members: List[QAPISchemaEnumMember],
+                        features: list[QAPISchemaFeature],
+                        members: list[QAPISchemaEnumMember],
                         prefix: Optional[str]) -> None:
         self._gen_tree(
             name, 'enum',
@@ -332,8 +330,8 @@ def visit_array_type(self, name: str, info: 
Optional[QAPISourceInfo],
 
     def visit_object_type_flat(self, name: str, info: Optional[QAPISourceInfo],
                                ifcond: QAPISchemaIfCond,
-                               features: List[QAPISchemaFeature],
-                               members: List[QAPISchemaObjectTypeMember],
+                               features: list[QAPISchemaFeature],
+                               members: list[QAPISchemaObjectTypeMember],
                                branches: Optional[QAPISchemaBranches]) -> None:
         obj: SchemaInfoObject = {
             'members': [self._gen_object_member(m) for m in members]
@@ -345,7 +343,7 @@ def visit_object_type_flat(self, name: str, info: 
Optional[QAPISourceInfo],
 
     def visit_alternate_type(self, name: str, info: Optional[QAPISourceInfo],
                              ifcond: QAPISchemaIfCond,
-                             features: List[QAPISchemaFeature],
+                             features: list[QAPISchemaFeature],
                              alternatives: QAPISchemaAlternatives) -> None:
         self._gen_tree(
             name, 'alternate',
@@ -357,7 +355,7 @@ def visit_alternate_type(self, name: str, info: 
Optional[QAPISourceInfo],
 
     def visit_command(self, name: str, info: Optional[QAPISourceInfo],
                       ifcond: QAPISchemaIfCond,
-                      features: List[QAPISchemaFeature],
+                      features: list[QAPISchemaFeature],
                       arg_type: Optional[QAPISchemaObjectType],
                       ret_type: Optional[QAPISchemaType], gen: bool,
                       success_response: bool, boxed: bool, allow_oob: bool,
@@ -376,7 +374,7 @@ def visit_command(self, name: str, info: 
Optional[QAPISourceInfo],
 
     def visit_event(self, name: str, info: Optional[QAPISourceInfo],
                     ifcond: QAPISchemaIfCond,
-                    features: List[QAPISchemaFeature],
+                    features: list[QAPISchemaFeature],
                     arg_type: Optional[QAPISchemaObjectType],
                     boxed: bool) -> None:
         assert self._schema is not None
diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
index 949d9e8bff7..1475e92a208 100644
--- a/scripts/qapi/parser.py
+++ b/scripts/qapi/parser.py
@@ -20,12 +20,9 @@
 from typing import (
     TYPE_CHECKING,
     Any,
-    Dict,
-    List,
     Mapping,
     Match,
     Optional,
-    Set,
     Union,
 )
 
@@ -41,10 +38,10 @@
 
 
 # Return value alias for get_expr().
-_ExprValue = Union[List[object], Dict[str, object], str, bool]
+_ExprValue = Union[list[object], dict[str, object], str, bool]
 
 
-class QAPIExpression(Dict[str, Any]):
+class QAPIExpression(dict[str, Any]):
     # pylint: disable=too-few-public-methods
     def __init__(self,
                  data: Mapping[str, object],
@@ -91,7 +88,7 @@ class QAPISchemaParser:
     """
     def __init__(self,
                  fname: str,
-                 previously_included: Optional[Set[str]] = None,
+                 previously_included: Optional[set[str]] = None,
                  incl_info: Optional[QAPISourceInfo] = None):
         self._fname = fname
         self._included = previously_included or set()
@@ -107,8 +104,8 @@ def __init__(self,
         self.line_pos = 0
 
         # Parser output:
-        self.exprs: List[QAPIExpression] = []
-        self.docs: List[QAPIDoc] = []
+        self.exprs: list[QAPIExpression] = []
+        self.docs: list[QAPIDoc] = []
 
         # Showtime!
         self._parse()
@@ -195,7 +192,7 @@ def reject_expr_doc(doc: Optional['QAPIDoc']) -> None:
     def _include(include: str,
                  info: QAPISourceInfo,
                  incl_fname: str,
-                 previously_included: Set[str]
+                 previously_included: set[str]
                  ) -> Optional['QAPISchemaParser']:
         incl_abs_fname = os.path.abspath(incl_fname)
         # catch inclusion cycle
@@ -220,7 +217,7 @@ def _include(include: str,
     @staticmethod
     def _pragma(name: str, value: object, info: QAPISourceInfo) -> None:
 
-        def check_list_str(name: str, value: object) -> List[str]:
+        def check_list_str(name: str, value: object) -> list[str]:
             if (not isinstance(value, list) or
                     any(not isinstance(elt, str) for elt in value)):
                 raise QAPISemError(
@@ -354,8 +351,8 @@ def accept(self, skip_comment: bool = True) -> None:
                                    self.src[self.cursor-1:])
                 raise QAPIParseError(self, "stray '%s'" % match.group(0))
 
-    def get_members(self) -> Dict[str, object]:
-        expr: Dict[str, object] = {}
+    def get_members(self) -> dict[str, object]:
+        expr: dict[str, object] = {}
         if self.tok == '}':
             self.accept()
             return expr
@@ -381,8 +378,8 @@ def get_members(self) -> Dict[str, object]:
             if self.tok != "'":
                 raise QAPIParseError(self, "expected string")
 
-    def get_values(self) -> List[object]:
-        expr: List[object] = []
+    def get_values(self) -> list[object]:
+        expr: list[object] = []
         if self.tok == ']':
             self.accept()
             return expr
@@ -694,21 +691,21 @@ def __init__(self, info: QAPISourceInfo, symbol: 
Optional[str] = None):
         # definition doc's symbol, None for free-form doc
         self.symbol: Optional[str] = symbol
         # the sections in textual order
-        self.all_sections: List[QAPIDoc.Section] = [
+        self.all_sections: list[QAPIDoc.Section] = [
             QAPIDoc.Section(info, QAPIDoc.Kind.PLAIN)
         ]
         # the body section
         self.body: Optional[QAPIDoc.Section] = self.all_sections[0]
         # dicts mapping parameter/feature names to their description
-        self.args: Dict[str, QAPIDoc.ArgSection] = {}
-        self.features: Dict[str, QAPIDoc.ArgSection] = {}
+        self.args: dict[str, QAPIDoc.ArgSection] = {}
+        self.features: dict[str, QAPIDoc.ArgSection] = {}
         # a command's "Returns" and "Errors" section
         self.returns: Optional[QAPIDoc.Section] = None
         self.errors: Optional[QAPIDoc.Section] = None
         # "Since" section
         self.since: Optional[QAPIDoc.Section] = None
         # sections other than .body, .args, .features
-        self.sections: List[QAPIDoc.Section] = []
+        self.sections: list[QAPIDoc.Section] = []
 
     def end(self) -> None:
         for section in self.all_sections:
@@ -763,7 +760,7 @@ def _new_description(
         info: QAPISourceInfo,
         name: str,
         kind: 'QAPIDoc.Kind',
-        desc: Dict[str, ArgSection]
+        desc: dict[str, ArgSection]
     ) -> None:
         if not name:
             raise QAPISemError(info, "invalid parameter name")
@@ -834,7 +831,7 @@ def check_expr(self, expr: QAPIExpression) -> None:
     def check(self) -> None:
 
         def check_args_section(
-                args: Dict[str, QAPIDoc.ArgSection], what: str
+                args: dict[str, QAPIDoc.ArgSection], what: str
         ) -> None:
             bogus = [name for name, section in args.items()
                      if not section.member]
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index cbe3b5aa91e..aaeb7b202f8 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -24,8 +24,6 @@
 from typing import (
     Any,
     Callable,
-    Dict,
-    List,
     Optional,
     Union,
     ValuesView,
@@ -49,7 +47,7 @@
 class QAPISchemaIfCond:
     def __init__(
         self,
-        ifcond: Optional[Union[str, Dict[str, object]]] = None,
+        ifcond: Optional[Union[str, dict[str, object]]] = None,
     ) -> None:
         self.ifcond = ifcond
 
@@ -121,7 +119,7 @@ def __init__(
         info: Optional[QAPISourceInfo],
         doc: Optional[QAPIDoc],
         ifcond: Optional[QAPISchemaIfCond] = None,
-        features: Optional[List[QAPISchemaFeature]] = None,
+        features: Optional[list[QAPISchemaFeature]] = None,
     ):
         super().__init__(info)
         for f in features or []:
@@ -141,7 +139,7 @@ def c_name(self) -> str:
     def check(self, schema: QAPISchema) -> None:
         assert not self._checked
         super().check(schema)
-        seen: Dict[str, QAPISchemaMember] = {}
+        seen: dict[str, QAPISchemaMember] = {}
         for f in self.features:
             f.check_clash(self.info, seen)
 
@@ -192,8 +190,8 @@ def visit_enum_type(
         name: str,
         info: Optional[QAPISourceInfo],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
-        members: List[QAPISchemaEnumMember],
+        features: list[QAPISchemaFeature],
+        members: list[QAPISchemaEnumMember],
         prefix: Optional[str],
     ) -> None:
         pass
@@ -212,9 +210,9 @@ def visit_object_type(
         name: str,
         info: Optional[QAPISourceInfo],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
+        features: list[QAPISchemaFeature],
         base: Optional[QAPISchemaObjectType],
-        members: List[QAPISchemaObjectTypeMember],
+        members: list[QAPISchemaObjectTypeMember],
         branches: Optional[QAPISchemaBranches],
     ) -> None:
         pass
@@ -224,8 +222,8 @@ def visit_object_type_flat(
         name: str,
         info: Optional[QAPISourceInfo],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
-        members: List[QAPISchemaObjectTypeMember],
+        features: list[QAPISchemaFeature],
+        members: list[QAPISchemaObjectTypeMember],
         branches: Optional[QAPISchemaBranches],
     ) -> None:
         pass
@@ -235,7 +233,7 @@ def visit_alternate_type(
         name: str,
         info: Optional[QAPISourceInfo],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
+        features: list[QAPISchemaFeature],
         alternatives: QAPISchemaAlternatives,
     ) -> None:
         pass
@@ -245,7 +243,7 @@ def visit_command(
         name: str,
         info: Optional[QAPISourceInfo],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
+        features: list[QAPISchemaFeature],
         arg_type: Optional[QAPISchemaObjectType],
         ret_type: Optional[QAPISchemaType],
         gen: bool,
@@ -262,7 +260,7 @@ def visit_event(
         name: str,
         info: Optional[QAPISourceInfo],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
+        features: list[QAPISchemaFeature],
         arg_type: Optional[QAPISchemaObjectType],
         boxed: bool,
     ) -> None:
@@ -275,7 +273,7 @@ class QAPISchemaModule:
 
     def __init__(self, name: str):
         self.name = name
-        self._entity_list: List[QAPISchemaEntity] = []
+        self._entity_list: list[QAPISchemaEntity] = []
 
     @staticmethod
     def is_system_module(name: str) -> bool:
@@ -418,8 +416,8 @@ def __init__(
         info: Optional[QAPISourceInfo],
         doc: Optional[QAPIDoc],
         ifcond: Optional[QAPISchemaIfCond],
-        features: Optional[List[QAPISchemaFeature]],
-        members: List[QAPISchemaEnumMember],
+        features: Optional[list[QAPISchemaFeature]],
+        members: list[QAPISchemaEnumMember],
         prefix: Optional[str],
     ):
         super().__init__(name, info, doc, ifcond, features)
@@ -430,7 +428,7 @@ def __init__(
 
     def check(self, schema: QAPISchema) -> None:
         super().check(schema)
-        seen: Dict[str, QAPISchemaMember] = {}
+        seen: dict[str, QAPISchemaMember] = {}
         for m in self.members:
             m.check_clash(self.info, seen)
 
@@ -447,7 +445,7 @@ def is_implicit(self) -> bool:
     def c_type(self) -> str:
         return c_name(self.name)
 
-    def member_names(self) -> List[str]:
+    def member_names(self) -> list[str]:
         return [m.name for m in self.members]
 
     def json_type(self) -> str:
@@ -521,9 +519,9 @@ def __init__(
         info: Optional[QAPISourceInfo],
         doc: Optional[QAPIDoc],
         ifcond: Optional[QAPISchemaIfCond],
-        features: Optional[List[QAPISchemaFeature]],
+        features: Optional[list[QAPISchemaFeature]],
         base: Optional[str],
-        local_members: List[QAPISchemaObjectTypeMember],
+        local_members: list[QAPISchemaObjectTypeMember],
         branches: Optional[QAPISchemaBranches],
     ):
         # struct has local_members, optional base, and no branches
@@ -538,7 +536,7 @@ def __init__(
         self.base = None
         self.local_members = local_members
         self.branches = branches
-        self.members: List[QAPISchemaObjectTypeMember]
+        self.members: list[QAPISchemaObjectTypeMember]
         self._check_complete = False
 
     def check(self, schema: QAPISchema) -> None:
@@ -573,9 +571,9 @@ def check(self, schema: QAPISchema) -> None:
             m.check_clash(self.info, seen)
 
         # self.check_clash() works in terms of the supertype, but
-        # self.members is declared List[QAPISchemaObjectTypeMember].
+        # self.members is declared list[QAPISchemaObjectTypeMember].
         # Cast down to the subtype.
-        members = cast(List[QAPISchemaObjectTypeMember], list(seen.values()))
+        members = cast(list[QAPISchemaObjectTypeMember], list(seen.values()))
 
         if self.branches:
             self.branches.check(schema, seen)
@@ -590,7 +588,7 @@ def check(self, schema: QAPISchema) -> None:
     def check_clash(
         self,
         info: Optional[QAPISourceInfo],
-        seen: Dict[str, QAPISchemaMember],
+        seen: dict[str, QAPISchemaMember],
     ) -> None:
         assert self._checked
         for m in self.members:
@@ -650,7 +648,7 @@ def __init__(
         info: QAPISourceInfo,
         doc: Optional[QAPIDoc],
         ifcond: Optional[QAPISchemaIfCond],
-        features: List[QAPISchemaFeature],
+        features: list[QAPISchemaFeature],
         alternatives: QAPISchemaAlternatives,
     ):
         super().__init__(name, info, doc, ifcond, features)
@@ -667,8 +665,8 @@ def check(self, schema: QAPISchema) -> None:
         self.alternatives.check(schema, {})
         # Alternate branch names have no relation to the tag enum values;
         # so we have to check for potential name collisions ourselves.
-        seen: Dict[str, QAPISchemaMember] = {}
-        types_seen: Dict[str, str] = {}
+        seen: dict[str, QAPISchemaMember] = {}
+        types_seen: dict[str, str] = {}
         for v in self.alternatives.variants:
             v.check_clash(self.info, seen)
             qtype = v.type.alternate_qtype()
@@ -720,7 +718,7 @@ class QAPISchemaVariants:
     def __init__(
         self,
         info: QAPISourceInfo,
-        variants: List[QAPISchemaVariant],
+        variants: list[QAPISchemaVariant],
     ):
         self.info = info
         self.tag_member: QAPISchemaObjectTypeMember
@@ -732,7 +730,7 @@ def set_defined_in(self, name: str) -> None:
 
     # pylint: disable=unused-argument
     def check(
-            self, schema: QAPISchema, seen: Dict[str, QAPISchemaMember]
+            self, schema: QAPISchema, seen: dict[str, QAPISchemaMember]
     ) -> None:
         for v in self.variants:
             v.check(schema)
@@ -741,13 +739,13 @@ def check(
 class QAPISchemaBranches(QAPISchemaVariants):
     def __init__(self,
                  info: QAPISourceInfo,
-                 variants: List[QAPISchemaVariant],
+                 variants: list[QAPISchemaVariant],
                  tag_name: str):
         super().__init__(info, variants)
         self._tag_name = tag_name
 
     def check(
-            self, schema: QAPISchema, seen: Dict[str, QAPISchemaMember]
+            self, schema: QAPISchema, seen: dict[str, QAPISchemaMember]
     ) -> None:
         # We need to narrow the member type:
         tag_member = seen.get(c_name(self._tag_name))
@@ -815,7 +813,7 @@ def check(
     def check_clash(
         self,
         info: Optional[QAPISourceInfo],
-        seen: Dict[str, QAPISchemaMember],
+        seen: dict[str, QAPISchemaMember],
     ) -> None:
         for v in self.variants:
             # Reset seen map for each variant, since qapi names from one
@@ -829,13 +827,13 @@ def check_clash(
 class QAPISchemaAlternatives(QAPISchemaVariants):
     def __init__(self,
                  info: QAPISourceInfo,
-                 variants: List[QAPISchemaVariant],
+                 variants: list[QAPISchemaVariant],
                  tag_member: QAPISchemaObjectTypeMember):
         super().__init__(info, variants)
         self.tag_member = tag_member
 
     def check(
-            self, schema: QAPISchema, seen: Dict[str, QAPISchemaMember]
+            self, schema: QAPISchema, seen: dict[str, QAPISchemaMember]
     ) -> None:
         super().check(schema, seen)
         assert isinstance(self.tag_member.type, QAPISchemaEnumType)
@@ -865,7 +863,7 @@ def set_defined_in(self, name: str) -> None:
     def check_clash(
         self,
         info: Optional[QAPISourceInfo],
-        seen: Dict[str, QAPISchemaMember],
+        seen: dict[str, QAPISchemaMember],
     ) -> None:
         cname = c_name(self.name)
         if cname in seen:
@@ -916,7 +914,7 @@ def __init__(
         name: str,
         info: Optional[QAPISourceInfo],
         ifcond: Optional[QAPISchemaIfCond] = None,
-        features: Optional[List[QAPISchemaFeature]] = None,
+        features: Optional[list[QAPISchemaFeature]] = None,
     ):
         super().__init__(name, info, ifcond)
         for f in features or []:
@@ -948,7 +946,7 @@ def __init__(
         typ: str,
         optional: bool,
         ifcond: Optional[QAPISchemaIfCond] = None,
-        features: Optional[List[QAPISchemaFeature]] = None,
+        features: Optional[list[QAPISchemaFeature]] = None,
     ):
         super().__init__(name, info, ifcond)
         for f in features or []:
@@ -965,7 +963,7 @@ def check(self, schema: QAPISchema) -> None:
         assert self.defined_in
         self.type = schema.resolve_type(self._type_name, self.info,
                                         self.describe)
-        seen: Dict[str, QAPISchemaMember] = {}
+        seen: dict[str, QAPISchemaMember] = {}
         for f in self.features:
             f.check_clash(self.info, seen)
 
@@ -998,7 +996,7 @@ def __init__(
         info: QAPISourceInfo,
         doc: Optional[QAPIDoc],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
+        features: list[QAPISchemaFeature],
         arg_type: Optional[str],
         ret_type: Optional[str],
         gen: bool,
@@ -1080,7 +1078,7 @@ def __init__(
         info: QAPISourceInfo,
         doc: Optional[QAPIDoc],
         ifcond: QAPISchemaIfCond,
-        features: List[QAPISchemaFeature],
+        features: list[QAPISchemaFeature],
         arg_type: Optional[str],
         boxed: bool,
     ):
@@ -1138,12 +1136,12 @@ def __init__(self, fname: str):
 
         exprs = check_exprs(parser.exprs)
         self.docs = parser.docs
-        self._entity_list: List[QAPISchemaEntity] = []
-        self._entity_dict: Dict[str, QAPISchemaDefinition] = {}
-        self._module_dict: Dict[str, QAPISchemaModule] = {}
+        self._entity_list: list[QAPISchemaEntity] = []
+        self._entity_dict: dict[str, QAPISchemaDefinition] = {}
+        self._module_dict: dict[str, QAPISchemaModule] = {}
         # NB, values in the dict will identify the first encountered
         # usage of a named feature only
-        self._feature_dict: Dict[str, QAPISchemaFeature] = {}
+        self._feature_dict: dict[str, QAPISchemaFeature] = {}
 
         # All schemas get the names defined in the QapiSpecialFeature enum.
         # Rely on dict iteration order matching insertion order so that
@@ -1269,9 +1267,9 @@ def _def_predefineds(self) -> None:
 
     def _make_features(
         self,
-        features: Optional[List[Dict[str, Any]]],
+        features: Optional[list[dict[str, Any]]],
         info: Optional[QAPISourceInfo],
-    ) -> List[QAPISchemaFeature]:
+    ) -> list[QAPISchemaFeature]:
         if features is None:
             return []
 
@@ -1287,8 +1285,8 @@ def _make_features(
     def _make_enum_member(
         self,
         name: str,
-        ifcond: Optional[Union[str, Dict[str, Any]]],
-        features: Optional[List[Dict[str, Any]]],
+        ifcond: Optional[Union[str, dict[str, Any]]],
+        features: Optional[list[dict[str, Any]]],
         info: Optional[QAPISourceInfo],
     ) -> QAPISchemaEnumMember:
         return QAPISchemaEnumMember(name, info,
@@ -1296,8 +1294,8 @@ def _make_enum_member(
                                     self._make_features(features, info))
 
     def _make_enum_members(
-        self, values: List[Dict[str, Any]], info: Optional[QAPISourceInfo]
-    ) -> List[QAPISchemaEnumMember]:
+        self, values: list[dict[str, Any]], info: Optional[QAPISourceInfo]
+    ) -> list[QAPISchemaEnumMember]:
         return [self._make_enum_member(v['name'], v.get('if'),
                                        v.get('features'), info)
                 for v in values]
@@ -1317,7 +1315,7 @@ def _make_implicit_object_type(
         info: QAPISourceInfo,
         ifcond: QAPISchemaIfCond,
         role: str,
-        members: List[QAPISchemaObjectTypeMember],
+        members: list[QAPISchemaObjectTypeMember],
     ) -> Optional[str]:
         if not members:
             return None
@@ -1348,9 +1346,9 @@ def _def_enum_type(self, expr: QAPIExpression) -> None:
     def _make_member(
         self,
         name: str,
-        typ: Union[List[str], str],
+        typ: Union[list[str], str],
         ifcond: QAPISchemaIfCond,
-        features: Optional[List[Dict[str, Any]]],
+        features: Optional[list[dict[str, Any]]],
         info: QAPISourceInfo,
     ) -> QAPISchemaObjectTypeMember:
         optional = False
@@ -1365,9 +1363,9 @@ def _make_member(
 
     def _make_members(
         self,
-        data: Dict[str, Any],
+        data: dict[str, Any],
         info: QAPISourceInfo,
-    ) -> List[QAPISchemaObjectTypeMember]:
+    ) -> list[QAPISchemaObjectTypeMember]:
         return [self._make_member(key, value['type'],
                                   QAPISchemaIfCond(value.get('if')),
                                   value.get('features'), info)
@@ -1415,7 +1413,7 @@ def _def_union_type(self, expr: QAPIExpression) -> None:
                                QAPISchemaIfCond(value.get('if')),
                                info)
             for (key, value) in data.items()]
-        members: List[QAPISchemaObjectTypeMember] = []
+        members: list[QAPISchemaObjectTypeMember] = []
         self._def_definition(
             QAPISchemaObjectType(name, info, expr.doc, ifcond, features,
                                  base, members,
@@ -1479,7 +1477,7 @@ def _def_event(self, expr: QAPIExpression) -> None:
         self._def_definition(QAPISchemaEvent(name, info, expr.doc, ifcond,
                                              features, data, boxed))
 
-    def _def_exprs(self, exprs: List[QAPIExpression]) -> None:
+    def _def_exprs(self, exprs: list[QAPIExpression]) -> None:
         for expr in exprs:
             if 'enum' in expr:
                 self._def_enum_type(expr)
diff --git a/scripts/qapi/source.py b/scripts/qapi/source.py
index ffdc3f482ac..960fe58a5ff 100644
--- a/scripts/qapi/source.py
+++ b/scripts/qapi/source.py
@@ -10,7 +10,7 @@
 # See the COPYING file in the top-level directory.
 
 import copy
-from typing import List, Optional, TypeVar
+from typing import Optional, TypeVar
 
 
 class QAPISchemaPragma:
@@ -21,13 +21,13 @@ def __init__(self) -> None:
         # Are documentation comments required?
         self.doc_required = False
         # Commands whose names may use '_'
-        self.command_name_exceptions: List[str] = []
+        self.command_name_exceptions: list[str] = []
         # Commands allowed to return a non-dictionary
-        self.command_returns_exceptions: List[str] = []
+        self.command_returns_exceptions: list[str] = []
         # Types, commands, and events with undocumented members
-        self.documentation_exceptions: List[str] = []
+        self.documentation_exceptions: list[str] = []
         # Types whose member names may violate case conventions
-        self.member_name_exceptions: List[str] = []
+        self.member_name_exceptions: list[str] = []
 
 
 class QAPISourceInfo:
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index 2bf75338283..ad84e68b488 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -13,7 +13,7 @@
 # See the COPYING file in the top-level directory.
 """
 
-from typing import List, Optional
+from typing import Optional
 
 from .common import c_enum_const, c_name, mcgen
 from .gen import QAPISchemaModularCVisitor, gen_features, ifcontext
@@ -38,7 +38,7 @@
 
 
 def gen_enum_lookup(name: str,
-                    members: List[QAPISchemaEnumMember],
+                    members: list[QAPISchemaEnumMember],
                     prefix: Optional[str] = None) -> str:
     max_index = c_enum_const(name, '_MAX', prefix)
     feats = ''
@@ -82,7 +82,7 @@ def gen_enum_lookup(name: str,
 
 
 def gen_enum(name: str,
-             members: List[QAPISchemaEnumMember],
+             members: list[QAPISchemaEnumMember],
              prefix: Optional[str] = None) -> str:
     # append automatically generated _MAX value
     enum_members = members + [QAPISchemaEnumMember('_MAX', None)]
@@ -136,7 +136,7 @@ def gen_array(name: str, element_type: QAPISchemaType) -> 
str:
                  c_name=c_name(name), c_type=element_type.c_type())
 
 
-def gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str:
+def gen_struct_members(members: list[QAPISchemaObjectTypeMember]) -> str:
     ret = ''
     for memb in members:
         ret += memb.ifcond.gen_if()
@@ -155,7 +155,7 @@ def gen_struct_members(members: 
List[QAPISchemaObjectTypeMember]) -> str:
 
 def gen_object(name: str, ifcond: QAPISchemaIfCond,
                base: Optional[QAPISchemaObjectType],
-               members: List[QAPISchemaObjectTypeMember],
+               members: list[QAPISchemaObjectTypeMember],
                variants: Optional[QAPISchemaVariants]) -> str:
     if name in objects_seen:
         return ''
@@ -325,8 +325,8 @@ def visit_enum_type(self,
                         name: str,
                         info: Optional[QAPISourceInfo],
                         ifcond: QAPISchemaIfCond,
-                        features: List[QAPISchemaFeature],
-                        members: List[QAPISchemaEnumMember],
+                        features: list[QAPISchemaFeature],
+                        members: list[QAPISchemaEnumMember],
                         prefix: Optional[str]) -> None:
         with ifcontext(ifcond, self._genh, self._genc):
             self._genh.preamble_add(gen_enum(name, members, prefix))
@@ -346,9 +346,9 @@ def visit_object_type(self,
                           name: str,
                           info: Optional[QAPISourceInfo],
                           ifcond: QAPISchemaIfCond,
-                          features: List[QAPISchemaFeature],
+                          features: list[QAPISchemaFeature],
                           base: Optional[QAPISchemaObjectType],
-                          members: List[QAPISchemaObjectTypeMember],
+                          members: list[QAPISchemaObjectTypeMember],
                           branches: Optional[QAPISchemaBranches]) -> None:
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
@@ -369,7 +369,7 @@ def visit_alternate_type(self,
                              name: str,
                              info: Optional[QAPISourceInfo],
                              ifcond: QAPISchemaIfCond,
-                             features: List[QAPISchemaFeature],
+                             features: list[QAPISchemaFeature],
                              alternatives: QAPISchemaAlternatives) -> None:
         with ifcontext(ifcond, self._genh):
             self._genh.preamble_add(gen_fwd_object_or_array(name))
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 36e240967b6..a0221fe5ab8 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -13,7 +13,7 @@
 See the COPYING file in the top-level directory.
 """
 
-from typing import List, Optional
+from typing import Optional
 
 from .common import (
     c_enum_const,
@@ -59,7 +59,7 @@ def gen_visit_members_decl(name: str) -> str:
 
 def gen_visit_object_members(name: str,
                              base: Optional[QAPISchemaObjectType],
-                             members: List[QAPISchemaObjectTypeMember],
+                             members: list[QAPISchemaObjectTypeMember],
                              branches: Optional[QAPISchemaBranches]) -> str:
     ret = mcgen('''
 
@@ -370,8 +370,8 @@ def visit_enum_type(self,
                         name: str,
                         info: Optional[QAPISourceInfo],
                         ifcond: QAPISchemaIfCond,
-                        features: List[QAPISchemaFeature],
-                        members: List[QAPISchemaEnumMember],
+                        features: list[QAPISchemaFeature],
+                        members: list[QAPISchemaEnumMember],
                         prefix: Optional[str]) -> None:
         with ifcontext(ifcond, self._genh, self._genc):
             self._genh.add(gen_visit_decl(name, scalar=True))
@@ -390,9 +390,9 @@ def visit_object_type(self,
                           name: str,
                           info: Optional[QAPISourceInfo],
                           ifcond: QAPISchemaIfCond,
-                          features: List[QAPISchemaFeature],
+                          features: list[QAPISchemaFeature],
                           base: Optional[QAPISchemaObjectType],
-                          members: List[QAPISchemaObjectTypeMember],
+                          members: list[QAPISchemaObjectTypeMember],
                           branches: Optional[QAPISchemaBranches]) -> None:
         # Nothing to do for the special empty builtin
         if name == 'q_empty':
@@ -412,7 +412,7 @@ def visit_alternate_type(self,
                              name: str,
                              info: Optional[QAPISourceInfo],
                              ifcond: QAPISchemaIfCond,
-                             features: List[QAPISchemaFeature],
+                             features: list[QAPISchemaFeature],
                              alternatives: QAPISchemaAlternatives) -> None:
         with ifcontext(ifcond, self._genh, self._genc):
             self._genh.add(gen_visit_decl(name))
diff --git a/scripts/rust/rustc_args.py b/scripts/rust/rustc_args.py
index 2633157df2a..5de6079b9a0 100644
--- a/scripts/rust/rustc_args.py
+++ b/scripts/rust/rustc_args.py
@@ -28,7 +28,7 @@
 from dataclasses import dataclass
 import logging
 from pathlib import Path
-from typing import Any, Iterable, List, Mapping, Optional, Set
+from typing import Any, Iterable, Mapping, Optional
 
 try:
     import tomllib
@@ -41,7 +41,7 @@
 class CargoTOML:
     tomldata: Mapping[Any, Any]
     workspace_data: Mapping[Any, Any]
-    check_cfg: Set[str]
+    check_cfg: set[str]
 
     def __init__(self, path: Optional[str], workspace: Optional[str]):
         if path is not None:
@@ -78,7 +78,7 @@ def get_table(self, key: str, can_be_workspace: bool = False) 
-> Mapping[Any, An
 
 @dataclass
 class LintFlag:
-    flags: List[str]
+    flags: list[str]
     priority: int
 
 
diff --git a/scripts/u2f-setup-gen.py b/scripts/u2f-setup-gen.py
index 2122598fed8..677530dbe9c 100755
--- a/scripts/u2f-setup-gen.py
+++ b/scripts/u2f-setup-gen.py
@@ -12,7 +12,6 @@
 import sys
 import os
 from random import randint
-from typing import Tuple
 
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives.asymmetric import ec
@@ -53,7 +52,7 @@ def write_setup_dir(dirpath: str, privkey_pem: bytes, 
cert_pem: bytes,
         f.write(f'{str(counter)}\n')
 
 
-def generate_ec_key_pair() -> Tuple[str, str]:
+def generate_ec_key_pair() -> tuple[str, str]:
     """
     Generate an ec key pair.
 
diff --git a/tests/functional/qemu_test/ports.py 
b/tests/functional/qemu_test/ports.py
index 631b77abf6b..3b9f5f286a1 100644
--- a/tests/functional/qemu_test/ports.py
+++ b/tests/functional/qemu_test/ports.py
@@ -12,7 +12,6 @@
 import socket
 
 from .config import BUILD_DIR
-from typing import List
 
 
 class Ports():
@@ -41,7 +40,7 @@ def check_bind(self, port: int) -> bool:
 
         return True
 
-    def find_free_ports(self, count: int) -> List[int]:
+    def find_free_ports(self, count: int) -> list[int]:
         result = []
         for port in range(self.PORTS_START, self.PORTS_END):
             if self.check_bind(port):
diff --git a/tests/functional/test_acpi_bits.py 
b/tests/functional/test_acpi_bits.py
index 8e0563a97b1..b9ca6a9b162 100755
--- a/tests/functional/test_acpi_bits.py
+++ b/tests/functional/test_acpi_bits.py
@@ -37,7 +37,6 @@
 import subprocess
 
 from typing import (
-    List,
     Optional,
     Sequence,
 )
@@ -76,7 +75,7 @@ def __init__(self,
         self.base_temp_dir = base_temp_dir
 
     @property
-    def _base_args(self) -> List[str]:
+    def _base_args(self) -> list[str]:
         args = super()._base_args
         args.extend([
             '-chardev',
diff --git a/tests/qemu-iotests/151 b/tests/qemu-iotests/151
index f2ff9c5dac2..5cb462b79a3 100755
--- a/tests/qemu-iotests/151
+++ b/tests/qemu-iotests/151
@@ -23,7 +23,7 @@ import math
 import os
 import subprocess
 import time
-from typing import List, Optional
+from typing import Optional
 import iotests
 from iotests import qemu_img
 
@@ -195,7 +195,7 @@ class TestActiveMirror(iotests.QMPTestCase):
 class TestThrottledWithNbdExportBase(iotests.QMPTestCase):
     image_len = 128 * 1024 * 1024  # MB
     iops: Optional[int] = None
-    background_processes: List['subprocess.Popen[str]'] = []
+    background_processes: list['subprocess.Popen[str]'] = []
 
     def setUp(self):
         # Must be set by subclasses
diff --git a/tests/qemu-iotests/297 b/tests/qemu-iotests/297
index ee78a627359..505905b775b 100755
--- a/tests/qemu-iotests/297
+++ b/tests/qemu-iotests/297
@@ -19,7 +19,6 @@
 import os
 import subprocess
 import sys
-from typing import List
 
 import iotests
 import linters
@@ -41,7 +40,7 @@ def check_linter(linter: str) -> bool:
     return True
 
 
-def test_pylint(files: List[str]) -> None:
+def test_pylint(files: list[str]) -> None:
     print('=== pylint ===')
     sys.stdout.flush()
 
@@ -51,7 +50,7 @@ def test_pylint(files: List[str]) -> None:
     linters.run_linter('pylint', files)
 
 
-def test_mypy(files: List[str]) -> None:
+def test_mypy(files: list[str]) -> None:
     print('=== mypy ===')
     sys.stdout.flush()
 
diff --git a/tests/qemu-iotests/300 b/tests/qemu-iotests/300
index e46616d7b19..9d5fd74920a 100755
--- a/tests/qemu-iotests/300
+++ b/tests/qemu-iotests/300
@@ -22,12 +22,12 @@
 import os
 import random
 import re
-from typing import Dict, List, Optional
+from typing import Optional
 
 import iotests
 
 
-BlockBitmapMapping = List[Dict[str, object]]
+BlockBitmapMapping = list[dict[str, object]]
 
 mig_sock = os.path.join(iotests.sock_dir, 'mig_sock')
 
diff --git a/tests/qemu-iotests/fat16.py b/tests/qemu-iotests/fat16.py
index 7d2d0524133..a2c69b3a54d 100644
--- a/tests/qemu-iotests/fat16.py
+++ b/tests/qemu-iotests/fat16.py
@@ -15,7 +15,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from typing import Callable, List, Optional, Protocol, Set
+from typing import Callable, Optional, Protocol
 import string
 
 SECTOR_SIZE = 512
@@ -227,7 +227,7 @@ def __init__(
         self.fats = self.read_sectors(
             self.boot_sector.reserved_sectors, fat_size_in_sectors
         )
-        self.fats_dirty_sectors: Set[int] = set()
+        self.fats_dirty_sectors: set[int] = set()
 
     def read_sectors(self, start_sector: int, num_sectors: int) -> bytes:
         return self.sector_reader(start_sector + self.start_sector,
@@ -238,7 +238,7 @@ def write_sectors(self, start_sector: int, data: bytes) -> 
None:
 
     def directory_from_bytes(
         self, data: bytes, start_sector: int
-    ) -> List[FatDirectoryEntry]:
+    ) -> list[FatDirectoryEntry]:
         """
         Convert `bytes` into a list of `FatDirectoryEntry` objects.
         Will ignore long file names.
@@ -268,7 +268,7 @@ def directory_from_bytes(
             )
         return entries
 
-    def read_root_directory(self) -> List[FatDirectoryEntry]:
+    def read_root_directory(self) -> list[FatDirectoryEntry]:
         root_dir = self.read_sectors(
             self.boot_sector.root_dir_start(), self.boot_sector.root_dir_size()
         )
@@ -373,7 +373,7 @@ def write_cluster(self, cluster: int, data: bytes) -> None:
 
     def read_directory(
         self, cluster: Optional[int]
-    ) -> List[FatDirectoryEntry]:
+    ) -> list[FatDirectoryEntry]:
         """
         Read the directory at the given cluster.
         """
diff --git a/tests/qemu-iotests/findtests.py b/tests/qemu-iotests/findtests.py
index dd77b453b8a..11531bdca7b 100644
--- a/tests/qemu-iotests/findtests.py
+++ b/tests/qemu-iotests/findtests.py
@@ -21,7 +21,7 @@
 import re
 from collections import defaultdict
 from contextlib import contextmanager
-from typing import Optional, List, Iterator, Set
+from typing import Optional, Iterator
 
 
 @contextmanager
@@ -89,10 +89,10 @@ def parse_test_name(self, name: str) -> str:
 
         return name
 
-    def find_tests(self, groups: Optional[List[str]] = None,
-                   exclude_groups: Optional[List[str]] = None,
-                   tests: Optional[List[str]] = None,
-                   start_from: Optional[str] = None) -> List[str]:
+    def find_tests(self, groups: Optional[list[str]] = None,
+                   exclude_groups: Optional[list[str]] = None,
+                   tests: Optional[list[str]] = None,
+                   start_from: Optional[str] = None) -> list[str]:
         """Find tests
 
         Algorithm:
@@ -123,7 +123,7 @@ def find_tests(self, groups: Optional[List[str]] = None,
         if tests is None:
             tests = []
 
-        res: Set[str] = set()
+        res: set[str] = set()
         if groups:
             # Some groups specified. exclude_groups supported, additionally
             # selecting some individual tests supported as well.
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 7292c8b342a..49a6bbc4cde 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -31,8 +31,8 @@
 import subprocess
 import sys
 import time
-from typing import (Any, Callable, Dict, Iterable, Iterator,
-                    List, Optional, Sequence, TextIO, Tuple, Type, TypeVar)
+from typing import (Any, Callable, Iterable, Iterator,
+                    Optional, Sequence, TextIO, TypeVar)
 import unittest
 
 from contextlib import contextmanager
@@ -154,7 +154,7 @@ def qemu_tool_popen(args: Sequence[str],
 def qemu_tool_pipe_and_status(tool: str, args: Sequence[str],
                               connect_stderr: bool = True,
                               drop_successful_output: bool = False) \
-        -> Tuple[str, int]:
+        -> tuple[str, int]:
     """
     Run a tool and return both its output and its exit code
     """
@@ -168,7 +168,7 @@ def qemu_tool_pipe_and_status(tool: str, args: 
Sequence[str],
             output = ''
         return (output, subp.returncode)
 
-def qemu_img_create_prepare_args(args: List[str]) -> List[str]:
+def qemu_img_create_prepare_args(args: list[str]) -> list[str]:
     if not args or args[0] != 'create':
         return list(args)
     args = args[1:]
@@ -344,7 +344,7 @@ def img_info_log(filename: str, filter_path: Optional[str] 
= None,
         filter_path = filename
     log(filter_img_info(output, filter_path, drop_child_info))
 
-def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
+def qemu_io_wrap_args(args: Sequence[str]) -> list[str]:
     if '-f' in args or '--image-opts' in args:
         return qemu_io_args_no_fmt + list(args)
     else:
@@ -457,7 +457,7 @@ def __init__(self, *args: str, instance_id: str = 'a', qmp: 
bool = False):
 
         assert self._pid == self._p.pid
 
-    def qmp(self, cmd: str, args: Optional[Dict[str, object]] = None) \
+    def qmp(self, cmd: str, args: Optional[dict[str, object]] = None) \
             -> QMPMessage:
         assert self._qmp is not None
         return self._qmp.cmd_raw(cmd, args)
@@ -466,7 +466,7 @@ def get_qmp(self) -> QEMUMonitorProtocol:
         assert self._qmp is not None
         return self._qmp
 
-    def cmd(self, cmd: str, args: Optional[Dict[str, object]] = None) \
+    def cmd(self, cmd: str, args: Optional[dict[str, object]] = None) \
             -> QMPReturnValue:
         assert self._qmp is not None
         return self._qmp.cmd(cmd, **(args or {}))
@@ -498,7 +498,7 @@ def qemu_nbd(*args):
     '''Run qemu-nbd in daemon mode and return the parent's exit code'''
     return subprocess.call(qemu_nbd_args + ['--fork'] + list(args))
 
-def qemu_nbd_early_pipe(*args: str) -> Tuple[int, str]:
+def qemu_nbd_early_pipe(*args: str) -> tuple[int, str]:
     '''Run qemu-nbd in daemon mode and return both the parent's exit code
        and its output in case of an error'''
     full_args = qemu_nbd_args + ['--fork'] + list(args)
@@ -706,7 +706,7 @@ def filter_qtest(output: str) -> str:
     output = re.sub(r'\n?\[I \+\d+\.\d+\] CLOSED\n?$', '', output)
     return output
 
-Msg = TypeVar('Msg', Dict[str, Any], List[Any], str)
+Msg = TypeVar('Msg', dict[str, Any], list[Any], str)
 
 def log(msg: Msg,
         filters: Iterable[Callable[[Msg], Msg]] = (),
@@ -919,7 +919,7 @@ def add_paused(self):
 
     def hmp(self, command_line: str, use_log: bool = False) -> QMPMessage:
         cmd = 'human-monitor-command'
-        kwargs: Dict[str, Any] = {'command-line': command_line}
+        kwargs: dict[str, Any] = {'command-line': command_line}
         if use_log:
             return self.qmp_log(cmd, **kwargs)
         else:
@@ -1462,7 +1462,7 @@ def verify_quorum():
     if not supports_quorum():
         notrun('quorum support missing')
 
-def has_working_luks() -> Tuple[bool, str]:
+def has_working_luks() -> tuple[bool, str]:
     """
     Check whether our LUKS driver can actually create images
     (this extends to LUKS encryption for qcow2).
@@ -1550,8 +1550,8 @@ def skip_if_unsupported(required_formats=(), 
read_only=False):
     '''Skip Test Decorator
        Runs the test if all the required formats are whitelisted'''
     def skip_test_decorator(func):
-        def func_wrapper(test_case: QMPTestCase, *args: List[Any],
-                         **kwargs: Dict[str, Any]) -> None:
+        def func_wrapper(test_case: QMPTestCase, *args: list[Any],
+                         **kwargs: dict[str, Any]) -> None:
             if callable(required_formats):
                 fmts = required_formats(test_case)
             else:
@@ -1567,13 +1567,13 @@ def func_wrapper(test_case: QMPTestCase, *args: 
List[Any],
     return skip_test_decorator
 
 def skip_for_formats(formats: Sequence[str] = ()) \
-    -> Callable[[Callable[[QMPTestCase, List[Any], Dict[str, Any]], None]],
-                Callable[[QMPTestCase, List[Any], Dict[str, Any]], None]]:
+    -> Callable[[Callable[[QMPTestCase, list[Any], dict[str, Any]], None]],
+                Callable[[QMPTestCase, list[Any], dict[str, Any]], None]]:
     '''Skip Test Decorator
        Skips the test for the given formats'''
     def skip_test_decorator(func):
-        def func_wrapper(test_case: QMPTestCase, *args: List[Any],
-                         **kwargs: Dict[str, Any]) -> None:
+        def func_wrapper(test_case: QMPTestCase, *args: list[Any],
+                         **kwargs: dict[str, Any]) -> None:
             if imgfmt in formats:
                 msg = f'{test_case}: Skipped for format {imgfmt}'
                 test_case.case_skip(msg)
@@ -1625,7 +1625,7 @@ class ReproducibleTestRunner(unittest.TextTestRunner):
     def __init__(
         self,
         stream: Optional[TextIO] = None,
-        resultclass: Type[unittest.TextTestResult] =
+        resultclass: type[unittest.TextTestResult] =
         ReproducibleTestResult,
         **kwargs: Any
     ) -> None:
@@ -1635,7 +1635,7 @@ def __init__(
                          resultclass=resultclass,
                          **kwargs)
 
-def execute_unittest(argv: List[str], debug: bool = False) -> None:
+def execute_unittest(argv: list[str], debug: bool = False) -> None:
     """Executes unittests within the calling module."""
 
     # Some tests have warnings, especially ResourceWarnings for unclosed
diff --git a/tests/qemu-iotests/linters.py b/tests/qemu-iotests/linters.py
index 9fb3fd14497..21b26bff298 100644
--- a/tests/qemu-iotests/linters.py
+++ b/tests/qemu-iotests/linters.py
@@ -17,7 +17,7 @@
 import re
 import subprocess
 import sys
-from typing import List, Mapping, Optional
+from typing import Mapping, Optional
 
 
 # TODO: Empty this list!
@@ -49,7 +49,7 @@ def is_python_file(filename):
             return False
 
 
-def get_test_files() -> List[str]:
+def get_test_files() -> list[str]:
     named_tests = [f'tests/{entry}' for entry in os.listdir('tests')]
     check_tests = set(os.listdir('.') + named_tests) - set(SKIP_FILES)
     return list(filter(is_python_file, check_tests))
@@ -57,7 +57,7 @@ def get_test_files() -> List[str]:
 
 def run_linter(
         tool: str,
-        args: List[str],
+        args: list[str],
         env: Optional[Mapping[str, str]] = None,
         suppress_output: bool = False,
 ) -> None:
diff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py
index 6326e46b7b1..3c0d5027594 100644
--- a/tests/qemu-iotests/testenv.py
+++ b/tests/qemu-iotests/testenv.py
@@ -25,7 +25,7 @@
 import random
 import subprocess
 import glob
-from typing import List, Dict, Any, Optional
+from typing import Any, Optional
 
 if sys.version_info >= (3, 9):
     from contextlib import AbstractContextManager as ContextManager
@@ -81,7 +81,7 @@ class TestEnv(ContextManager['TestEnv']):
                      'IMGKEYSECRET', 'QEMU_DEFAULT_MACHINE', 'MALLOC_PERTURB_',
                      'GDB_OPTIONS', 'PRINT_QEMU']
 
-    def prepare_subprocess(self, args: List[str]) -> Dict[str, str]:
+    def prepare_subprocess(self, args: list[str]) -> dict[str, str]:
         if self.debug:
             args.append('-d')
 
@@ -96,7 +96,7 @@ def prepare_subprocess(self, args: List[str]) -> Dict[str, 
str]:
         os_env.update(self.get_env())
         return os_env
 
-    def get_env(self) -> Dict[str, str]:
+    def get_env(self) -> dict[str, str]:
         env = {}
         for v in self.env_variables:
             val = getattr(self, v.lower(), None)
diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py
index 2e236c8fa39..d4e5c4c7ff9 100644
--- a/tests/qemu-iotests/testrunner.py
+++ b/tests/qemu-iotests/testrunner.py
@@ -27,7 +27,7 @@
 import shutil
 import sys
 from multiprocessing import Pool
-from typing import List, Optional, Any, Sequence, Dict
+from typing import Optional, Any, Sequence
 from testenv import TestEnv
 
 if sys.version_info >= (3, 9):
@@ -43,7 +43,7 @@ def silent_unlink(path: Path) -> None:
         pass
 
 
-def file_diff(file1: str, file2: str) -> List[str]:
+def file_diff(file1: str, file2: str) -> list[str]:
     with open(file1, encoding="utf-8") as f1, \
          open(file2, encoding="utf-8") as f2:
         # We want to ignore spaces at line ends. There are a lot of mess about
@@ -66,7 +66,7 @@ class LastElapsedTime(ContextManager['LastElapsedTime']):
     def __init__(self, cache_file: str, env: TestEnv) -> None:
         self.env = env
         self.cache_file = cache_file
-        self.cache: Dict[str, Dict[str, Dict[str, float]]]
+        self.cache: dict[str, dict[str, dict[str, float]]]
 
         try:
             with open(cache_file, encoding="utf-8") as f:
@@ -122,8 +122,8 @@ def proc_run_test(test: str, test_field_width: int) -> 
TestResult:
         assert runner is not None
         return runner.run_test(test, test_field_width, mp=True)
 
-    def run_tests_pool(self, tests: List[str],
-                       test_field_width: int, jobs: int) -> List[TestResult]:
+    def run_tests_pool(self, tests: list[str],
+                       test_field_width: int, jobs: int) -> list[TestResult]:
 
         # passing self directly to Pool.starmap() just doesn't work, because
         # it's a context manager.
@@ -369,7 +369,7 @@ def run_test(self, test: str,
         sys.stdout.flush()
         return res
 
-    def run_tests(self, tests: List[str], jobs: int = 1) -> bool:
+    def run_tests(self, tests: list[str], jobs: int = 1) -> bool:
         n_run = 0
         failed = []
         notrun = []
diff --git a/tests/qemu-iotests/tests/stream-under-throttle 
b/tests/qemu-iotests/tests/stream-under-throttle
index 1a50b682fc4..84627fe3ef5 100755
--- a/tests/qemu-iotests/tests/stream-under-throttle
+++ b/tests/qemu-iotests/tests/stream-under-throttle
@@ -21,7 +21,6 @@
 
 import asyncio
 import os
-from typing import List
 import iotests
 from iotests import qemu_img_create, qemu_io
 
@@ -39,7 +38,7 @@ class TcgVM(iotests.VM):
     the order they appear.
     '''
     @property
-    def _base_args(self) -> List[str]:
+    def _base_args(self) -> list[str]:
         # Put -accel tcg first so it takes precedence
         return ['-accel', 'tcg'] + super()._base_args
 
-- 
2.48.1


Reply via email to