From ffef25e4f16a12cb3b5fc1cdaa2e808263adde17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Kek=C3=A4l=C3=A4inen?= Date: Sun, 12 Oct 2025 05:58:22 +0000 Subject: [PATCH 1/3] fix: Make `make fmt` pass by fixing mypy errors in 'crypt' module stubs (#6507) The `make fmt` command was failing due to `mypy` errors: $ make fmt ... Cannot find implementation or library stub for module named "crypt" cloudinit/distros/netbsd.py:15: error: Cannot find implementation or library stub for module named "crypt" cloudinit/sources/DataSourceAzure.py:53: error: Cannot find implementation or library stub for module named "crypt" Resolve this by adding `type: ignore` comments to instructs `mypy` to skip type checking for this specific import, allowing the format check to pass without suppressing other type-checking. Detected on latest Debian unstable running `python3-mypy-extensions` version 1.1.0-1. --- cloudinit/distros/netbsd.py | 2 +- cloudinit/sources/DataSourceAzure.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudinit/distros/netbsd.py b/cloudinit/distros/netbsd.py index 157aba06924..f458c3edf65 100644 --- a/cloudinit/distros/netbsd.py +++ b/cloudinit/distros/netbsd.py @@ -12,7 +12,7 @@ from cloudinit import subp, util try: - import crypt # pylint: disable=W4901 + import crypt # type: ignore # pylint: disable=W4901 salt = crypt.METHOD_BLOWFISH # pylint: disable=E1101 blowfish_hash: Any = functools.partial( diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 06872659300..44c1ae28d4e 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -50,7 +50,7 @@ from cloudinit.url_helper import UrlError try: - import crypt # pylint: disable=W4901 + import crypt # type: ignore # pylint: disable=W4901 blowfish_hash: Any = functools.partial( crypt.crypt, salt=f"$6${util.rand_str(strlen=16)}" From bb02287c1a59c2d32272f768d992eef7351e879e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Kek=C3=A4l=C3=A4inen?= Date: Sun, 12 Oct 2025 06:22:48 +0000 Subject: [PATCH 2/3] fix: Fix `make fmt-tip` by limiting Pylint scope (#6507) Correct the `check_format_tip` target to run Pylint only on the project's source directories: `cloudinit/`, `tests/`, and `tools/`. When Pylint was run on the entire current directory (`.`), it attempted to lint all installed third-party libraries within the `.tox` virtual environment. This led to a fatal `astroid.exceptions.AstroidError` crash, preventing the format check from completing: $ make fmt-tip ... .tox/check_format_tip/lib/python3.13/site-packages/appdirs.py:538: [E1101(no-member), _get_win_folder_with_jna] Module 'array' has no 'zeros' member concurrent.futures.process._RemoteTraceback: """ Traceback (most recent call last): File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 831, in _check_file check_astroid_module(ast_node) ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 1020, in check_astroid_module retval = self._check_astroid_module( ast_node, walker, rawcheckers, tokencheckers ) File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 1072, in _check_astroid_module walker.walk(node) ~~~~~~~~~~~^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/utils/ast_walker.py", line 90, in walk self.walk(child) ~~~~~~~~~^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/utils/ast_walker.py", line 90, in walk self.walk(child) ~~~~~~~~~^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/utils/ast_walker.py", line 90, in walk self.walk(child) ~~~~~~~~~^^^^^^^ [Previous line repeated 2 more times] File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/utils/ast_walker.py", line 87, in walk callback(astroid) ~~~~~~~~^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/checkers/variables.py", line 1701, in visit_name self._undefined_and_used_before_checker(node, stmt) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/checkers/variables.py", line 1742, in _undefined_and_used_before_checker action, nodes_to_consume = self._check_consumer( ~~~~~~~~~~~~~~~~~~~~^ node, stmt, frame, current_consumer, base_scope_type ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/checkers/variables.py", line 1858, in _check_consumer self._check_late_binding_closure(node) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/checkers/variables.py", line 2961, in _check_late_binding_closure assign_scope, stmts = node.lookup(node.name) ~~~~~~~~~~~^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/nodes/_base_nodes.py", line 277, in lookup return self.scope().scope_lookup(self, name) ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/nodes/scoped_nodes/scoped_nodes.py", line 1706, in scope_lookup return frame._scope_lookup(node, name, offset) ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/nodes/scoped_nodes/mixin.py", line 91, in _scope_lookup return pscope.scope_lookup(node, name) ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/nodes/scoped_nodes/scoped_nodes.py", line 328, in scope_lookup return self._scope_lookup(node, name, offset) ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/nodes/scoped_nodes/mixin.py", line 80, in _scope_lookup stmts = _filter_stmts(node, self.locals[name], self, offset) File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/filter_statements.py", line 193, in _filter_stmts if not (optional_assign or nodes.are_exclusive(_stmts[pindex], node)): ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/nodes/node_classes.py", line 149, in are_exclusive c2attr, c2node = node.locate_child(previous) ~~~~~~~~~~~~~~~~~^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/astroid/nodes/node_ng.py", line 391, in locate_child raise AstroidError(msg % (repr(child), repr(self))) astroid.exceptions.AstroidError: Could not find in 's children The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/lib/python3.13/concurrent/futures/process.py", line 254, in _process_worker r = call_item.fn(*call_item.args, **call_item.kwargs) File "/usr/lib/python3.13/concurrent/futures/process.py", line 203, in _process_chunk return [fn(*args) for args in chunk] ~~^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/parallel.py", line 79, in _worker_check_single_file _worker_linter.check_single_file_item(file_item) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 740, in check_single_file_item self._check_file(self.get_ast, check_astroid_module, file) ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 833, in _check_file raise astroid.AstroidError from e astroid.exceptions.AstroidError """ The above exception was the direct cause of the following exception: Traceback (most recent call last): File "", line 198, in _run_module_as_main File "", line 88, in _run_code File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/__main__.py", line 10, in pylint.run_pylint() ~~~~~~~~~~~~~~~~~^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/__init__.py", line 34, in run_pylint PylintRun(argv or sys.argv[1:]) ~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/run.py", line 240, in __init__ linter.check(args) ~~~~~~~~~~~~^^^^^^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/pylinter.py", line 679, in check check_parallel( ~~~~~~~~~~~~~~^ self, ^^^^^ ...<2 lines>... extra_packages_paths, ^^^^^^^^^^^^^^^^^^^^^ ) ^ File "/debcraft/source/.tox/check_format_tip/lib/python3.13/site-packages/pylint/lint/parallel.py", line 162, in check_parallel ) in executor.map(_worker_check_single_file, files): ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.13/concurrent/futures/process.py", line 617, in _chain_from_iterable_of_lists for element in iterable: ^^^^^^^^ File "/usr/lib/python3.13/concurrent/futures/_base.py", line 619, in result_iterator yield _result_or_cancel(fs.pop()) ~~~~~~~~~~~~~~~~~^^^^^^^^^^ File "/usr/lib/python3.13/concurrent/futures/_base.py", line 317, in _result_or_cancel return fut.result(timeout) ~~~~~~~~~~^^^^^^^^^ File "/usr/lib/python3.13/concurrent/futures/_base.py", line 449, in result return self.__get_result() ~~~~~~~~~~~~~~~~~^^ File "/usr/lib/python3.13/concurrent/futures/_base.py", line 401, in __get_result raise self._exception astroid.exceptions.AstroidError check_format_tip: exit 1 (126.06 seconds) /debcraft/source> .tox/check_format_tip/bin/python -m pylint . pid=6861 check_format_tip: FAIL code 1 (183.94=setup[57.76]+cmd[0.12,126.06] seconds) evaluation failed :( (184.04 seconds) make: *** [Makefile:119: fmt-tip] Error 1 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 4e801689577..48e92b552de 100644 --- a/tox.ini +++ b/tox.ini @@ -108,7 +108,7 @@ deps = {[latest_versions]deps} commands = {envpython} -m ruff check {posargs:.} - {envpython} -m pylint {posargs:.} + {envpython} -m pylint {posargs:cloudinit/ tests/ tools/} {envpython} -m black --check {posargs:.} {envpython} -m isort --check-only --diff {posargs:.} {envpython} -m mypy {posargs:cloudinit/ tests/ tools/} From ee9319aae649154cda067e17dcfd9c8f62aba6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Otto=20Kek=C3=A4l=C3=A4inen?= Date: Thu, 23 Oct 2025 00:05:53 +0000 Subject: [PATCH 3/3] fix: Allow running `make` on development versions (#6507) When `make` was run on a non-release branch, and `git` was installed, the `check_version` target failed because `tools/read-version` compares the static version from `cloudinit/version.py` with a dynamically generated version from `git describe`. The `git describe` output for development branches includes additional details (e.g., `25.3-6-gc6a1d1f1`) that do not match the static base version (`25.3`), resulting the error: $ make Error: read-version version '25.3-6-gc6a1d1f1' not equal to code version '25.3' make: *** [Makefile:57: check_version] Error 2 Fix this by skipping the version check when not running in CI, so develpers can now run `make`. Release builds and CI environments have dedicated version handling and are not affected by this change. --- tools/read-version | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tools/read-version b/tools/read-version index f47edd1523a..a79b2faf3c2 100755 --- a/tools/read-version +++ b/tools/read-version @@ -124,12 +124,22 @@ def main(use_tags: bool = False, output_json: bool = False): ) is_release_branch_ci = github_ci_release_br or travis_ci_release_br - version, version_long = get_version_from_git( - src_version=src_version, - major_minor_version=major_minor_version, - use_tags=use_tags, - is_release_branch_ci=is_release_branch_ci, - ) + if not os.environ.get("CI"): + # For local development runs (not CI), bypass git version to avoid + # mismatches with the code version during 'make' checks. + print( + "Bypassing git version check for local development", + file=sys.stderr, + ) + version = src_version + version_long = "" + else: + version, version_long = get_version_from_git( + src_version=src_version, + major_minor_version=major_minor_version, + use_tags=use_tags, + is_release_branch_ci=is_release_branch_ci, + ) details = get_version_details(version, version_long, is_release_branch_ci)