|
20 | 20 | from packaging.version import Version |
21 | 21 |
|
22 | 22 | from fromager import candidate, context, packagesettings, resolver, sources, wheels |
| 23 | +from fromager.requirements_file import RequirementType |
23 | 24 |
|
24 | 25 | _BOOTSTRAP_TIME = datetime.datetime(2026, 3, 26, 0, 0, 0, tzinfo=datetime.UTC) |
25 | 26 | _COOLDOWN_7_DAYS = datetime.timedelta(days=7) |
@@ -860,3 +861,69 @@ def test_compute_max_age_cutoff_disabled( |
860 | 861 | """_compute_max_age_cutoff returns None when max_release_age is not set.""" |
861 | 862 | cutoff = resolver._compute_max_age_cutoff(tmp_context) |
862 | 863 | assert cutoff is None |
| 864 | + |
| 865 | + |
| 866 | +def test_resolve_package_cooldown_exempt_toplevel_equality_pin( |
| 867 | + tmp_path: pathlib.Path, |
| 868 | +) -> None: |
| 869 | + """Top-level == pin bypasses cooldown.""" |
| 870 | + ctx = _make_ctx(tmp_path, cooldown=_COOLDOWN) |
| 871 | + result = resolver.resolve_package_cooldown( |
| 872 | + ctx, Requirement("test-pkg==1.3.2"), req_type=RequirementType.TOP_LEVEL |
| 873 | + ) |
| 874 | + assert result is None |
| 875 | + |
| 876 | + |
| 877 | +def test_resolve_package_cooldown_enforced_transitive_equality_pin( |
| 878 | + tmp_path: pathlib.Path, |
| 879 | +) -> None: |
| 880 | + """Transitive == pin does NOT bypass cooldown.""" |
| 881 | + ctx = _make_ctx(tmp_path, cooldown=_COOLDOWN) |
| 882 | + result = resolver.resolve_package_cooldown( |
| 883 | + ctx, Requirement("test-pkg==1.3.2"), req_type=RequirementType.INSTALL |
| 884 | + ) |
| 885 | + assert result is _COOLDOWN |
| 886 | + |
| 887 | + |
| 888 | +def test_resolve_package_cooldown_enforced_toplevel_no_pin( |
| 889 | + tmp_path: pathlib.Path, |
| 890 | +) -> None: |
| 891 | + """Top-level requirement without == still gets cooldown.""" |
| 892 | + ctx = _make_ctx(tmp_path, cooldown=_COOLDOWN) |
| 893 | + result = resolver.resolve_package_cooldown( |
| 894 | + ctx, Requirement("test-pkg>=1.0"), req_type=RequirementType.TOP_LEVEL |
| 895 | + ) |
| 896 | + assert result is _COOLDOWN |
| 897 | + |
| 898 | + |
| 899 | +def test_resolve_package_cooldown_none_req_type_not_exempt( |
| 900 | + tmp_path: pathlib.Path, |
| 901 | +) -> None: |
| 902 | + """Unknown req_type (None) with == does NOT bypass cooldown.""" |
| 903 | + ctx = _make_ctx(tmp_path, cooldown=_COOLDOWN) |
| 904 | + result = resolver.resolve_package_cooldown( |
| 905 | + ctx, Requirement("test-pkg==1.3.2"), req_type=None |
| 906 | + ) |
| 907 | + assert result is _COOLDOWN |
| 908 | + |
| 909 | + |
| 910 | +def test_resolve_package_cooldown_toplevel_wildcard_equality_not_exempt( |
| 911 | + tmp_path: pathlib.Path, |
| 912 | +) -> None: |
| 913 | + """Top-level wildcard equality (==1.*) is not an exact pin — cooldown applies.""" |
| 914 | + ctx = _make_ctx(tmp_path, cooldown=_COOLDOWN) |
| 915 | + result = resolver.resolve_package_cooldown( |
| 916 | + ctx, Requirement("test-pkg==1.*"), req_type=RequirementType.TOP_LEVEL |
| 917 | + ) |
| 918 | + assert result is _COOLDOWN |
| 919 | + |
| 920 | + |
| 921 | +def test_resolve_package_cooldown_toplevel_compound_specifier_not_exempt( |
| 922 | + tmp_path: pathlib.Path, |
| 923 | +) -> None: |
| 924 | + """Top-level compound specifier (==1.0,>0.9) is not a single exact pin.""" |
| 925 | + ctx = _make_ctx(tmp_path, cooldown=_COOLDOWN) |
| 926 | + result = resolver.resolve_package_cooldown( |
| 927 | + ctx, Requirement("test-pkg==1.0,>0.9"), req_type=RequirementType.TOP_LEVEL |
| 928 | + ) |
| 929 | + assert result is _COOLDOWN |
0 commit comments