From 89ca2f7fea7dc0378b55591489606253fae54679 Mon Sep 17 00:00:00 2001 From: anujsingh-cse Date: Wed, 23 Sep 2026 09:24:53 +0530 Subject: [PATCH 1/4] chore: add type annotations to vmware imc config_file Removing cloudinit.sources.helpers.vmware.imc.config_file and tests.unittests.sources.vmware.test_vmware_config_file from the mypy override list in pyproject.toml surfaces six errors. config_file.py: the standard configparser idiom config.optionxform = str assigns a class to a method, which mypy flags as both method-assign and assignment; this is intentional (disables option lowercasing) and follows the existing ignore style used in cloudinit/config/schema.py. test_vmware_config_file.py: two assertions chain .get("nameservers").get(...) which mypy sees as union-attr because dict.get returns Optional. Adding the {} default keeps runtime behavior identical when the key is present and makes the Optional case explicit. Refs GH-5445 --- cloudinit/sources/helpers/vmware/imc/config_file.py | 2 +- pyproject.toml | 3 +-- tests/unittests/sources/vmware/test_vmware_config_file.py | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cloudinit/sources/helpers/vmware/imc/config_file.py b/cloudinit/sources/helpers/vmware/imc/config_file.py index ec17cbc736c..c88a6107717 100644 --- a/cloudinit/sources/helpers/vmware/imc/config_file.py +++ b/cloudinit/sources/helpers/vmware/imc/config_file.py @@ -58,7 +58,7 @@ def _loadConfigFile(self, filename): logger.info("Parsing the config file %s.", filename) config = configparser.ConfigParser() - config.optionxform = str + config.optionxform = str # type: ignore [method-assign, assignment] config.read(filename) self.clear() diff --git a/pyproject.toml b/pyproject.toml index d44c0276d99..c554a5bbaec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ module = [ "cloudinit.sources.DataSourceSmartOS", "cloudinit.sources.helpers.azure", "cloudinit.sources.helpers.openstack", - "cloudinit.sources.helpers.vmware.imc.config_file", + "cloudinit.user_data", "tests.unittests.analyze.test_show", "tests.unittests.config.test_apt_configure_sources_list_v3", "tests.unittests.config.test_apt_source_v1", @@ -116,7 +116,6 @@ module = [ "tests.unittests.sources.test_smartos", "tests.unittests.sources.test_upcloud", "tests.unittests.sources.test_vultr", - "tests.unittests.sources.vmware.test_vmware_config_file", "tests.unittests.test__init__", "tests.unittests.test_apport", "tests.unittests.test_builtin_handlers", diff --git a/tests/unittests/sources/vmware/test_vmware_config_file.py b/tests/unittests/sources/vmware/test_vmware_config_file.py index af10180fc93..5f0419737fa 100644 --- a/tests/unittests/sources/vmware/test_vmware_config_file.py +++ b/tests/unittests/sources/vmware/test_vmware_config_file.py @@ -161,8 +161,8 @@ def test_get_config_nameservers(self): for _, config in ethernets.items(): assert isinstance(config, dict) - name_servers = config.get("nameservers").get("addresses") - dns_suffixes = config.get("nameservers").get("search") + name_servers = config.get("nameservers", {}).get("addresses") + dns_suffixes = config.get("nameservers", {}).get("search") assert ["10.20.145.1", "10.20.145.2"] == name_servers, "dns" assert [ "eng.vmware.com", @@ -185,8 +185,8 @@ def test_get_config_dns_suffixes(self): for _, config in ethernets.items(): assert isinstance(config, dict) - name_servers = config.get("nameservers").get("addresses") - dns_suffixes = config.get("nameservers").get("search") + name_servers = config.get("nameservers", {}).get("addresses") + dns_suffixes = config.get("nameservers", {}).get("search") assert None is name_servers, "dns" assert ["eng.vmware.com"] == dns_suffixes, "suffixes" From e5243b8a8ef04f51afb16e0d2241efa15829d747 Mon Sep 17 00:00:00 2001 From: anujsingh-cse Date: Wed, 30 Sep 2026 15:33:02 +0530 Subject: [PATCH 2/4] docs(vmware): document the optionxform type-ignore Per review: add a comment explaining why the ignore is needed. The assignment is the documented configparser idiom for preserving key case; mypy sees it as assigning a class to a method. Refs GH-5445 --- cloudinit/sources/helpers/vmware/imc/config_file.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cloudinit/sources/helpers/vmware/imc/config_file.py b/cloudinit/sources/helpers/vmware/imc/config_file.py index c88a6107717..a37fc20c7ff 100644 --- a/cloudinit/sources/helpers/vmware/imc/config_file.py +++ b/cloudinit/sources/helpers/vmware/imc/config_file.py @@ -58,6 +58,9 @@ def _loadConfigFile(self, filename): logger.info("Parsing the config file %s.", filename) config = configparser.ConfigParser() + # Assigning the builtin str as the optionxform transform is the + # documented configparser idiom for preserving key case; mypy + # cannot express assigning a class to a method, hence the ignore. config.optionxform = str # type: ignore [method-assign, assignment] config.read(filename) From 8164d279f70c71fab6c0aa306c1243d286e38731 Mon Sep 17 00:00:00 2001 From: anujsingh-cse Date: Sat, 10 Oct 2026 09:12:25 +0530 Subject: [PATCH 3/4] test(azure): parenthesize implicit concatenations for ruff ISC004 #6958 added base64 error-message parameters to test_azure_helper.py with implicitly concatenated strings inside collection literals, which the pinned ruff flags as ISC004. CI for every open PR runs against the merge ref, so this fails check_format across the board. Wrap the two concatenations in parentheses; the string values are unchanged. --- tests/unittests/sources/test_azure_helper.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/unittests/sources/test_azure_helper.py b/tests/unittests/sources/test_azure_helper.py index b72ce830e46..d222bc7f1f3 100644 --- a/tests/unittests/sources/test_azure_helper.py +++ b/tests/unittests/sources/test_azure_helper.py @@ -1562,8 +1562,10 @@ def test_empty_custom_data_passes(self): [ ( "ABCDE", # invalid length - "Invalid base64-encoded string: number of data characters " - "(5) cannot be 1 more than a multiple of 4", + ( + "Invalid base64-encoded string: number of data characters " + "(5) cannot be 1 more than a multiple of 4" + ), ), ( "ab", # incorrect padding @@ -1571,8 +1573,10 @@ def test_empty_custom_data_passes(self): ), ( "not_base64", # bad character stripped away - "Invalid base64-encoded string: number of data characters " - "(9) cannot be 1 more than a multiple of 4", + ( + "Invalid base64-encoded string: number of data characters " + "(9) cannot be 1 more than a multiple of 4" + ), ), ], ) From e1324b04dbf812f9e18a85aca699593443cc3659 Mon Sep 17 00:00:00 2001 From: anujsingh-cse Date: Mon, 26 Oct 2026 14:00:55 +0530 Subject: [PATCH 4/4] chore(vmware): annotate ConfigFile signatures Annotate __init__, _insertKey, _loadConfigFile and get_count_with_prefix so the module's typing coverage is not limited to the optionxform ignore. Also drop the stray cloudinit.user_data exclusion entry, which does not belong to this module. --- cloudinit/sources/helpers/vmware/imc/config_file.py | 8 ++++---- pyproject.toml | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cloudinit/sources/helpers/vmware/imc/config_file.py b/cloudinit/sources/helpers/vmware/imc/config_file.py index a37fc20c7ff..64d3fae0317 100644 --- a/cloudinit/sources/helpers/vmware/imc/config_file.py +++ b/cloudinit/sources/helpers/vmware/imc/config_file.py @@ -16,10 +16,10 @@ class ConfigFile(ConfigSource, dict): """ConfigFile module to load the content from a specified source.""" - def __init__(self, filename): + def __init__(self, filename: str) -> None: self._loadConfigFile(filename) - def _insertKey(self, key, val): + def _insertKey(self, key: str, val: str) -> None: """ Inserts a Key Value pair. @@ -44,7 +44,7 @@ def _insertKey(self, key, val): self[key] = val - def _loadConfigFile(self, filename): + def _loadConfigFile(self, filename: str) -> None: """ Parses properties from the specified config file. @@ -72,7 +72,7 @@ def _loadConfigFile(self, filename): for key, value in config.items(category): self._insertKey(category + "|" + key, value) - def get_count_with_prefix(self, prefix): + def get_count_with_prefix(self, prefix: str) -> int: """ Return the total count of keys that start with the specified prefix. diff --git a/pyproject.toml b/pyproject.toml index c097b4939d5..e93309104af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,6 @@ module = [ "cloudinit.sources.DataSourceSmartOS", "cloudinit.sources.helpers.azure", "cloudinit.sources.helpers.openstack", - "cloudinit.user_data", "tests.unittests.analyze.test_show", "tests.unittests.config.test_apt_configure_sources_list_v3", "tests.unittests.config.test_apt_source_v1",