Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions envs/failing-env2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
channels:
- conda-forge
dependencies:
- package_no_version_not_in_exclude
22 changes: 22 additions & 0 deletions minimum_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,22 @@ def parse_environment(text):
return specs, warnings


def assert_spec_has_version(environments):
# packages in policy.exclude were already removed

for env, specs in environments.items():
for spec in specs:
if spec.version is None:

msg = (
f"No minimum version found for '{spec.name}' in '{env}'. Either"
" add a version or add to the list of excluded packages in the"
" policy file."
)

raise ValueError(msg)


def parse_policy(file):
policy = yaml.safe_load(file)
try:
Expand Down Expand Up @@ -344,6 +360,10 @@ def parse_date(string):
@click.option("--today", type=parse_date, default=None)
@click.option("--policy", "policy_file", type=click.File(mode="r"), required=True)
def main(today, policy_file, environment_paths):
_main(today, policy_file, environment_paths)


def _main(today, policy_file, environment_paths):
Comment on lines +363 to +366
Copy link
Member

@keewis keewis Sep 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we might need to clean this up a bit: currently _main would call sys.exit, which is not great for testing. It also should take the contents of the files instead of file handles / paths, which avoids the need to do I/O in the tests.

Additionally, _main is not really a descriptive name. How about something like validate_environment instead?

console = Console()

policy = parse_policy(policy_file)
Expand All @@ -360,6 +380,8 @@ def main(today, policy_file, environment_paths):
for env, (specs, _) in parsed_environments.items()
}

assert_spec_has_version(environments)

Comment on lines +383 to +384
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this should be done at the same time as applying exclude? I don't have the time to come up with something better right now, but assuming this isn't too urgent I will spend some time on this later this week.

all_packages = list(
dict.fromkeys(spec.name for spec in concat(environments.values()))
)
Expand Down
19 changes: 18 additions & 1 deletion test_script.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import datetime as dt
import pathlib

import pytest
from rattler import Version

from minimum_versions import Policy, Release, Spec
from minimum_versions import Policy, Release, Spec, _main


@pytest.mark.parametrize(
Expand All @@ -27,6 +28,22 @@ def test_spec_parse(text, expected_spec, expected_name, expected_warnings):
assert actual_warnings == expected_warnings


def test_error_missing_version_or_exclude():

msg = (
"No minimum version found for 'package_no_version_not_in_exclude' in"
" 'failing-env2'. Either add a version or add to the list of excluded packages"
" in the policy file."
)

with open("policy.yaml") as policy:

environment_paths = [pathlib.Path("envs/failing-env2.yaml")]

with pytest.raises(ValueError, match=msg):
_main(dt.date(2023, 12, 12), policy, environment_paths=environment_paths)


@pytest.mark.parametrize(
["package_name", "policy", "today", "expected"],
(
Expand Down
Loading