From 4b0044da38b2a193c317464638089251c627d3e3 Mon Sep 17 00:00:00 2001 From: mulhern Date: Fri, 8 May 2026 22:04:25 -0400 Subject: [PATCH 1/7] Make revision_number a more global option Signed-off-by: mulhern --- misc_scripts/update_introspection_data.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/misc_scripts/update_introspection_data.py b/misc_scripts/update_introspection_data.py index 3bd98cd..cd866ad 100755 --- a/misc_scripts/update_introspection_data.py +++ b/misc_scripts/update_introspection_data.py @@ -337,14 +337,15 @@ def _gen_parser() -> argparse.ArgumentParser: ) ) + parser.add_argument( + "--revision-number", help="D-Bus interface revision number", type=int + ) + subparsers = parser.add_subparsers(title="subcommands") python_parser = subparsers.add_parser( "python", help="Generate introspection data for consumption by Python scripts" ) - python_parser.add_argument( - "--revision-number", help="D-Bus interface revision number", type=int - ) python_parser.set_defaults(func=_python_output) docs_parser = subparsers.add_parser( From f126977c24775478ef6ed8dec356170155437719 Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 11 May 2026 10:57:15 -0400 Subject: [PATCH 2/7] Remove use of Optional, use | None instead It is supported and preferred. Signed-off-by: mulhern --- misc_scripts/update_introspection_data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc_scripts/update_introspection_data.py b/misc_scripts/update_introspection_data.py index cd866ad..b3df14d 100755 --- a/misc_scripts/update_introspection_data.py +++ b/misc_scripts/update_introspection_data.py @@ -22,7 +22,7 @@ import sys import xml.etree.ElementTree as ET from enum import Enum -from typing import List, Mapping, Optional, Sequence +from typing import List, Mapping, Sequence import dbus from dbus.proxies import ProxyObject @@ -166,7 +166,7 @@ def setup_minimal_object_set(bus: dbus.SystemBus) -> dict[ProxyType, ProxyObject def _make_python_spec( - proxies: Mapping[ProxyType, ProxyObject], *, revision_number: Optional[int] = None + proxies: Mapping[ProxyType, ProxyObject], *, revision_number: int | None = None ) -> dict[str, str]: """ Make the introspection spec for python consumption. From 340b725fab7db18283c1e6f218633f3353fd9d3c Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 11 May 2026 11:09:43 -0400 Subject: [PATCH 3/7] Hoist revision extension extraction up a level Signed-off-by: mulhern --- misc_scripts/update_introspection_data.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/misc_scripts/update_introspection_data.py b/misc_scripts/update_introspection_data.py index b3df14d..7c0744b 100755 --- a/misc_scripts/update_introspection_data.py +++ b/misc_scripts/update_introspection_data.py @@ -165,20 +165,26 @@ def setup_minimal_object_set(bus: dbus.SystemBus) -> dict[ProxyType, ProxyObject } +def _get_revision_ext( + manager: ProxyObject, maybe_revision_number: int | None = None +) -> str: + """ + Return revision extension. + """ + return f"r{ + Version(Manager.Properties.Version.Get(manager)).minor + if maybe_revision_number is None + else maybe_revision_number + }" + + def _make_python_spec( proxies: Mapping[ProxyType, ProxyObject], *, revision_number: int | None = None ) -> dict[str, str]: """ Make the introspection spec for python consumption. """ - - revision_number = ( - Version(Manager.Properties.Version.Get(proxies[ProxyType.MANAGER])).minor - if revision_number is None - else revision_number - ) - - revision = f"r{revision_number}" + revision = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) def get_current_interfaces(interface_prefixes: Sequence[str]) -> List[str]: return [f"{prefix}.{revision}" for prefix in interface_prefixes] From 7b6dc1ed8e21fa8f11b3226f5f799fed1b8ea63e Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 11 May 2026 11:41:16 -0400 Subject: [PATCH 4/7] Hoist some method local methods to module-level and generalize them Signed-off-by: mulhern --- misc_scripts/update_introspection_data.py | 94 ++++++++++++++--------- 1 file changed, 58 insertions(+), 36 deletions(-) diff --git a/misc_scripts/update_introspection_data.py b/misc_scripts/update_introspection_data.py index 7c0744b..f0cd23d 100755 --- a/misc_scripts/update_introspection_data.py +++ b/misc_scripts/update_introspection_data.py @@ -22,7 +22,7 @@ import sys import xml.etree.ElementTree as ET from enum import Enum -from typing import List, Mapping, Sequence +from typing import List, Mapping, MutableMapping, Sequence import dbus from dbus.proxies import ProxyObject @@ -178,55 +178,77 @@ def _get_revision_ext( }" +def _get_current_interfaces( + revision_ext: str, interface_prefixes: Sequence[str] +) -> List[str]: + """ + Return a list of interfaces names. + """ + return [f"{prefix}.{revision_ext}" for prefix in interface_prefixes] + + +def _add_data( + specs: MutableMapping[str, str], + proxy_object: ProxyObject, + interfaces: Sequence[str], +): + """ + Introspect on the proxy, get the information for the specified + interfaces, and add it to specs. + + :param proxy: dbus Proxy object + :param list interfaces: list of interesting interface names + :raises: RuntimeError if some interface not found + """ + string_data = Introspectable.Methods.Introspect(proxy_object, {}) + xml_data = ET.fromstring(string_data) + + for interface_name in interfaces: + try: + interface = next( + interface + for interface in xml_data + if interface.attrib["name"] == interface_name + ) + specs[interface_name] = _xml_object_to_str(interface) + except StopIteration as err: + raise RuntimeError( + f"interface {interface_name} not found in introspection data" + ) from err + + def _make_python_spec( proxies: Mapping[ProxyType, ProxyObject], *, revision_number: int | None = None ) -> dict[str, str]: """ Make the introspection spec for python consumption. """ - revision = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) - - def get_current_interfaces(interface_prefixes: Sequence[str]) -> List[str]: - return [f"{prefix}.{revision}" for prefix in interface_prefixes] + revision_ext = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) specs = {} - def _add_data(proxy_key: ProxyType, interfaces: Sequence[str]): - """ - Introspect on the proxy, get the information for the specified - interfaces, and add it to specs. + _add_data(specs, proxies[ProxyType.MANAGER], [OBJECT_MANAGER_INTERFACE]) - :param proxy: dbus Proxy object - :param list interfaces: list of interesting interface names - :raises: RuntimeError if some interface not found - """ - string_data = Introspectable.Methods.Introspect(proxies[proxy_key], {}) - xml_data = ET.fromstring(string_data) - - for interface_name in interfaces: - try: - interface = next( - interface - for interface in xml_data - if interface.attrib["name"] == interface_name - ) - specs[interface_name] = _xml_object_to_str(interface) - except StopIteration as err: - raise RuntimeError( - f"interface {interface_name} not found in introspection data" - ) from err - - _add_data(ProxyType.MANAGER, [OBJECT_MANAGER_INTERFACE]) - - _add_data(ProxyType.MANAGER, get_current_interfaces(TOP_OBJECT_INTERFACE_PREFIXES)) - _add_data(ProxyType.POOL, get_current_interfaces(POOL_OBJECT_INTERFACE_PREFIXES)) + _add_data( + specs, + proxies[ProxyType.MANAGER], + _get_current_interfaces(revision_ext, TOP_OBJECT_INTERFACE_PREFIXES), + ) + _add_data( + specs, + proxies[ProxyType.POOL], + _get_current_interfaces(revision_ext, POOL_OBJECT_INTERFACE_PREFIXES), + ) _add_data( - ProxyType.BLOCKDEV, get_current_interfaces(BLOCKDEV_OBJECT_INTERFACE_PREFIXES) + specs, + proxies[ProxyType.BLOCKDEV], + _get_current_interfaces(revision_ext, BLOCKDEV_OBJECT_INTERFACE_PREFIXES), ) _add_data( - ProxyType.FILESYSTEM, - get_current_interfaces(FILESYSTEM_OBJECT_INTERFACE_PREFIXES), + specs, + proxies[ProxyType.FILESYSTEM], + _get_current_interfaces(revision_ext, FILESYSTEM_OBJECT_INTERFACE_PREFIXES), ) return specs From 797d65a7320a91a01b89a3a8d3bc8a2e0072fe5c Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 11 May 2026 13:05:09 -0400 Subject: [PATCH 5/7] Rewrite docs generation to make it more convenient Signed-off-by: mulhern --- misc_scripts/update_introspection_data.py | 88 ++++++++--------------- 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/misc_scripts/update_introspection_data.py b/misc_scripts/update_introspection_data.py index f0cd23d..7154169 100755 --- a/misc_scripts/update_introspection_data.py +++ b/misc_scripts/update_introspection_data.py @@ -282,62 +282,56 @@ def _python_output(namespace: argparse.Namespace): _print_python_spec(specs) -def _make_docs_spec(proxies: Mapping[ProxyType, ProxyObject]) -> dict[ProxyType, str]: +def _make_docs_spec( + proxies: Mapping[ProxyType, ProxyObject], revision_number: int | None +) -> dict[str, str]: """ Make the introspection spec for use in docs repo. """ - + revision_ext = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) specs = {} - def _add_data(proxy_key: ProxyType): - """ - Get the introspection data, and add it to the spec. - - :param proxy_key: key for proxies - """ - string_data = Introspectable.Methods.Introspect(proxies[proxy_key], {}) - specs[proxy_key] = _xml_object_to_str(ET.fromstring(string_data)) - - _add_data(ProxyType.MANAGER) - _add_data(ProxyType.POOL) - _add_data(ProxyType.BLOCKDEV) - _add_data(ProxyType.FILESYSTEM) + _add_data( + specs, + proxies[ProxyType.MANAGER], + _get_current_interfaces(revision_ext, TOP_OBJECT_INTERFACE_PREFIXES), + ) + _add_data( + specs, + proxies[ProxyType.POOL], + _get_current_interfaces(revision_ext, POOL_OBJECT_INTERFACE_PREFIXES), + ) + _add_data( + specs, + proxies[ProxyType.BLOCKDEV], + _get_current_interfaces(revision_ext, BLOCKDEV_OBJECT_INTERFACE_PREFIXES), + ) + _add_data( + specs, + proxies[ProxyType.FILESYSTEM], + _get_current_interfaces(revision_ext, FILESYSTEM_OBJECT_INTERFACE_PREFIXES), + ) return specs -def _print_docs_spec(specs: Mapping[ProxyType, str], namespace: argparse.Namespace): +def _print_docs_spec(specs: Mapping[str, str], namespace: argparse.Namespace): """ Print spec for inclusion on docs website. :param specs: the specification to print - :type specs: dict of ProxyType * XML object + :type specs: dict of str * str :param namespace: the namespace parsed from the command-line arguments """ - def _proxy_type_to_filename(proxy_type: ProxyType) -> str: - """ - Return filename for proxy type. - """ - if proxy_type == ProxyType.MANAGER: - return namespace.manager_file_name - if proxy_type == ProxyType.POOL: - return namespace.pool_file_name - if proxy_type == ProxyType.FILESYSTEM: - return namespace.filesystem_file_name - if proxy_type == ProxyType.BLOCKDEV: - return namespace.blockdev_file_name - - assert False, "unreachable" - abs_output_dir = os.path.abspath(namespace.output_dir) try: os.mkdir(abs_output_dir) except FileExistsError as err: raise RuntimeError("Cannot create output dir for files") from err - for proxy_type, introspection_data in specs.items(): - file_path = os.path.join(abs_output_dir, _proxy_type_to_filename(proxy_type)) + for interface_name, introspection_data in specs.items(): + file_path = os.path.join(abs_output_dir, f"{interface_name}.xml") with open(file_path, "w", encoding="utf-8") as file: print(introspection_data, file=file) @@ -348,7 +342,7 @@ def _docs_output(namespace: argparse.Namespace): """ bus = dbus.SystemBus() proxies = setup_minimal_object_set(bus) - specs = _make_docs_spec(proxies) + specs = _make_docs_spec(proxies, revision_number=namespace.revision_number) _print_docs_spec(specs, namespace) @@ -380,30 +374,6 @@ def _gen_parser() -> argparse.ArgumentParser: "docs", help="Generate introspection data for consumption by website docs" ) docs_parser.add_argument("output_dir", help="directory for output files") - docs_parser.add_argument( - "--manager-file-name", - dest="manager_file_name", - default="manager.xml", - help="filename for manager object introspection data", - ) - docs_parser.add_argument( - "--pool-file-name", - dest="pool_file_name", - default="pool.xml", - help="filename for pool object introspection data", - ) - docs_parser.add_argument( - "--filesystem-file-name", - dest="filesystem_file_name", - default="filesystem.xml", - help="filename for filesystem object introspection data", - ) - docs_parser.add_argument( - "--blockdev-file-name", - dest="blockdev_file_name", - default="blockdev.xml", - help="filename for blockdev object introspection data", - ) docs_parser.set_defaults(func=_docs_output) parser.set_defaults(func=lambda _: parser.error("missing sub-command")) From 4e2cc2e50d05888d44705bd93b0dda2d23559580 Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 11 May 2026 13:46:54 -0400 Subject: [PATCH 6/7] Refactor to add a method to just make Stratis specs Signed-off-by: mulhern --- misc_scripts/update_introspection_data.py | 53 +++++++++-------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/misc_scripts/update_introspection_data.py b/misc_scripts/update_introspection_data.py index 7154169..99f326a 100755 --- a/misc_scripts/update_introspection_data.py +++ b/misc_scripts/update_introspection_data.py @@ -217,18 +217,14 @@ def _add_data( ) from err -def _make_python_spec( - proxies: Mapping[ProxyType, ProxyObject], *, revision_number: int | None = None -) -> dict[str, str]: +def _add_stratis_specs( + specs: MutableMapping[str, str], + proxies: Mapping[ProxyType, ProxyObject], + revision_ext: str, +): """ - Make the introspection spec for python consumption. + Add specs for Stratis interfaces. """ - revision_ext = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) - - specs = {} - - _add_data(specs, proxies[ProxyType.MANAGER], [OBJECT_MANAGER_INTERFACE]) - _add_data( specs, proxies[ProxyType.MANAGER], @@ -251,6 +247,20 @@ def _make_python_spec( _get_current_interfaces(revision_ext, FILESYSTEM_OBJECT_INTERFACE_PREFIXES), ) + +def _make_python_spec( + proxies: Mapping[ProxyType, ProxyObject], *, revision_number: int | None = None +) -> dict[str, str]: + """ + Make the introspection spec for python consumption. + """ + revision_ext = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) + + specs = {} + + _add_data(specs, proxies[ProxyType.MANAGER], [OBJECT_MANAGER_INTERFACE]) + _add_stratis_specs(specs, proxies, revision_ext) + return specs @@ -290,28 +300,7 @@ def _make_docs_spec( """ revision_ext = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) specs = {} - - _add_data( - specs, - proxies[ProxyType.MANAGER], - _get_current_interfaces(revision_ext, TOP_OBJECT_INTERFACE_PREFIXES), - ) - _add_data( - specs, - proxies[ProxyType.POOL], - _get_current_interfaces(revision_ext, POOL_OBJECT_INTERFACE_PREFIXES), - ) - - _add_data( - specs, - proxies[ProxyType.BLOCKDEV], - _get_current_interfaces(revision_ext, BLOCKDEV_OBJECT_INTERFACE_PREFIXES), - ) - _add_data( - specs, - proxies[ProxyType.FILESYSTEM], - _get_current_interfaces(revision_ext, FILESYSTEM_OBJECT_INTERFACE_PREFIXES), - ) + _add_stratis_specs(specs, proxies, revision_ext) return specs From 714242f860e50a7b83d9bd77f67613f369a0ce49 Mon Sep 17 00:00:00 2001 From: mulhern Date: Mon, 11 May 2026 13:52:55 -0400 Subject: [PATCH 7/7] Specify type of literal dict Signed-off-by: mulhern --- misc_scripts/update_introspection_data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/misc_scripts/update_introspection_data.py b/misc_scripts/update_introspection_data.py index 99f326a..d83899a 100755 --- a/misc_scripts/update_introspection_data.py +++ b/misc_scripts/update_introspection_data.py @@ -256,7 +256,7 @@ def _make_python_spec( """ revision_ext = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) - specs = {} + specs: dict[str, str] = {} _add_data(specs, proxies[ProxyType.MANAGER], [OBJECT_MANAGER_INTERFACE]) _add_stratis_specs(specs, proxies, revision_ext) @@ -299,7 +299,7 @@ def _make_docs_spec( Make the introspection spec for use in docs repo. """ revision_ext = _get_revision_ext(proxies[ProxyType.MANAGER], revision_number) - specs = {} + specs: dict[str, str] = {} _add_stratis_specs(specs, proxies, revision_ext) return specs