diff --git a/envs/pixi.toml b/envs/pixi.toml index 365e095..767cf67 100644 --- a/envs/pixi.toml +++ b/envs/pixi.toml @@ -11,7 +11,11 @@ python = "3.10" [feature.failing.dependencies] numpy = "2.1" +[feature.exclude.dependencies] +pytest = "!=9.1.0" + [environments] env1 = { features = ["py310"] } env2 = ["py39"] failing-env = { features = ["failing"] } +exclude-env = { features = ["exclude"] } diff --git a/minimum_versions/environments/pixi.py b/minimum_versions/environments/pixi.py index 9508413..e83c2af 100644 --- a/minimum_versions/environments/pixi.py +++ b/minimum_versions/environments/pixi.py @@ -11,6 +11,7 @@ version_re = re.compile(f"(?P{_version_re})") lower_pin_re = re.compile(rf">=(?P{_version_re})$") tight_pin_re = re.compile(rf">=(?P{_version_re}),<(?P{_version_re})") +exclusion_pin_re = re.compile(rf"!=(?P{_version_re})$") def parse_spec(name, version_text: str | dict): @@ -44,6 +45,13 @@ def parse_spec(name, version_text: str | dict): ) raw_version = lower_pin + elif (match := exclusion_pin_re.match(version_text)) is not None: + excluded = match.group("excluded") + warnings.append( + f"Excluded version found: {excluded!r}. This is invalid for policy packages" + " and must be ignored explicitly." + ) + raw_version = excluded else: raise ValueError(f"Unsupported version spec: {version_text}") @@ -110,7 +118,7 @@ def parse_pixi_environment(name: str, manifest_path: pathlib.Path | None): ( get_in([feature, "dependencies"], all_features, {}) if feature != "default" - else pixi_config.get("dependencies", []) + else pixi_config.get("dependencies", {}) ) for feature in feature_names ] diff --git a/minimum_versions/main.py b/minimum_versions/main.py index 4857c2a..e777725 100644 --- a/minimum_versions/main.py +++ b/minimum_versions/main.py @@ -61,7 +61,8 @@ def validate(today, policy_file, manifest_path, environment_paths): } warnings = { - env: dict(warnings_) for env, (_, warnings_) in parsed_environments.items() + env: {n: w for n, w in warnings_ if n not in policy.exclude} + for env, (_, warnings_) in parsed_environments.items() } environments = { env: [spec for spec in specs if spec.name not in policy.exclude] diff --git a/minimum_versions/tests/test_environments.py b/minimum_versions/tests/test_environments.py index d25a083..1de5cb5 100644 --- a/minimum_versions/tests/test_environments.py +++ b/minimum_versions/tests/test_environments.py @@ -357,6 +357,32 @@ def test_parse_spec_error(self, version_text): [("c", [])], id="local_package", ), + pytest.param( + textwrap.dedent("""\ + [feature.feature1.dependencies] + a = "!=1.0.1" + + [environments] + env1 = { features = ["feature1"] } + """.rstrip()), + "pixi.toml", + [ + Spec("a", Version("1.0.1")), + ], + [ + ( + "a", + [ + ( + "Excluded version found: '1.0.1'. This is invalid for policy packages" + " and must be ignored explicitly." + ), + "package should be pinned to a minor version (got 1.0.1)", + ], + ) + ], + id="excluded_version", + ), ), ) def test_parse_pixi_environment(