From 61ae21b51f5c062c311041bbba3cb20df2f65a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20D=C3=B6ring?= <30527984+radoering@users.noreply.github.com> Date: Sun, 27 Oct 2024 10:39:49 +0100 Subject: [PATCH] make `allow-prereleases` a tri-state setting to really forbid pre-releases if the setting is `false` and keep default behavior to allow pre-releases only if necessary --- src/poetry/core/factory.py | 2 +- src/poetry/core/packages/dependency.py | 11 +++++++++-- tests/packages/test_dependency.py | 2 +- tests/packages/test_dependency_group.py | 7 ++++++- tests/test_factory.py | 18 +++++++++++++++++- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/poetry/core/factory.py b/src/poetry/core/factory.py index c58059a0c..0f2dca31a 100644 --- a/src/poetry/core/factory.py +++ b/src/poetry/core/factory.py @@ -414,7 +414,7 @@ def create_dependency( python_versions = constraint.get("python") platform = constraint.get("platform") markers = constraint.get("markers") - allows_prereleases = constraint.get("allow-prereleases", False) + allows_prereleases = constraint.get("allow-prereleases") dependency: Dependency if "git" in constraint: diff --git a/src/poetry/core/packages/dependency.py b/src/poetry/core/packages/dependency.py index 1ba279bab..43eb89d44 100644 --- a/src/poetry/core/packages/dependency.py +++ b/src/poetry/core/packages/dependency.py @@ -41,7 +41,7 @@ def __init__( constraint: str | VersionConstraint, optional: bool = False, groups: Iterable[str] | None = None, - allows_prereleases: bool = False, + allows_prereleases: bool | None = None, extras: Iterable[str] | None = None, source_type: str | None = None, source_url: str | None = None, @@ -233,7 +233,14 @@ def base_pep_508_name(self) -> str: def base_pep_508_name_resolved(self) -> str: return self.base_pep_508_name - def allows_prereleases(self) -> bool: + def allows_prereleases(self) -> bool | None: + """ + None (default): only use pre-release versions + if no stable version satisfies the constraint + False: do not allow pre-release versions + even if this means there is no solution + True: do not distinguish between stable and pre-release versions + """ return self._allows_prereleases def is_optional(self) -> bool: diff --git a/tests/packages/test_dependency.py b/tests/packages/test_dependency.py index 5d0a51887..2d274ea2a 100644 --- a/tests/packages/test_dependency.py +++ b/tests/packages/test_dependency.py @@ -24,7 +24,7 @@ "^1.0.0-1", ], ) -@pytest.mark.parametrize("allows_prereleases", [False, True]) +@pytest.mark.parametrize("allows_prereleases", [None, False, True]) def test_allows_prerelease(constraint: str, allows_prereleases: bool) -> None: dependency = Dependency("A", constraint, allows_prereleases=allows_prereleases) assert dependency.allows_prereleases() == allows_prereleases diff --git a/tests/packages/test_dependency_group.py b/tests/packages/test_dependency_group.py index fac4eeb3a..002bb0d09 100644 --- a/tests/packages/test_dependency_group.py +++ b/tests/packages/test_dependency_group.py @@ -15,7 +15,7 @@ def create_dependency( constraint: str = "*", *, extras: tuple[str, ...] = (), - allows_prereleases: bool = False, + allows_prereleases: bool | None = None, develop: bool = False, source_name: str | None = None, marker: str | None = None, @@ -147,6 +147,11 @@ def test_remove_dependency_removes_from_both_lists() -> None: [create_dependency("foo", allows_prereleases=True)], [create_dependency("foo", ">=1", allows_prereleases=True)], ), + ( + [Dependency.create_from_pep_508("foo>=1")], + [create_dependency("foo", allows_prereleases=False)], + [create_dependency("foo", ">=1", allows_prereleases=False)], + ), # directory dependency - develop ( [DirectoryDependency("foo", Path("path/to/foo"))], diff --git a/tests/test_factory.py b/tests/test_factory.py index b6d9cc34c..5da4a1aaf 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -221,7 +221,7 @@ def test_create_poetry(new_format: str) -> None: requests = dependencies["requests"] assert requests.pretty_constraint == (">=2.18,<3.0" if new_format else "^2.18") assert not requests.is_vcs() - assert not requests.allows_prereleases() + assert requests.allows_prereleases() is None assert requests.is_optional() assert requests.extras == frozenset({"security"}) @@ -930,6 +930,22 @@ def test_create_dependency_marker_variants( assert str(dep.marker) == exp_marker +@pytest.mark.parametrize( + ("constraint", "expected"), + [ + ("1", None), + ({"version": "1"}, None), + ({"version": "1", "allow-prereleases": False}, False), + ({"version": "1", "allow-prereleases": True}, True), + ], +) +def test_create_dependency_allow_prereleases( + constraint: str | dict[str, str], expected: bool | None +) -> None: + dep = Factory.create_dependency("foo", constraint) + assert dep.allows_prereleases() is expected + + def test_all_classifiers_unique_even_if_classifiers_is_duplicated() -> None: poetry = Factory().create_poetry( fixtures_dir / "project_with_duplicated_classifiers"