From 91f268f1691b9be698e2dfcd87abe11eff0fd436 Mon Sep 17 00:00:00 2001 From: kwall Date: Wed, 10 Dec 2025 17:23:51 -0700 Subject: [PATCH 1/4] Fix pip.installed state managed pre-release upgrades `pip index versions` will never yield pre-release versions of the package without the `--pre` option. In effect, this means providing `pre_releases=True` and `upgrade=True` to the `pip.installed` state will never work, but I'm unsure of the actual extent of this bug. --- requirements/pytest.txt | 1 + salt/modules/pip.py | 6 ++- tests/pytests/functional/modules/test_pip.py | 48 ++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/requirements/pytest.txt b/requirements/pytest.txt index 376464b0a0d7..81a65e448b2d 100644 --- a/requirements/pytest.txt +++ b/requirements/pytest.txt @@ -1,4 +1,5 @@ mock >= 3.0.0 +packaging # PyTest docker >= 7.1.0; python_version >= '3.8' docker < 7.1.0; python_version < '3.8' diff --git a/salt/modules/pip.py b/salt/modules/pip.py index d108d0815ad8..320dbdf1a40c 100644 --- a/salt/modules/pip.py +++ b/salt/modules/pip.py @@ -1654,7 +1654,11 @@ def list_all_versions( pip_version = version(bin_env=bin_env, cwd=cwd, user=user) if salt.utils.versions.compare(ver1=pip_version, oper=">=", ver2="21.2"): regex = re.compile(r"\s*Available versions: (.*)") - cmd.extend(["index", "versions", pkg]) + # pre-release versions are not included by default + if any([include_alpha, include_beta, include_rc]): + cmd.extend(["index", "versions", "--pre", pkg]) + else: + cmd.extend(["index", "versions", pkg]) else: if salt.utils.versions.compare(ver1=pip_version, oper=">=", ver2="20.3"): cmd.append("--use-deprecated=legacy-resolver") diff --git a/tests/pytests/functional/modules/test_pip.py b/tests/pytests/functional/modules/test_pip.py index fa2b1a6573dc..39ce206e57a8 100644 --- a/tests/pytests/functional/modules/test_pip.py +++ b/tests/pytests/functional/modules/test_pip.py @@ -6,6 +6,7 @@ from contextlib import contextmanager import pytest +from packaging.version import parse as parse_version import salt.utils.platform from salt.exceptions import CommandNotFoundError @@ -113,6 +114,53 @@ def test_list_available_packages_with_index_url(pip, pip_version, tmp_path): assert available_versions +@pytest.mark.parametrize( + "pip_version", + ( + pytest.param( + "pip==9.0.3", + marks=pytest.mark.skipif( + sys.version_info >= (3, 10), + reason="'pip==9.0.3' is not available on Py >= 3.10", + ), + ), + "pip<20.0", + "pip<21.0", + "pip>=21.0", + ), +) +@pytest.mark.parametrize( + "include_alpha,include_beta,include_rc", + ( + (False, False, True), # 001 + (False, True, False), # 010 + (False, True, True), # 011 + (True, False, False), # 100 + (True, False, True), # 101 + (True, True, False), # 110 + (True, True, True), # 111 + ) +) +def test_list_available_packages_returns_prerelease_versions_if_alpha_beta_or_rc_included( + venv, pip, pip_version, include_alpha, include_beta, include_rc +): + """Tests that pre-release versions are returned when flags enable them. + + Note: relies on PyPI hosting pre-release versions of `typing-extensions`. + """ + venv.install("-U", pip_version) + package_name = "typing-extensions" + versions = pip.list_all_versions( + package_name, + bin_env=str(venv.venv_bin_dir), + include_alpha=include_alpha, + include_beta=include_beta, + include_rc=include_rc, + ) + # parse each version and assert there's a pre-release version somewhere + assert any(map(lambda v: v.is_prerelease, map(parse_version, versions))) + + def test_issue_2087_missing_pip(venv, pip, modules): # Let's remove the pip binary pip_bin = venv.venv_bin_dir / "pip" From e0bd7e3a5a2ce10dee8d6d5d43a046225989a07a Mon Sep 17 00:00:00 2001 From: kwall Date: Thu, 11 Dec 2025 11:10:12 -0700 Subject: [PATCH 2/4] Add changelog file --- changelog/68525.fixed.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/68525.fixed.md diff --git a/changelog/68525.fixed.md b/changelog/68525.fixed.md new file mode 100644 index 000000000000..f21f7fe82e6a --- /dev/null +++ b/changelog/68525.fixed.md @@ -0,0 +1 @@ +Fix `pip.installed` state managed pre-release upgrades From 7307cb28a9f89d1efefd8e7afeb22fc49278c1b9 Mon Sep 17 00:00:00 2001 From: kwall Date: Tue, 27 Jan 2026 18:16:56 -0700 Subject: [PATCH 3/4] Fix test logic for failing platforms --- tests/pytests/functional/modules/test_pip.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/tests/pytests/functional/modules/test_pip.py b/tests/pytests/functional/modules/test_pip.py index 39ce206e57a8..c0dc1be96755 100644 --- a/tests/pytests/functional/modules/test_pip.py +++ b/tests/pytests/functional/modules/test_pip.py @@ -129,18 +129,9 @@ def test_list_available_packages_with_index_url(pip, pip_version, tmp_path): "pip>=21.0", ), ) -@pytest.mark.parametrize( - "include_alpha,include_beta,include_rc", - ( - (False, False, True), # 001 - (False, True, False), # 010 - (False, True, True), # 011 - (True, False, False), # 100 - (True, False, True), # 101 - (True, True, False), # 110 - (True, True, True), # 111 - ) -) +@pytest.mark.parametrize("include_alpha", (True, False)) +@pytest.mark.parametrize("include_beta", (True, False)) +@pytest.mark.parametrize("include_rc", (True, False)) def test_list_available_packages_returns_prerelease_versions_if_alpha_beta_or_rc_included( venv, pip, pip_version, include_alpha, include_beta, include_rc ): @@ -158,7 +149,7 @@ def test_list_available_packages_returns_prerelease_versions_if_alpha_beta_or_rc include_rc=include_rc, ) # parse each version and assert there's a pre-release version somewhere - assert any(map(lambda v: v.is_prerelease, map(parse_version, versions))) + assert any(list(map(lambda v: v.is_prerelease, map(parse_version, versions)))) def test_issue_2087_missing_pip(venv, pip, modules): From a9f8e69613c58fec4cdcc2dbf08aaafaf58db3f4 Mon Sep 17 00:00:00 2001 From: kwall Date: Mon, 2 Feb 2026 12:34:18 -0700 Subject: [PATCH 4/4] Fix test --- tests/pytests/functional/modules/test_pip.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/pytests/functional/modules/test_pip.py b/tests/pytests/functional/modules/test_pip.py index c0dc1be96755..b0f9abf07e02 100644 --- a/tests/pytests/functional/modules/test_pip.py +++ b/tests/pytests/functional/modules/test_pip.py @@ -132,7 +132,7 @@ def test_list_available_packages_with_index_url(pip, pip_version, tmp_path): @pytest.mark.parametrize("include_alpha", (True, False)) @pytest.mark.parametrize("include_beta", (True, False)) @pytest.mark.parametrize("include_rc", (True, False)) -def test_list_available_packages_returns_prerelease_versions_if_alpha_beta_or_rc_included( +def test_list_available_packages_with_pre_releases_flags( venv, pip, pip_version, include_alpha, include_beta, include_rc ): """Tests that pre-release versions are returned when flags enable them. @@ -148,8 +148,12 @@ def test_list_available_packages_returns_prerelease_versions_if_alpha_beta_or_rc include_beta=include_beta, include_rc=include_rc, ) - # parse each version and assert there's a pre-release version somewhere - assert any(list(map(lambda v: v.is_prerelease, map(parse_version, versions)))) + + has_prerelease = any(map(lambda v: v.is_prerelease, map(parse_version, versions))) + if any(include_alpha, include_beta, include_rc): + assert has_prerelease + else: + assert not has_prerelease def test_issue_2087_missing_pip(venv, pip, modules):