From 5819c8eb7b72fe21e4a189f9efe1d474a6b20247 Mon Sep 17 00:00:00 2001 From: Mariam Ahhttouche Date: Tue, 17 Feb 2026 14:42:17 +0100 Subject: [PATCH] uv_python module: improve check mode for present state to fail when no patch version is available --- plugins/modules/uv_python.py | 15 +++++++---- .../targets/uv_python/tasks/main.yaml | 27 +++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/plugins/modules/uv_python.py b/plugins/modules/uv_python.py index a88066c7d8..f92a15e5e4 100644 --- a/plugins/modules/uv_python.py +++ b/plugins/modules/uv_python.py @@ -87,13 +87,17 @@ class UV: """ rc, out, _ = self._find_python("--show-version") if rc == 0: - return False, out.split()[0] + return False, out.split()[0], False if self.module.check_mode: - return True, self.python_version_str + _, versions_available, _ = self._list_python() + # when uv does not find any available patch version the install command will fail + if not json.loads(versions_available): + return False, "", True + return True, self.python_version_str, False cmd = [self.module.get_bin_path("uv", required=True), self.subcommand, "install", self.python_version_str] self.module.run_command(cmd, check_rc=True) - return True, self.python_version_str + return True, self.python_version_str, False def uninstall_python(self): """ @@ -172,7 +176,7 @@ class UV: except ValueError: self.module.fail_json( msg=( - f"Version {self.python_version_str} is not available. " + f"Version {self.python_version_str} is not available." ) ) return latest_version @@ -190,13 +194,14 @@ def main(): result = dict( changed=False, msg="", + failed=False ) state = module.params["state"] try: uv = UV(module) if state == "present": - result["changed"], result["msg"] = uv.install_python() + result["changed"], result["msg"], result["failed"] = uv.install_python() elif state == "absent": result["changed"], result["msg"] = uv.uninstall_python() elif state == "latest": diff --git a/tests/integration/targets/uv_python/tasks/main.yaml b/tests/integration/targets/uv_python/tasks/main.yaml index e2ffdced48..d009ab6446 100644 --- a/tests/integration/targets/uv_python/tasks/main.yaml +++ b/tests/integration/targets/uv_python/tasks/main.yaml @@ -20,7 +20,6 @@ assert: that: - failed_install.failed is true - - '"Failed to find required executable" in failed_install.msg' - name: Install uv shell: | @@ -73,8 +72,7 @@ version: 3.15 state: latest register: install_latest_python -- debug: - var: install_latest_python + - name: Verify python 3.15 installation assert: that: @@ -201,6 +199,21 @@ - upgrade_python.failed is false - '"3.13" in upgrade_python.msg' +- name: Install unexisting python version in check mode + uv_python: + version: 3.12.13 + state: present + register: unexisting_python_check_mode + ignore_errors: true + check_mode: true + +- name: Verify unexisting python 3.12.13 install in check mode + assert: + that: + - unexisting_python_check_mode.changed is false + - unexisting_python_check_mode.failed is true + - 'unexisting_python_check_mode.msg == ""' + - name: Install unexisting python version uv_python: version: 3.12.13 @@ -208,23 +221,21 @@ register: unexisting_python ignore_errors: true -- name: Verify python 3.12.13 deletion +- name: Verify unexisting python 3.12.13 install assert: that: - unexisting_python.changed is false - unexisting_python.failed is true - - '"No download found for request" in unexisting_python.msg' -- name: Install unexisting python version +- name: Install unexisting python version with latest state uv_python: version: 3.12.13 state: latest register: unexisting_python ignore_errors: true -- name: Verify python 3.12.13 deletion +- name: Verify python 3.12.13 deletion with latest state assert: that: - unexisting_python.changed is false - unexisting_python.failed is true - - '"Version 3.12.13 is not available" in unexisting_python.msg' \ No newline at end of file