From 55276d68cd491ae0c332375d3cbc798f410f90bb Mon Sep 17 00:00:00 2001 From: Adrian Wolny Date: Wed, 21 Feb 2024 11:17:16 +0100 Subject: [PATCH] Prevent channel/dependency reordering when rendering the environment (#203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bruno Oliveira Co-authored-by: Martin PrĂ¼sse --- CHANGELOG.rst | 8 ++++++++ src/conda_devenv/devenv.py | 10 +++++----- tests/test_load_yaml_dict.py | 11 +++++++++++ tests/test_load_yaml_dict/deps_order.yml | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 tests/test_load_yaml_dict/deps_order.yml diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f871c70..04b8ab5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,14 @@ CHANGELOG ========= +UNRELEASED +---------- + +* Dependency order is no longer sorted automatically, instead the order is preserved as they are defined in the ``*.devenv.yml`` files. + Usually this would not matter, but it is important for ``pip`` dependencies which declare development installations, as it is important + that those happen in the specified order. + + 3.2.1 (2024-01-03) ------------------ diff --git a/src/conda_devenv/devenv.py b/src/conda_devenv/devenv.py index 3385d87..bf21a41 100644 --- a/src/conda_devenv/devenv.py +++ b/src/conda_devenv/devenv.py @@ -403,15 +403,15 @@ def merge_dependencies_version_specifications( else: raise UsageError(f"Only strings and dicts are supported, got: {dep!r}") - result = set() + # keep the order of dependencies + result: dict[str, Any] = collections.OrderedDict() for dep_name, dep_version_matchers in new_dependencies.items(): if len(dep_version_matchers) > 0: - result.add(dep_name + " " + ",".join(dep_version_matchers)) + result[dep_name + " " + ",".join(dep_version_matchers)] = None else: - result.add(dep_name) + result[dep_name] = None - new_dict_dependencies = sorted(new_dict_dependencies, key=lambda x: list(x.keys())) - yaml_dict[key_to_merge] = sorted(result) + new_dict_dependencies + yaml_dict[key_to_merge] = list(result.keys()) + new_dict_dependencies @dataclass(frozen=True) diff --git a/tests/test_load_yaml_dict.py b/tests/test_load_yaml_dict.py index cb51e7c..fc5bbe6 100644 --- a/tests/test_load_yaml_dict.py +++ b/tests/test_load_yaml_dict.py @@ -191,6 +191,17 @@ def test_downstream_overrides_platforms(tmp_path) -> None: } +def test_load_yaml_dict_dependency_order(datadir) -> None: + """ + Make sure the order of channels and pip dependencies is preserved + """ + conda_yaml_dict = load_yaml_dict(datadir / "deps_order.yml") + channels = conda_yaml_dict["channels"] + assert channels == ["pytorch", "nvidia", "conda-forge", "bioconda"] + pip_dependencies = conda_yaml_dict["dependencies"][3] + assert pip_dependencies["pip"] == ["-e c-package", "-e b-package", "-e D-package"] + + class TestConstraints: def test_no_constraints(self) -> None: data = {"dependencies": ["attrs >19", "boltons"]} diff --git a/tests/test_load_yaml_dict/deps_order.yml b/tests/test_load_yaml_dict/deps_order.yml new file mode 100644 index 0000000..b2ab624 --- /dev/null +++ b/tests/test_load_yaml_dict/deps_order.yml @@ -0,0 +1,16 @@ +name: test-env + +channels: + - pytorch + - nvidia + - conda-forge + - bioconda + +dependencies: + - pytorch + - numpy + - scikit-image + - pip: + - "-e c-package" + - "-e b-package" + - "-e D-package"