From 67dd75e1a8d73e36da6400b9218b8b879c66b24f Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:12:46 +0530 Subject: [PATCH 01/20] typing: fix mypy annotation errors in test_apt_configure_sources_list_v3 Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - .../config/test_apt_configure_sources_list_v3.py | 15 ++++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0972e89a336..bae7b30beb0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_apt_configure_sources_list_v3", "tests.unittests.config.test_apt_source_v1", "tests.unittests.config.test_cc_apt_pipelining", "tests.unittests.config.test_cc_chef", diff --git a/tests/unittests/config/test_apt_configure_sources_list_v3.py b/tests/unittests/config/test_apt_configure_sources_list_v3.py index 30a4d9ac48b..354de9508f9 100644 --- a/tests/unittests/config/test_apt_configure_sources_list_v3.py +++ b/tests/unittests/config/test_apt_configure_sources_list_v3.py @@ -6,6 +6,7 @@ """ import stat +from typing import Any import pytest @@ -238,7 +239,7 @@ def test_apt_v3_empty_cfg_source_list_by_distro( "_should_configure_on_empty_apt", return_value=SubpResult(True, "test"), ) - cc_apt_configure.handle("test", {"apt": {}}, mycloud, None) + cc_apt_configure.handle("test", {"apt": {}}, mycloud, []) sources_file = tmpdir.join(f"/etc/apt/sources.list.d/{distro}.sources") if template_present: @@ -257,13 +258,13 @@ def test_apt_v3_empty_cfg_source_list_by_distro( def test_apt_v3_source_list_ubuntu_snappy(self, mocker): """test_apt_v3_source_list_ubuntu_snappy - without custom sources or params""" - cfg = {"apt": {}} + cfg: dict = {"apt": {}} mycloud = get_cloud() mock_writefile = mocker.patch.object(util, "write_file") mock_issnappy = mocker.patch.object(util, "system_is_snappy") mock_issnappy.return_value = True - cc_apt_configure.handle("test", cfg, mycloud, None) + cc_apt_configure.handle("test", cfg, mycloud, []) mock_writefile.assert_not_called() assert 1 == mock_issnappy.call_count @@ -315,7 +316,7 @@ def test_apt_v3_source_list_psm_deb822_feature_aware( util.write_file(tmpl_file, tmpl_content) mycloud = get_cloud("ubuntu") - cc_apt_configure.handle("test", {"apt": cfg}, mycloud, None) + cc_apt_configure.handle("test", {"apt": cfg}, mycloud, []) sources_file = tmpdir.join(apt_file) assert expected == sources_file.read() @@ -369,7 +370,7 @@ def test_apt_v3_srcl_custom_deb822_feature_aware( cc_apt_configure.features, "APT_DEB822_SOURCE_LIST_FILE", deb822 ) mocker.patch.object(Distro, "get_primary_arch", return_value="amd64") - cc_apt_configure.handle("notimportant", cfg, mycloud, None) + cc_apt_configure.handle("notimportant", cfg, mycloud, []) sources_file = tmpdir.join(apt_file) assert expected == sources_file.read() assert 0o644 == stat.S_IMODE(sources_file.stat().mode) @@ -428,7 +429,7 @@ def test_apt_v3_srcl_deb822_custom_psm_keys( util.write_file(tmpl_file, tmpl_content) # Base config - cfg = { + cfg: dict[str, Any] = { "preserve_sources_list": False, "primary": [{"arches": ["default"], "uri": pm}], } @@ -442,7 +443,7 @@ def test_apt_v3_srcl_deb822_custom_psm_keys( cfg["security"][0]["key"] = smkey mycloud = get_cloud(distro) - cc_apt_configure.handle("test", {"apt": cfg}, mycloud, None) + cc_apt_configure.handle("test", {"apt": cfg}, mycloud, []) apt_file = f"/etc/apt/sources.list.d/{distro}.sources" sources_file = tmpdir.join(apt_file) From fb92212c82be18dbd491bb92968e89bdec33eae1 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:13:59 +0530 Subject: [PATCH 02/20] typing: fix mypy annotation errors in test_apt_source_v1 Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_apt_source_v1.py | 11 ++++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bae7b30beb0..a0a9787f8ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_apt_source_v1", "tests.unittests.config.test_cc_apt_pipelining", "tests.unittests.config.test_cc_chef", "tests.unittests.config.test_cc_final_message", diff --git a/tests/unittests/config/test_apt_source_v1.py b/tests/unittests/config/test_apt_source_v1.py index c3729dc4fc9..a84717910bb 100644 --- a/tests/unittests/config/test_apt_source_v1.py +++ b/tests/unittests/config/test_apt_source_v1.py @@ -11,6 +11,7 @@ import re from functools import partial from textwrap import dedent +from typing import Any from unittest import mock from unittest.mock import call @@ -844,7 +845,7 @@ def test_convert_to_new_format_dict_collision(self, apt_lists, m_gpg): }, } cfg_3_only = {"apt": {"sources": fullv3}} - cfg_1_and_3 = {"apt_sources": [cfg1, cfg2, cfg3]} + cfg_1_and_3: dict[str, Any] = {"apt_sources": [cfg1, cfg2, cfg3]} cfg_1_and_3.update(cfg_3_only) # collision (equal, so ok to remove) @@ -869,7 +870,9 @@ def test_convert_to_new_format_dict_collision(self, apt_lists, m_gpg): }, } cfg_3_only = {"apt": {"sources": diff}} - cfg_1_and_3_different = {"apt_sources": [cfg1, cfg2, cfg3]} + cfg_1_and_3_different: dict[str, Any] = { + "apt_sources": [cfg1, cfg2, cfg3] + } cfg_1_and_3_different.update(cfg_3_only) # collision (unequal by dict having a different entry) @@ -883,7 +886,9 @@ def test_convert_to_new_format_dict_collision(self, apt_lists, m_gpg): } } cfg_3_only = {"apt": {"sources": missing}} - cfg_1_and_3_missing = {"apt_sources": [cfg1, cfg2, cfg3]} + cfg_1_and_3_missing: dict[str, Any] = { + "apt_sources": [cfg1, cfg2, cfg3] + } cfg_1_and_3_missing.update(cfg_3_only) # collision (unequal by dict missing an entry) with pytest.raises(ValueError): From 79d2efb7c8f50ae163fa18ea316460ea26a52d81 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:14:13 +0530 Subject: [PATCH 03/20] typing: fix mypy annotation errors in test_cc_apt_pipelining Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_apt_pipelining.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a0a9787f8ed..3f28968a589 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_apt_pipelining", "tests.unittests.config.test_cc_chef", "tests.unittests.config.test_cc_final_message", "tests.unittests.config.test_cc_growpart", diff --git a/tests/unittests/config/test_cc_apt_pipelining.py b/tests/unittests/config/test_cc_apt_pipelining.py index 6fb2926aa31..ffd9053399e 100644 --- a/tests/unittests/config/test_cc_apt_pipelining.py +++ b/tests/unittests/config/test_cc_apt_pipelining.py @@ -20,14 +20,14 @@ class TestAptPipelining: @mock.patch("cloudinit.config.cc_apt_pipelining.util.write_file") def test_not_disabled_by_default(self, m_write_file): """ensure that default behaviour is to not disable pipelining""" - cc_apt_pipelining.handle("foo", {}, None, None) + cc_apt_pipelining.handle("foo", {}, mock.Mock(), []) assert 0 == m_write_file.call_count @mock.patch("cloudinit.config.cc_apt_pipelining.util.write_file") def test_false_disables_pipelining(self, m_write_file): """ensure that pipelining can be disabled with correct config""" cc_apt_pipelining.handle( - "foo", {"apt_pipelining": "false"}, None, None + "foo", {"apt_pipelining": "false"}, mock.Mock(), [] ) assert 1 == m_write_file.call_count args, _ = m_write_file.call_args From 0a74f669e8b426d27dc2ad4366935bdcb5c9a79b Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:14:24 +0530 Subject: [PATCH 04/20] typing: fix mypy annotation errors in test_cc_chef Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_chef.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3f28968a589..17570a7f13a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_chef", "tests.unittests.config.test_cc_final_message", "tests.unittests.config.test_cc_growpart", "tests.unittests.config.test_cc_install_hotplug", diff --git a/tests/unittests/config/test_cc_chef.py b/tests/unittests/config/test_cc_chef.py index c4e669518b4..8b6eafab32b 100644 --- a/tests/unittests/config/test_cc_chef.py +++ b/tests/unittests/config/test_cc_chef.py @@ -122,7 +122,7 @@ class TestChef: def test_no_config(self): """No chef directories are created on when no chef config provided""" - cfg = {} + cfg: dict = {} cc_chef.handle("chef", cfg, get_cloud(), []) for d in cc_chef.CHEF_DIRS: assert not os.path.isdir(d) @@ -180,11 +180,11 @@ def test_basic_config(self): if k in unrendered_keys: continue assert v in c - for k, v in cc_chef.CHEF_RB_TPL_DEFAULTS.items(): + for k, default_v in cc_chef.CHEF_RB_TPL_DEFAULTS.items(): if k in unrendered_keys: continue # the value from the cfg overrides that in the default - val = cfg["chef"].get(k, v) + val = cfg["chef"].get(k, default_v) if isinstance(val, str): assert val in c c = util.load_text_file(cc_chef.CHEF_FB_PATH) From 5ee27499307f6bfc940564aaf2ef4ebb2186f88a Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:14:35 +0530 Subject: [PATCH 05/20] typing: fix mypy annotation errors in test_cc_final_message Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_final_message.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 17570a7f13a..5b75fcc2a00 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_final_message", "tests.unittests.config.test_cc_growpart", "tests.unittests.config.test_cc_install_hotplug", "tests.unittests.config.test_cc_keys_to_console", diff --git a/tests/unittests/config/test_cc_final_message.py b/tests/unittests/config/test_cc_final_message.py index e612e3dad52..cd5a67b03b0 100644 --- a/tests/unittests/config/test_cc_final_message.py +++ b/tests/unittests/config/test_cc_final_message.py @@ -35,7 +35,7 @@ def test_boot_finished_written( boot_finished = instance_dir / "boot-finished" m_cloud = get_cloud(paths=paths) - handle(None, {}, m_cloud, []) + handle("", {}, m_cloud, []) # We should not change the status of the instance directory assert instance_dir_exists == instance_dir.exists() @@ -69,7 +69,7 @@ def test_only_warn_when_datasourcenone_is_fallback_in_datasource_list( m_cloud.datasource.dsname = dsname Path(paths.get_ipath_cur()).mkdir() with caplog.at_level(log_level): - handle(None, {}, m_cloud, []) + handle("", {}, m_cloud, []) # We should not change the status of the instance directory if expected_log: From 19d9236e852779c4da3cfa85668f34033bcb5a41 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:16:48 +0530 Subject: [PATCH 06/20] typing: fix mypy annotation errors in test_cc_growpart Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_growpart.py | 25 +++++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5b75fcc2a00..aa0ca3c81fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_growpart", "tests.unittests.config.test_cc_install_hotplug", "tests.unittests.config.test_cc_keys_to_console", "tests.unittests.config.test_cc_puppet", diff --git a/tests/unittests/config/test_cc_growpart.py b/tests/unittests/config/test_cc_growpart.py index 6f22673945e..e1f15639aed 100644 --- a/tests/unittests/config/test_cc_growpart.py +++ b/tests/unittests/config/test_cc_growpart.py @@ -110,7 +110,7 @@ def test_mode_off(mocker): cc_growpart.handle( name="growpart", cfg=config, - cloud=None, + cloud=mock.Mock(), args=[], ) mock_resizer.assert_not_called() @@ -127,11 +127,11 @@ def freebsd_cloud(mocker): distro = cls("freebsd", {}, None) cloud_obj = cloud.Cloud( - None, - None, + mock.Mock(), + mock.Mock(), {}, distro, - None, + mock.Mock(), ) return cloud_obj @@ -333,7 +333,13 @@ def test_simple_devices(self, mocker): ) resize_calls = [] - class myresizer: + class myresizer(cc_growpart.Resizer): + def __init__(self): + pass + + def available(self, devices: list) -> bool: + return True + def resize(self, diskdev, partnum, partdev, fs): resize_calls.append((diskdev, partnum, partdev, fs)) if partdev == "/dev/YYda2": @@ -518,8 +524,11 @@ def common_mocks(self, mocker): # when needed self.distro = MockDistro() - original_device_part_info = self.distro.device_part_info - self.distro.device_part_info = self._device_part_info_side_effect + mocker.patch.object( + self.distro, + "device_part_info", + side_effect=self._device_part_info_side_effect, + ) mocker.patch("os.stat") mocker.patch("stat.S_ISBLK") mocker.patch("stat.S_ISCHR") @@ -553,7 +562,7 @@ def common_mocks(self, mocker): self.resizer = mock.Mock() self.resizer.resize = mock.Mock(return_value=(1024, 1024)) yield - self.distro.device_part_info = original_device_part_info + # device_part_info is restored automatically by mocker def test_resize_when_encrypted(self, common_mocks, caplog): info = cc_growpart.resize_devices( From c87c1ea97496cb270c0797867a200515ec98f296 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:29:00 +0530 Subject: [PATCH 07/20] typing: fix mypy annotation errors in test_cc_install_hotplug Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - .../config/test_cc_install_hotplug.py | 30 +++++++++---------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index aa0ca3c81fa..5fcd2048a52 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_install_hotplug", "tests.unittests.config.test_cc_keys_to_console", "tests.unittests.config.test_cc_puppet", "tests.unittests.config.test_cc_resizefs", diff --git a/tests/unittests/config/test_cc_install_hotplug.py b/tests/unittests/config/test_cc_install_hotplug.py index d34d95b0092..fa6fba855ce 100644 --- a/tests/unittests/config/test_cc_install_hotplug.py +++ b/tests/unittests/config/test_cc_install_hotplug.py @@ -1,5 +1,5 @@ # This file is part of cloud-init. See LICENSE file for license information. -from collections import namedtuple +from types import SimpleNamespace from unittest import mock import pytest @@ -22,15 +22,13 @@ def mocks(): m_which = mock.patch("cloudinit.subp.which", return_value=None) m_path_exists = mock.patch("os.path.exists", return_value=False) - yield namedtuple( - "Mocks", "m_update_enabled m_write m_del m_subp m_which m_path_exists" - )( - m_update_enabled.start(), - m_write.start(), - m_del.start(), - m_subp.start(), - m_which.start(), - m_path_exists.start(), + yield SimpleNamespace( + m_update_enabled=m_update_enabled.start(), + m_write=m_write.start(), + m_del=m_del.start(), + m_subp=m_subp.start(), + m_which=m_which.start(), + m_path_exists=m_path_exists.start(), ) m_update_enabled.stop() @@ -59,7 +57,7 @@ def test_rules_installed_when_supported_and_enabled( else: libexecdir = "/usr/lib/cloud-init" with mock.patch("os.path.exists", return_value=libexec_exists): - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) mocks.m_write.assert_called_once_with( filename=HOTPLUG_UDEV_PATH, content=HOTPLUG_UDEV_RULES_TEMPLATE.format( @@ -82,7 +80,7 @@ def test_rules_not_installed_when_unsupported(self, mocks): m_cloud = mock.MagicMock() m_cloud.datasource.get_supported_events.return_value = {} - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) assert mocks.m_write.call_args_list == [] assert mocks.m_del.call_args_list == [] assert mocks.m_subp.call_args_list == [] @@ -94,7 +92,7 @@ def test_rules_not_installed_when_disabled(self, mocks): EventScope.NETWORK: {EventType.HOTPLUG} } - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) assert mocks.m_write.call_args_list == [] assert mocks.m_del.call_args_list == [] assert mocks.m_subp.call_args_list == [] @@ -105,7 +103,7 @@ def test_rules_uninstalled_when_disabled(self, mocks): m_cloud = mock.MagicMock() m_cloud.datasource.get_supported_events.return_value = {} - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) mocks.m_del.assert_called_with(HOTPLUG_UDEV_PATH) assert mocks.m_subp.call_args_list == [ mock.call( @@ -125,7 +123,7 @@ def test_rules_not_installed_when_no_udevadm(self, mocks): EventScope.NETWORK: {EventType.HOTPLUG} } - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) assert mocks.m_del.call_args_list == [] assert mocks.m_write.call_args_list == [] assert mocks.m_subp.call_args_list == [] @@ -142,7 +140,7 @@ def test_rules_installed_on_ec2(self, mocks): ) with mock.patch("os.path.exists", return_value=True): - handle(None, {}, m_cloud, None) + handle("", {}, m_cloud, []) udev_rules = """\ # Installed by cloud-init due to network hotplug userdata From 4b4e018724b01ae0e9bbe1a9db253d6756827808 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Sun, 30 Aug 2026 20:21:40 +0530 Subject: [PATCH 08/20] typing: fix mypy annotation errors in test_cc_keys_to_console Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_keys_to_console.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5fcd2048a52..3b80ed62b06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_keys_to_console", "tests.unittests.config.test_cc_puppet", "tests.unittests.config.test_cc_resizefs", "tests.unittests.config.test_cc_resolv_conf", diff --git a/tests/unittests/config/test_cc_keys_to_console.py b/tests/unittests/config/test_cc_keys_to_console.py index 28296d09b47..28ce2b2dde6 100644 --- a/tests/unittests/config/test_cc_keys_to_console.py +++ b/tests/unittests/config/test_cc_keys_to_console.py @@ -43,7 +43,7 @@ def test_emit_keys_to_console_config( m_path_exists.return_value = True m_subp.return_value = ("", "") - cc_keys_to_console.handle("name", cfg, mock.Mock(), ()) + cc_keys_to_console.handle("name", cfg, mock.Mock(), []) assert subp_called == (m_subp.call_count == 1) From da208dfd941ad2db89e377318a7bf3bf5c7715d0 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:17:40 +0530 Subject: [PATCH 09/20] typing: fix mypy annotation errors in test_cc_puppet Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_puppet.py | 48 ++++++++++++------------ 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3b80ed62b06..df36e31b5eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_puppet", "tests.unittests.config.test_cc_resizefs", "tests.unittests.config.test_cc_resolv_conf", "tests.unittests.config.test_cc_rh_subscription", diff --git a/tests/unittests/config/test_cc_puppet.py b/tests/unittests/config/test_cc_puppet.py index 166a7fe0e29..33a96478f10 100644 --- a/tests/unittests/config/test_cc_puppet.py +++ b/tests/unittests/config/test_cc_puppet.py @@ -84,8 +84,8 @@ def test_skips_missing_puppet_key_in_cloudconfig( ): """Cloud-config containing no 'puppet' key is skipped.""" - cfg = {} - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cfg: dict = {} + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert "no 'puppet' configuration found" in caplog.text assert 0 == m_man_puppet.call_count @@ -95,7 +95,7 @@ def test_puppet_config_starts_puppet_service(self, m_subp, m_man_puppet): cloud = get_cloud() cfg = {"puppet": {"install": False}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert 2 == m_man_puppet.call_count expected_calls = [ mock.call(cloud, "enable"), @@ -108,8 +108,8 @@ def test_empty_puppet_config_installs_puppet(self, m_subp, m_man_puppet): """Cloud-config empty 'puppet' configuration installs latest puppet.""" cloud = get_cloud() cloud.distro = mock.MagicMock() - cfg = {"puppet": {}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cfg: dict = {"puppet": {}} + cc_puppet.handle("notimportant", cfg, cloud, []) assert [ mock.call(["puppet-agent"]) ] == cloud.distro.install_packages.call_args_list @@ -120,7 +120,7 @@ def test_puppet_config_installs_puppet_on_true(self, m_subp, _): cloud = get_cloud() cloud.distro = mock.MagicMock() cfg = {"puppet": {"install": True}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert [ mock.call(["puppet-agent"]) ] in cloud.distro.install_packages.call_args_list @@ -134,7 +134,7 @@ def test_puppet_config_installs_puppet_aio(self, m_subp, m_aio, _): cloud = get_cloud() cloud.distro = distro cfg = {"puppet": {"install": True, "install_type": "aio"}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, None, None, True ) @@ -156,7 +156,7 @@ def test_puppet_config_installs_puppet_aio_with_version( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, "6.24.0", None, True ) @@ -178,7 +178,7 @@ def test_puppet_config_installs_puppet_aio_with_collection( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, None, "puppet6", True ) @@ -200,7 +200,7 @@ def test_puppet_config_installs_puppet_aio_with_custom_url( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, "http://test.url/path/to/script.sh", None, None, True ) @@ -222,7 +222,7 @@ def test_puppet_config_installs_puppet_aio_without_cleanup( "install_type": "aio", } } - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) m_aio.assert_called_with( distro, cc_puppet.AIO_INSTALL_URL, None, None, False ) @@ -233,7 +233,7 @@ def test_puppet_config_installs_puppet_version(self, m_subp, _): cloud = get_cloud() cloud.distro = mock.MagicMock() cfg = {"puppet": {"version": "3.8"}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert [ mock.call([["puppet-agent", "3.8"]]) ] == cloud.distro.install_packages.call_args_list @@ -251,7 +251,7 @@ def test_puppet_config_updates_puppet_conf(self, m_subp, m_man_puppet): util.write_file(self.CONF, "[agent]\nserver = origpuppet\nother = 3") cloud = get_cloud() cloud.distro = mock.MagicMock() - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) content = util.load_text_file(self.CONF) expected = "[agent]\nserver = puppetserver.example.org\nother = 3\n\n" assert expected == content @@ -288,7 +288,7 @@ def _fake_get_config_value(puppet_bin, setting): } } } - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) content = util.load_text_file(self.CSR_ATTRIBUTES_PATH) expected = textwrap.dedent("""\ custom_attributes: @@ -305,7 +305,7 @@ def test_puppet_runs_puppet_if_requested(self, m_subp, m_man_puppet): """Run puppet with default args if 'exec' is set to True.""" cloud = get_cloud() cfg = {"puppet": {"exec": True}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) assert 2 == m_man_puppet.call_count expected_calls = [ mock.call(cloud, "enable"), @@ -320,8 +320,8 @@ def test_puppet_runs_puppet_if_requested(self, m_subp, m_man_puppet): def test_puppet_starts_puppetd(self, m_subp, m_man_puppet): """Run puppet with default args if 'exec' is set to True.""" cloud = get_cloud() - cfg = {"puppet": {}} - cc_puppet.handle("notimportant", cfg, cloud, None) + cfg: dict = {"puppet": {}} + cc_puppet.handle("notimportant", cfg, cloud, []) assert 2 == m_man_puppet.call_count expected_calls = [ mock.call(cloud, "enable"), @@ -334,7 +334,7 @@ def test_puppet_skips_puppetd(self, m_subp, m_man_puppet): """Run puppet with default args if 'exec' is set to True.""" cfg = {"puppet": {"start_service": False}} - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 0 == m_man_puppet.call_count assert [ mock.call(["systemctl", "start", "puppet-agent"], capture=False) @@ -352,7 +352,7 @@ def test_puppet_runs_puppet_with_args_list_if_requested( "exec_args": ["--onetime", "--detailed-exitcodes"], } } - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 2 == m_man_puppet.call_count assert [ mock.call( @@ -373,7 +373,7 @@ def test_puppet_runs_puppet_with_args_string_if_requested( "exec_args": "--onetime --detailed-exitcodes", } } - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 2 == m_man_puppet.call_count assert [ mock.call( @@ -384,7 +384,7 @@ def test_puppet_runs_puppet_with_args_string_if_requested( @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", "")) def test_puppet_falls_back_to_older_name(self, m_subp, m_man_puppet): - cfg = {"puppet": {}} + cfg: dict = {"puppet": {}} with mock.patch( "tests.unittests.util.MockDistro.install_packages" ) as install_pkg: @@ -392,7 +392,7 @@ def test_puppet_falls_back_to_older_name(self, m_subp, m_man_puppet): install_pkg.side_effect = (PackageInstallerError, 0) cloud = get_cloud() - cc_puppet.handle("notimportant", cfg, cloud, None) + cc_puppet.handle("notimportant", cfg, cloud, []) expected_calls = [ mock.call(cloud, "enable"), mock.call(cloud, "start"), @@ -408,7 +408,7 @@ def test_puppet_with_conf_package_name_fails(self, m_subp, m_man_puppet): # puppet-agent not installed, but puppet is install_pkg.side_effect = (ProcessExecutionError, 0) with pytest.raises(ProcessExecutionError): - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 0 == m_man_puppet.call_count assert [ mock.call(["systemctl", "start", "puppet-agent"], capture=True) @@ -417,7 +417,7 @@ def test_puppet_with_conf_package_name_fails(self, m_subp, m_man_puppet): @mock.patch("cloudinit.config.cc_puppet.subp.subp", return_value=("", "")) def test_puppet_with_conf_package_name_success(self, m_subp, m_man_puppet): cfg = {"puppet": {"package_name": "puppet"}} - cc_puppet.handle("notimportant", cfg, get_cloud(), None) + cc_puppet.handle("notimportant", cfg, get_cloud(), []) assert 2 == m_man_puppet.call_count From 7ba300a62ae443808d967bb484767d1211dedd8f Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:32:14 +0530 Subject: [PATCH 10/20] typing: fix mypy annotation errors in test_cc_resizefs Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_resizefs.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index df36e31b5eb..24d6d1d0a09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_resizefs", "tests.unittests.config.test_cc_resolv_conf", "tests.unittests.config.test_cc_rh_subscription", "tests.unittests.config.test_cc_ubuntu_autoinstall", diff --git a/tests/unittests/config/test_cc_resizefs.py b/tests/unittests/config/test_cc_resizefs.py index b103f0a7124..8682f7b0ed9 100644 --- a/tests/unittests/config/test_cc_resizefs.py +++ b/tests/unittests/config/test_cc_resizefs.py @@ -81,7 +81,7 @@ def test_can_skip_resize_ext(self): def test_handle_noops_on_disabled(self, caplog): """The handle function logs when the configuration disables resize.""" cfg = {"resize_rootfs": False} - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) assert ( mock.ANY, logging.DEBUG, @@ -96,7 +96,7 @@ def test_handle_warns_on_unknown_mount_info( """handle warns when get_mount_info sees unknown filesystem for /.""" m_get_mount_info.return_value = None cfg = {"resize_rootfs": True} - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) logs = caplog.text assert ( "WARNING: Invalid cloud-config provided:\nresize_rootfs:" @@ -190,7 +190,7 @@ def test_handle_zfs_root( cfg = {"resize_rootfs": True} with mock.patch("cloudinit.config.cc_resizefs.do_resize") as dresize: - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) ret = dresize.call_args[0] assert (("zpool", "online", "-e", "vmzroot", disk),) == ret @@ -224,7 +224,7 @@ def fake_stat(devpath): with mock.patch("cloudinit.config.cc_resizefs.do_resize") as dresize: with mock.patch("cloudinit.config.cc_resizefs.os.stat") as m_stat: m_stat.side_effect = fake_stat - handle("cc_resizefs", cfg, cloud=None, args=[]) + handle("cc_resizefs", cfg, cloud=mock.Mock(), args=[]) assert ( ("zpool", "online", "-e", "zroot", "/dev/" + disk), ) == dresize.call_args[0] From 74387d398b22e832ce81eff84858ac2844649a0c Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:17:55 +0530 Subject: [PATCH 11/20] typing: fix mypy annotation errors in test_cc_resolv_conf Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_resolv_conf.py | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 24d6d1d0a09..5c51c6baef9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_resolv_conf", "tests.unittests.config.test_cc_rh_subscription", "tests.unittests.config.test_cc_ubuntu_autoinstall", "tests.unittests.config.test_cc_update_etc_hosts", diff --git a/tests/unittests/config/test_cc_resolv_conf.py b/tests/unittests/config/test_cc_resolv_conf.py index 6bf67dda026..75e887ae05b 100644 --- a/tests/unittests/config/test_cc_resolv_conf.py +++ b/tests/unittests/config/test_cc_resolv_conf.py @@ -32,8 +32,7 @@ class TestResolvConf: cfg = {"manage_resolv_conf": True, "resolv_conf": {}} def call_resolv_conf_handler(self, distro, conf, paths): - ds = None - cc = cloud.Cloud(ds, paths, {}, distro, None) + cc = cloud.Cloud(mock.Mock(), paths, {}, distro, mock.Mock()) cc_resolv_conf.handle("cc_resolv_conf", conf, cc, []) @mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file") @@ -88,10 +87,9 @@ def test_resolv_conf_etc_resolv_conf( def test_resolv_conf_invalid_resolve_conf_fn( self, m_render_to_file, caplog, Distro, tmp_path ): - ds = None dist = Distro("rhel", self.cfg) paths = helpers.Paths({"cloud_dir": str(tmp_path)}) - cc = cloud.Cloud(ds, paths, {}, dist, None) + cc = cloud.Cloud(mock.Mock(), paths, {}, dist, mock.Mock()) cc.distro.resolve_conf_fn = "bla" cc_resolv_conf.handle("rhel", self.cfg, cc, []) From e1ca63fceb8be914133ca2b7c789e8782c409804 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:18:30 +0530 Subject: [PATCH 12/20] typing: fix mypy annotation errors in test_cc_rh_subscription Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - .../config/test_cc_rh_subscription.py | 29 ++++++++++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5c51c6baef9..f6bf53755f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_rh_subscription", "tests.unittests.config.test_cc_ubuntu_autoinstall", "tests.unittests.config.test_cc_update_etc_hosts", "tests.unittests.config.test_cc_users_groups", diff --git a/tests/unittests/config/test_cc_rh_subscription.py b/tests/unittests/config/test_cc_rh_subscription.py index 18d13dd41c7..af34430ff63 100644 --- a/tests/unittests/config/test_cc_rh_subscription.py +++ b/tests/unittests/config/test_cc_rh_subscription.py @@ -4,6 +4,7 @@ import copy import logging +from typing import cast import pytest @@ -53,7 +54,7 @@ def test_already_registered(self, m_sman_cli, caplog): Emulates a system that is already registered. Ensure it gets a non-ProcessExecution error from is_registered() """ - cc_rh_subscription.handle(NAME, self.CONFIG, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG, mock.Mock(), []) assert m_sman_cli.call_count == 1 assert "System is already registered" in caplog.text @@ -71,7 +72,7 @@ def test_simple_registration( " 12345678-abde-abcde-1234-1234567890abc" ) m_sman_cli.side_effect = [subp.ProcessExecutionError, (reg, "bar")] - cc_rh_subscription.handle(NAME, self.CONFIG, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG, mock.Mock(), []) assert mock.call(["identity"]) in m_sman_cli.call_args_list assert ( mock.call( @@ -106,7 +107,7 @@ def test_update_repos_disable_with_none( enable_repo_key = "enable_repo".replace("_", variable_name_separator) disable_repo_key = "disable_repo".replace("_", variable_name_separator) - cfg["rh_subscription"].update( + cast(dict, cfg["rh_subscription"]).update( {enable_repo_key: ["repo1"], disable_repo_key: None} ) mysm = cc_rh_subscription.SubscriptionManager(cfg) @@ -149,7 +150,7 @@ def test_full_registration(self, m_sman_cli, caplog, mocker): # on the host running the tests mocker.patch("shutil.rmtree") - cc_rh_subscription.handle(NAME, self.CONFIG_FULL, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_FULL, mock.Mock(), []) assert m_sman_cli.call_count == 10 for call in call_lists: assert mock.call(call) in m_sman_cli.call_args_list @@ -225,13 +226,15 @@ def test_no_password(self, m_sman_cli): subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, self.CONFIG_NO_PASSWORD, None, []) + cc_rh_subscription.handle( + NAME, self.CONFIG_NO_PASSWORD, mock.Mock(), [] + ) assert m_sman_cli.call_count == 0 def test_no_org(self, m_sman_cli, caplog): """Attempt to register without the org key/value.""" m_sman_cli.side_effect = [subp.ProcessExecutionError] - cc_rh_subscription.handle(NAME, self.CONFIG_NO_KEY, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_NO_KEY, mock.Mock(), []) m_sman_cli.assert_called_with(["identity"]) assert m_sman_cli.call_count == 1 self.assert_logged_warnings( @@ -272,7 +275,7 @@ def test_service_level_without_auto( subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, auto_attach_cfg, None, []) + cc_rh_subscription.handle(NAME, auto_attach_cfg, mock.Mock(), []) assert m_sman_cli.call_count == 1 self.assert_logged_warnings( warnings, @@ -287,7 +290,7 @@ def test_pool_not_a_list(self, m_sman_cli, caplog): subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, self.CONFIG_BADPOOL, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_BADPOOL, mock.Mock(), []) assert m_sman_cli.call_count == 2 self.assert_logged_warnings( ( @@ -305,7 +308,7 @@ def test_repo_not_a_list(self, m_sman_cli, caplog): subp.ProcessExecutionError, (self.REG, "bar"), ] - cc_rh_subscription.handle(NAME, self.CONFIG_BADREPO, None, []) + cc_rh_subscription.handle(NAME, self.CONFIG_BADREPO, mock.Mock(), []) assert m_sman_cli.call_count == 2 self.assert_logged_warnings( ( @@ -329,7 +332,7 @@ def test_bad_release_version(self, m_delete_pm_cache, m_sman_cli, caplog): subp.ProcessExecutionError, ] cc_rh_subscription.handle( - NAME, self.CONFIG_BAD_RELEASE_VERSION, None, [] + NAME, self.CONFIG_BAD_RELEASE_VERSION, mock.Mock(), [] ) assert m_sman_cli.call_count == 3 assert m_delete_pm_cache.call_count == 0 @@ -362,7 +365,7 @@ def test_pm_cache_deletion_after_setting_release_version( (self.REG, "bar"), ("Release set to: 1.2Server", ""), ] - cc_rh_subscription.handle(NAME, good_release_ver_cfg, None, []) + cc_rh_subscription.handle(NAME, good_release_ver_cfg, mock.Mock(), []) # assert "rh_subscription plugin completed successfully" in caplog.text assert m_sman_cli.call_count == 3 assert m_rmtree.call_args_list == [mock.call("/var/cache/dnf")] @@ -479,8 +482,8 @@ def test_deprecated_values(self): correct python object fields """ - cfg_with_new_keys = {"rh_subscription": {}} - cfg_with_deprecated_keys = {"rh_subscription": {}} + cfg_with_new_keys: dict = {"rh_subscription": {}} + cfg_with_deprecated_keys: dict = {"rh_subscription": {}} deprecation_pairs = [ ("activation-key", "activation_key"), From 898220fe16cfde1b7d35505ab9642f9b706259ee Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:18:30 +0530 Subject: [PATCH 13/20] typing: fix mypy annotation errors in test_cc_ubuntu_autoinstall Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_ubuntu_autoinstall.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f6bf53755f1..fc325b03475 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_ubuntu_autoinstall", "tests.unittests.config.test_cc_update_etc_hosts", "tests.unittests.config.test_cc_users_groups", "tests.unittests.config.test_cc_wireguard", diff --git a/tests/unittests/config/test_cc_ubuntu_autoinstall.py b/tests/unittests/config/test_cc_ubuntu_autoinstall.py index 56534b67db9..87209cc0c19 100644 --- a/tests/unittests/config/test_cc_ubuntu_autoinstall.py +++ b/tests/unittests/config/test_cc_ubuntu_autoinstall.py @@ -96,7 +96,7 @@ def test_handle_autoinstall_cfg( ): subp.return_value = snap_list, "" cloud = get_cloud(distro="ubuntu", paths=Paths({"cloud_dir": tmpdir})) - cc_ubuntu_autoinstall.handle("name", cfg, cloud, None) + cc_ubuntu_autoinstall.handle("name", cfg, cloud, []) assert subp_calls == subp.call_args_list for log in logs: assert log in caplog.text From 0fc7e171742036de4f6acd84c26ee067d718e173 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Sun, 30 Aug 2026 20:21:42 +0530 Subject: [PATCH 14/20] typing: fix mypy annotation errors in test_cc_update_etc_hosts Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fc325b03475..0a40d191b94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_update_etc_hosts", "tests.unittests.config.test_cc_users_groups", "tests.unittests.config.test_cc_wireguard", "tests.unittests.config.test_cc_yum_add_repo", From 34089f4405f590a5b5cd13eb8506f56b0a99f7dc Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:18:43 +0530 Subject: [PATCH 15/20] typing: fix mypy annotation errors in test_cc_users_groups Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - .../unittests/config/test_cc_users_groups.py | 30 +++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0a40d191b94..8b6ce45852c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_users_groups", "tests.unittests.config.test_cc_wireguard", "tests.unittests.config.test_cc_yum_add_repo", "tests.unittests.config.test_cc_zypper_add_repo", diff --git a/tests/unittests/config/test_cc_users_groups.py b/tests/unittests/config/test_cc_users_groups.py index 26e8b6f210d..fbc0d8c15b1 100644 --- a/tests/unittests/config/test_cc_users_groups.py +++ b/tests/unittests/config/test_cc_users_groups.py @@ -28,7 +28,7 @@ class TestHandleUsersGroups: def test_handle_no_cfg_creates_no_users_or_groups(self, m_user, m_group): """Test handle with no config will not create users or groups.""" - cfg = {} # merged cloud-config + cfg: dict = {} # merged cloud-config # System config defines a default user for the distro. sys_cfg = { "default_user": { @@ -38,9 +38,9 @@ def test_handle_no_cfg_creates_no_users_or_groups(self, m_user, m_group): "shell": "/bin/bash", } } - metadata = {} + metadata: dict = {} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_user.assert_not_called() m_group.assert_not_called() @@ -56,9 +56,9 @@ def test_handle_users_in_cfg_calls_create_users(self, m_user, m_group): "shell": "/bin/bash", } } - metadata = {} + metadata: dict = {} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -96,7 +96,7 @@ def test_handle_users_in_cfg_calls_create_users_on_bsd( "homedir": "/home/freebsd", } } - metadata = {} + metadata: dict = {} # patch ifconfig -a with mock.patch( "cloudinit.distros.networking.subp.subp", return_value=("", None) @@ -104,7 +104,7 @@ def test_handle_users_in_cfg_calls_create_users_on_bsd( cloud = get_cloud( distro="freebsd", sys_cfg=sys_cfg, metadata=metadata ) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_fbsd_user.call_args_list, [ @@ -138,7 +138,7 @@ def test_users_with_ssh_redirect_user_passes_keys(self, m_user, m_group): } metadata = {"public-keys": ["key1"]} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -177,7 +177,7 @@ def test_users_with_ssh_redirect_user_default_str(self, m_user, m_group): } metadata = {"public-keys": ["key1"]} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -214,7 +214,7 @@ def test_users_without_home_cannot_import_ssh_keys(self, m_user, m_group): match=r"Not creating user me2. Key\(s\) ssh_import_id cannot be" " provided with no_create_home", ): - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_group.assert_not_called() def test_users_with_ssh_redirect_user_non_default(self, m_user, m_group): @@ -241,7 +241,7 @@ def test_users_with_ssh_redirect_user_non_default(self, m_user, m_group): match="Not creating user me2. Invalid value of ssh_redirect_user:" " snowflake. Expected values: true, default or false.", ): - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_group.assert_not_called() def test_users_with_ssh_redirect_user_default_false(self, m_user, m_group): @@ -258,7 +258,7 @@ def test_users_with_ssh_redirect_user_default_false(self, m_user, m_group): } metadata = {"public-keys": ["key1"]} cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) assert_count_equal( m_user.call_args_list, [ @@ -281,10 +281,10 @@ def test_users_ssh_redirect_user_and_no_default( "users": ["default", {"name": "me2", "ssh_redirect_user": True}] } # System config defines *no* default user for the distro. - sys_cfg = {} - metadata = {} # no public-keys defined + sys_cfg: dict = {} + metadata: dict = {} # no public-keys defined cloud = get_cloud(distro="ubuntu", sys_cfg=sys_cfg, metadata=metadata) - cc_users_groups.handle("modulename", cfg, cloud, None) + cc_users_groups.handle("modulename", cfg, cloud, []) m_user.assert_called_once_with("me2", default=False) m_group.assert_not_called() assert [ From 3e45825bd8d263303c2e0687cbcb12d1be06dfc1 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:19:18 +0530 Subject: [PATCH 16/20] typing: fix mypy annotation errors in test_cc_wireguard Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_wireguard.py | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8b6ce45852c..5b0031632ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_wireguard", "tests.unittests.config.test_cc_yum_add_repo", "tests.unittests.config.test_cc_zypper_add_repo", "tests.unittests.config.test_modules", diff --git a/tests/unittests/config/test_cc_wireguard.py b/tests/unittests/config/test_cc_wireguard.py index b87851aaa7e..1ed35151307 100644 --- a/tests/unittests/config/test_cc_wireguard.py +++ b/tests/unittests/config/test_cc_wireguard.py @@ -4,7 +4,7 @@ import pytest -from cloudinit import subp, util +from cloudinit import cloud, subp, util from cloudinit.config import cc_wireguard from cloudinit.config.schema import ( SchemaValidationError, @@ -19,7 +19,7 @@ MIN_KERNEL_VERSION = (5, 6) -class FakeCloud: +class FakeCloud(cloud.Cloud): def __init__(self, distro): self.distro = distro @@ -39,7 +39,7 @@ def test_readiness_probe_schema_non_string_values(self): def test_suppl_schema_error_on_missing_keys(self): """ValueError raised reporting any missing required keys""" - cfg = {} + cfg: dict = {} match = ( f"Invalid wireguard interface configuration:{NL}" "Missing required wg:interfaces keys: config_path, content, name" @@ -207,8 +207,8 @@ def test_handle_no_config( self, m_maybe_install_wireguard_packages, caplog ): """When no wireguard configuration is provided, nothing happens.""" - cfg = {} - cc_wireguard.handle("wg", cfg=cfg, cloud=None, args=None) + cfg: dict = {} + cc_wireguard.handle("wg", cfg=cfg, cloud=mock.Mock(), args=[]) assert ( mock.ANY, logging.DEBUG, From 8617ac165e33a4a451fd5f09c59704211fe987e2 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:19:36 +0530 Subject: [PATCH 17/20] typing: fix mypy annotation errors in test_cc_yum_add_repo Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_yum_add_repo.py | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5b0031632ad..e06cc12163b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_yum_add_repo", "tests.unittests.config.test_cc_zypper_add_repo", "tests.unittests.config.test_modules", "tests.unittests.config.test_schema", diff --git a/tests/unittests/config/test_cc_yum_add_repo.py b/tests/unittests/config/test_cc_yum_add_repo.py index 5d4206310b4..7f8b52dc3c7 100644 --- a/tests/unittests/config/test_cc_yum_add_repo.py +++ b/tests/unittests/config/test_cc_yum_add_repo.py @@ -3,6 +3,7 @@ import configparser import logging import re +from unittest import mock import pytest @@ -36,7 +37,7 @@ def test_bad_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) with pytest.raises(IOError): util.load_text_file("/etc/yum.repos.d/epel_testing.repo") @@ -53,7 +54,7 @@ def test_metalink_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file("/etc/yum.repos.d/epel-testing.repo") parser = configparser.ConfigParser() parser.read_string(contents) @@ -87,7 +88,7 @@ def test_mirrorlist_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file("/etc/yum.repos.d/epel-testing.repo") parser = configparser.ConfigParser() parser.read_string(contents) @@ -121,7 +122,7 @@ def test_write_config(self): }, }, } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file("/etc/yum.repos.d/epel-testing.repo") parser = configparser.ConfigParser() parser.read_string(contents) @@ -159,7 +160,7 @@ def test_write_config_array(self): } } } - cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) + cc_yum_add_repo.handle("yum_add_repo", cfg, mock.Mock(), []) contents = util.load_text_file( "/etc/yum.repos.d/puppetlabs-products.repo" ) From 6fecd996cc94a22d901576b9bc58480c8f024262 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:29:28 +0530 Subject: [PATCH 18/20] typing: fix mypy annotation errors in test_cc_zypper_add_repo Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_cc_zypper_add_repo.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e06cc12163b..32fbb4b83e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_cc_zypper_add_repo", "tests.unittests.config.test_modules", "tests.unittests.config.test_schema", "tests.unittests.distros.test_ifconfig", diff --git a/tests/unittests/config/test_cc_zypper_add_repo.py b/tests/unittests/config/test_cc_zypper_add_repo.py index b30c382a904..2698d148e8f 100644 --- a/tests/unittests/config/test_cc_zypper_add_repo.py +++ b/tests/unittests/config/test_cc_zypper_add_repo.py @@ -4,6 +4,7 @@ import glob import logging import os +from unittest import mock import pytest @@ -13,7 +14,6 @@ LOG = logging.getLogger(__name__) - ZYPP_CONF = "etc/zypp/zypp.conf" @@ -154,7 +154,7 @@ def test_handler_full_setup(self, tmp_path): root_d = str(tmp_path) os.makedirs("%s/etc/zypp/repos.d" % root_d) helpers.populate_dir(root_d, {ZYPP_CONF: "# Zypp config\n"}) - cc_zypper_add_repo.handle("zypper_add_repo", cfg, None, []) + cc_zypper_add_repo.handle("zypper_add_repo", cfg, mock.Mock(), []) cfg_out = os.path.join(root_d, ZYPP_CONF) contents = util.load_text_file(cfg_out) expected = [ From de3c43e62bb72bfc0f4318e31a648030323ec329 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:21:32 +0530 Subject: [PATCH 19/20] typing: fix mypy annotation errors in test_modules Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_modules.py | 51 +++++++++++++++----------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 32fbb4b83e2..83490b1b120 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_modules", "tests.unittests.config.test_schema", "tests.unittests.distros.test_ifconfig", "tests.unittests.distros.test_netbsd", diff --git a/tests/unittests/config/test_modules.py b/tests/unittests/config/test_modules.py index e4ccd9c69e6..00aa23461f3 100644 --- a/tests/unittests/config/test_modules.py +++ b/tests/unittests/config/test_modules.py @@ -5,7 +5,7 @@ import inspect import logging from pathlib import Path -from typing import List +from typing import List, cast from unittest import mock import pytest @@ -69,14 +69,17 @@ def test__is_inapplicable( self, activate_by_schema_keys, cfg, active, frequency ): module = mock.Mock() - module.meta = MetaSchema( - name="module_name", - id="cc_module_name", - title="title", - description="description", - distros=[ALL_DISTROS], - examples=["example_0", "example_1"], - frequency=frequency, + module.meta = cast( + MetaSchema, + { + "name": "module_name", + "id": "cc_module_name", + "title": "title", + "description": "description", + "distros": [ALL_DISTROS], + "examples": ["example_0", "example_1"], + "frequency": frequency, + }, ) if activate_by_schema_keys is not None: module.meta["activate_by_schema_keys"] = activate_by_schema_keys @@ -93,7 +96,7 @@ def test__is_inapplicable_examples(self, mod_name, module, example): module_details = ModuleDetails( module=module, name=mod_name, - frequency=["always"], + frequency="always", run_args=[], ) assert True is _is_active(module_details, util.load_yaml(example)) @@ -109,14 +112,17 @@ def test_run_section(self, frequency, active, caplog, mocker): mods._cached_cfg = {} raw_name = "my_module" module = mock.Mock() - module.meta = MetaSchema( - name=raw_name, - id=f"cc_{raw_name}", - title="title", - description="description", - distros=[ALL_DISTROS], - examples=["example_0", "example_1"], - frequency=frequency, + module.meta = cast( + MetaSchema, + { + "name": raw_name, + "id": f"cc_{raw_name}", + "title": "title", + "description": "description", + "distros": [ALL_DISTROS], + "examples": ["example_0", "example_1"], + "frequency": frequency, + }, ) module_details = ModuleDetails( module=module, @@ -160,7 +166,7 @@ def test_run_section_examples( module_details = ModuleDetails( module=module, name=mod_name, - frequency=["always"], + frequency="always", run_args=[], ) mocker.patch.object( @@ -192,10 +198,11 @@ def handle(name, cfg, cloud, log, args): module_details = ModuleDetails( module=module, name="mod_name", - frequency=["always"], + frequency="always", run_args=[], ) - m_cc = mods.init.cloudify.return_value + m_cc = mock.MagicMock() + cast(mock.MagicMock, mods.init.cloudify).return_value = m_cc m_cc.run.return_value = (1, "doesnotmatter") mods._run_modules([module_details]) @@ -211,7 +218,7 @@ def handle(name, cfg, cloud, log, args): "args": [], "log": mock.ANY, }, - freq=["always"], + freq="always", ) ] == m_cc.run.call_args_list From 0745339a2f44be0e49c1757869dc8ca5e7a87dd4 Mon Sep 17 00:00:00 2001 From: Shreenidhi Shedi Date: Tue, 1 Sep 2026 19:22:01 +0530 Subject: [PATCH 20/20] typing: fix mypy annotation errors in test_schema Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Shreenidhi Shedi --- pyproject.toml | 1 - tests/unittests/config/test_schema.py | 16 +++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 83490b1b120..8c7e1e6d3f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ module = [ "cloudinit.sources.helpers.vmware.imc.config_nic", "cloudinit.user_data", "tests.unittests.analyze.test_show", - "tests.unittests.config.test_schema", "tests.unittests.distros.test_ifconfig", "tests.unittests.distros.test_netbsd", "tests.unittests.distros.test_netconfig", diff --git a/tests/unittests/config/test_schema.py b/tests/unittests/config/test_schema.py index a91234b0748..738598d5a5e 100644 --- a/tests/unittests/config/test_schema.py +++ b/tests/unittests/config/test_schema.py @@ -13,7 +13,7 @@ from pathlib import Path from textwrap import dedent from types import ModuleType -from typing import List +from typing import List, cast import pytest import yaml @@ -1049,10 +1049,16 @@ def test_annotated_cloudconfig_file_no_schema_errors(self): """With no schema_errors, print the original content.""" content = b"ntp:\n pools: [ntp1.pools.com]\n" _, schemamarks = load_with_marks(content) - assert content == annotated_cloudconfig_file( - content, - schemamarks=schemamarks, - schema_errors=[], + assert ( + content + == cast( + str, + annotated_cloudconfig_file( + content.decode(), + schemamarks=schemamarks, + schema_errors=[], + ), + ).encode() ) def test_annotated_cloudconfig_file_schema_annotates_and_adds_footer(self):