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 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..b0f9abf07e02 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,48 @@ 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", (True, False)) +@pytest.mark.parametrize("include_beta", (True, False)) +@pytest.mark.parametrize("include_rc", (True, False)) +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. + + 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, + ) + + 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): # Let's remove the pip binary pip_bin = venv.venv_bin_dir / "pip"