Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platforms and channels are now defined by the most-downstream devenv file #212

Merged
merged 1 commit into from
Jul 22, 2024
Merged
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
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
CHANGELOG
=========

3.4.0 (UNRELEASED)
------------------

* Previously the ``name``, ``channels``, and ``platforms`` keys would only be overwritten by the root ``devenv.yml`` file (the one use to invoke ``conda devenv`` with).
Now any downstream ``devenv.yml`` file will override these keys, with the most downstream ``devenv.yml`` file "winning", which was always the intended behavior.

3.3.0 (2024-02-21)
------------------

Expand Down
11 changes: 7 additions & 4 deletions src/conda_devenv/devenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,10 +499,13 @@ def load_yaml_dict(

merge_dependencies_version_specifications(merged_dict, key_to_merge="dependencies")

# Force these keys to always be set by the starting/root devenv file, when defined.
force_root_keys = ("name", "channels", "platforms")
forced_keys = {k: root_yaml[k] for k in force_root_keys if k in root_yaml}
merged_dict.update(forced_keys)
# Force these keys to always be set by the most downstream devenv file.
# all_yaml_dicts is ordered from downstream to upstream.
for forced_key in ("name", "channels", "platforms"):
for yaml_dict in all_yaml_dicts.values():
if forced_key in yaml_dict:
merged_dict[forced_key] = yaml_dict[forced_key]
break

if "environment" not in merged_dict:
merged_dict["environment"] = {}
Expand Down
213 changes: 209 additions & 4 deletions tests/test_load_yaml_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ def test_downstream_overrides_channels(tmp_path) -> None:
)
)

# This is the most downstream file which defines 'channels', so it overwrites any
# upstream definition.
b_fn = tmp_path / "b.devenv.yml"
b_fn.write_text(
textwrap.dedent(
Expand All @@ -150,13 +152,114 @@ def test_downstream_overrides_channels(tmp_path) -> None:
)
)

assert load_yaml_dict(b_fn) == {
"name": "b",
c_fn = tmp_path / "c.devenv.yml"
c_fn.write_text(
textwrap.dedent(
"""
name: c
includes:
- {{ root }}/b.devenv.yml
"""
)
)

assert load_yaml_dict(c_fn) == {
"name": "c",
"channels": ["b1_channel", "b2_channel"],
"environment": {},
}


def test_no_downstream_overrides_channels(tmp_path) -> None:
# The 'channels' key is defined only by one upstream file.
a_fn = tmp_path / "a.devenv.yml"
a_fn.write_text(
textwrap.dedent(
"""
name: a
channels:
- z_channel
- a_channel
"""
)
)

b_fn = tmp_path / "b.devenv.yml"
b_fn.write_text(
textwrap.dedent(
"""
name: b
includes:
- {{ root }}/a.devenv.yml
"""
)
)

c_fn = tmp_path / "c.devenv.yml"
c_fn.write_text(
textwrap.dedent(
"""
name: c
includes:
- {{ root }}/b.devenv.yml
"""
)
)

assert load_yaml_dict(c_fn) == {
"name": "c",
"channels": ["z_channel", "a_channel"],
"environment": {},
}


def test_root_overrides_channels(tmp_path) -> None:
a_fn = tmp_path / "a.devenv.yml"
a_fn.write_text(
textwrap.dedent(
"""
name: a
channels:
- z_channel
- a_channel
"""
)
)

b_fn = tmp_path / "b.devenv.yml"
b_fn.write_text(
textwrap.dedent(
"""
name: b
includes:
- {{ root }}/a.devenv.yml
"""
)
)

# This is the root file, so it overwrites the 'channels' completely.
c_fn = tmp_path / "c.devenv.yml"
c_fn.write_text(
textwrap.dedent(
"""
name: c
includes:
- {{ root }}/b.devenv.yml
channels:
- a_channel
- z_channel
- b_channel
"""
)
)

assert load_yaml_dict(c_fn) == {
"name": "c",
"channels": ["a_channel", "z_channel", "b_channel"],
"environment": {},
}


def test_downstream_overrides_platforms(tmp_path) -> None:
a_fn = tmp_path / "a.devenv.yml"
a_fn.write_text(
Expand All @@ -170,22 +273,124 @@ def test_downstream_overrides_platforms(tmp_path) -> None:
)
)

# This is the most downstream file which defines 'platforms', so it overwrites any
# upstream definition.
b_fn = tmp_path / "b.devenv.yml"
b_fn.write_text(
textwrap.dedent(
"""
name: b
includes:
- {{ root }}/a.devenv.yml
platforms:
- win-64
- osx-64
"""
)
)

c_fn = tmp_path / "c.devenv.yml"
c_fn.write_text(
textwrap.dedent(
"""
name: c
includes:
- {{ root }}/b.devenv.yml
"""
)
)

assert load_yaml_dict(c_fn) == {
"name": "c",
"platforms": ["win-64", "osx-64"],
"environment": {},
}


def test_no_downstream_overrides_platforms(tmp_path) -> None:
# The 'platforms' key is defined only by one upstream file.
a_fn = tmp_path / "a.devenv.yml"
a_fn.write_text(
textwrap.dedent(
"""
name: a
platforms:
- win-64
- linux-64
"""
)
)

b_fn = tmp_path / "b.devenv.yml"
b_fn.write_text(
textwrap.dedent(
"""
name: b
includes:
- {{ root }}/a.devenv.yml
"""
)
)

c_fn = tmp_path / "c.devenv.yml"
c_fn.write_text(
textwrap.dedent(
"""
name: c
includes:
- {{ root }}/b.devenv.yml
"""
)
)

assert load_yaml_dict(c_fn) == {
"name": "c",
"platforms": ["win-64", "linux-64"],
"environment": {},
}


def test_root_overrides_platforms(tmp_path) -> None:
a_fn = tmp_path / "a.devenv.yml"
a_fn.write_text(
textwrap.dedent(
"""
name: a
platforms:
- win-64
- linux-64
"""
)
)

b_fn = tmp_path / "b.devenv.yml"
b_fn.write_text(
textwrap.dedent(
"""
name: b
includes:
- {{ root }}/a.devenv.yml
"""
)
)

# This is the root file, so it overwrites the 'platforms' completely.
c_fn = tmp_path / "c.devenv.yml"
c_fn.write_text(
textwrap.dedent(
"""
name: c
includes:
- {{ root }}/b.devenv.yml
platforms:
- win-64
- osx-64
"""
)
)

assert load_yaml_dict(b_fn) == {
"name": "b",
assert load_yaml_dict(c_fn) == {
"name": "c",
"platforms": ["win-64", "osx-64"],
"environment": {},
}
Expand Down
Loading