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
14 changes: 10 additions & 4 deletions example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ This would be the same as running `unidep merge --name myenv --verbose`:
📄 Parsing `setup_py_project/requirements.yaml`
📄 Parsing `../setuptools_project` from `local_dependencies`
📄 Parsing `setup_py_project/../setuptools_project/requirements.yaml`
📄 Parsing `../hatch_project[test]` from `local_dependencies`
📄 Parsing `setup_py_project/../setuptools_project/../hatch_project/requirements.yaml[test]`
📄 Moving `test` optional dependencies to main dependencies for `setup_py_project/../setuptools_project/../hatch_project/requirements.yaml[test]`
📄 Parsing `setuptools_project/requirements.yaml`
📄 Parsing `../hatch_project[test]` from `local_dependencies`
📄 Parsing `setuptools_project/../hatch_project/requirements.yaml[test]`
📄 Moving `test` optional dependencies to main dependencies for `setuptools_project/../hatch_project/requirements.yaml[test]`
📝 Generating environment file at `environment.yaml`
📝 Environment file generated successfully.
✅ Generated environment file at `environment.yaml` from `hatch2_project/pyproject.toml`, `hatch_project/requirements.yaml`, `pyproject_toml_project/pyproject.toml`, `setup_py_project/requirements.yaml`, `setuptools_project/requirements.yaml`
Expand Down Expand Up @@ -110,11 +116,11 @@ Using `unidep` for installation offers a more comprehensive approach. It handles
$ unidep install --dry-run -e ./setup_py_project
📦 Installing conda dependencies with `conda install --yes --override-channels --channel conda-forge pandas">=1,<3" adaptive">=0.15.0, <2.0.0" pfapack packaging adaptive-scheduler numpy">=1.21" hpc05 pexpect pytest pytest-cov`

📦 Installing pip dependencies with `/opt/hostedtoolcache/Python/3.13.1/x64/bin/python -m pip install yaml2bib rsync-time-machine slurm-usage pyyaml aiokef markdown-code-runner numthreads unidep`
📦 Installing pip dependencies with `/opt/hostedtoolcache/Python/3.13.2/x64/bin/python -m pip install yaml2bib rsync-time-machine slurm-usage pyyaml aiokef markdown-code-runner numthreads unidep`

📝 Found local dependencies: {'setup_py_project': ['hatch_project', 'setuptools_project']}

📦 Installing project with `/opt/hostedtoolcache/Python/3.13.1/x64/bin/python -m pip install --no-deps -e /home/runner/work/unidep/unidep/example/hatch_project -e /home/runner/work/unidep/unidep/example/setuptools_project -e ./setup_py_project`
📦 Installing project with `/opt/hostedtoolcache/Python/3.13.2/x64/bin/python -m pip install --no-deps -e /home/runner/work/unidep/unidep/example/hatch_project -e /home/runner/work/unidep/unidep/example/setuptools_project -e ./setup_py_project`

```

Expand Down Expand Up @@ -157,11 +163,11 @@ unidep install-all -e
$ unidep install-all -e --dry-run
📦 Installing conda dependencies with `conda install --yes --override-channels --channel conda-forge adaptive-scheduler numpy">=1.21" hpc05 pandas">=1,<3" pexpect adaptive">=0.15.0, <2.0.0" pfapack packaging pytest pytest-cov`

📦 Installing pip dependencies with `/opt/hostedtoolcache/Python/3.13.1/x64/bin/python -m pip install unidep markdown-code-runner numthreads yaml2bib rsync-time-machine slurm-usage pyyaml aiokef`
📦 Installing pip dependencies with `/opt/hostedtoolcache/Python/3.13.2/x64/bin/python -m pip install unidep markdown-code-runner numthreads yaml2bib rsync-time-machine slurm-usage pyyaml aiokef`

📝 Found local dependencies: {'pyproject_toml_project': ['hatch_project'], 'setup_py_project': ['hatch_project', 'setuptools_project'], 'setuptools_project': ['hatch_project']}

📦 Installing project with `/opt/hostedtoolcache/Python/3.13.1/x64/bin/python -m pip install --no-deps -e ./hatch2_project -e ./hatch_project -e ./pyproject_toml_project -e ./setup_py_project -e ./setuptools_project`
📦 Installing project with `/opt/hostedtoolcache/Python/3.13.2/x64/bin/python -m pip install --no-deps -e ./hatch2_project -e ./hatch_project -e ./pyproject_toml_project -e ./setup_py_project -e ./setuptools_project`

```

Expand Down
60 changes: 60 additions & 0 deletions tests/test_parse_yaml_local_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,66 @@ def test_circular_local_dependencies(
assert len(resolved["adaptive-scheduler"][None]) == 2


@pytest.mark.parametrize("toml_or_yaml", ["toml", "yaml"])
def test_circular_local_dependencies_with_common(
toml_or_yaml: Literal["toml", "yaml"],
tmp_path: Path,
) -> None:
project1 = tmp_path / "project1"
project1.mkdir(exist_ok=True, parents=True)
project2 = tmp_path / "project2"
project2.mkdir(exist_ok=True, parents=True)

r1 = project1 / "requirements.yaml"
r2 = project2 / "requirements.yaml"
r1.write_text(
textwrap.dedent(
"""\
dependencies:
- adaptive-scheduler
local_dependencies:
- ../project2
- ../project2 # duplicate include (shouldn't affect the result)
""",
),
)
# Test with old `includes` name
r2.write_text(
textwrap.dedent(
"""\
dependencies:
- adaptive
includes: # `local_dependencies` was called `includes` in <=0.41.0
- ../project1
- ../common-requirements.yaml
""",
),
)

# Add a common requirements file
common_requirements = tmp_path / "common-requirements.yaml"
common_requirements.write_text("dependencies: [unidep]")

r1 = maybe_as_toml(toml_or_yaml, r1)
# Only convert r1 to toml, not r2, because we want to test that
with pytest.warns(DeprecationWarning, match="is deprecated since 0.42.0"):
requirements = parse_requirements(r1, r2, verbose=False)
# Both will be duplicated because of the circular dependency
# but `resolve_conflicts` will remove the duplicates
assert len(requirements.requirements["adaptive"]) == 4
assert len(requirements.requirements["adaptive-scheduler"]) == 2
unidep = requirements.requirements["unidep"]
assert len(unidep) == 4
resolved = resolve_conflicts(requirements.requirements, requirements.platforms)
assert len(resolved["adaptive"]) == 1
assert len(resolved["adaptive"][None]) == 2
assert len(resolved["adaptive-scheduler"]) == 1
assert len(resolved["adaptive-scheduler"][None]) == 2
unidep_origin = resolved["unidep"][None]["conda"].origin
# Should have all 3 files in its origin
assert len(unidep_origin) == 3


@pytest.mark.parametrize("toml_or_yaml", ["toml", "yaml"])
def test_parse_local_dependencies(
toml_or_yaml: Literal["toml", "yaml"],
Expand Down
60 changes: 50 additions & 10 deletions tests/test_project_dependency_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
parse_requirements,
)
from unidep.platform_definitions import Spec
from unidep.utils import PathWithExtras

if TYPE_CHECKING:
from pathlib import Path
Expand Down Expand Up @@ -100,33 +101,72 @@ def test_project_dependency_handling_in_pyproject_toml(
)

requirements = parse_requirements(p)

ori = (PathWithExtras(p, []),)
expected = {
"python-graphviz": [
Spec(name="python-graphviz", which="conda", identifier="17e5d607"),
Spec(
name="python-graphviz",
which="conda",
identifier="17e5d607",
origin=ori,
),
],
"graphviz": [
Spec(name="graphviz", which="pip", identifier="17e5d607"),
Spec(name="graphviz", which="conda", identifier="5eb93b8c"),
Spec(name="graphviz", which="pip", identifier="17e5d607", origin=ori),
Spec(name="graphviz", which="conda", identifier="5eb93b8c", origin=ori),
],
}
if project_dependency_handling == "pip-only":
expected.update(
{
"requests": [Spec(name="requests", which="pip", identifier="08fd8713")],
"pandas": [Spec(name="pandas", which="pip", identifier="9e467fa1")],
"requests": [
Spec(
name="requests",
which="pip",
identifier="08fd8713",
origin=ori,
),
],
"pandas": [
Spec(
name="pandas",
which="pip",
identifier="9e467fa1",
origin=ori,
),
],
},
)
elif project_dependency_handling == "same-name":
expected.update(
{
"requests": [
Spec(name="requests", which="conda", identifier="08fd8713"),
Spec(name="requests", which="pip", identifier="08fd8713"),
Spec(
name="requests",
which="conda",
identifier="08fd8713",
origin=ori,
),
Spec(
name="requests",
which="pip",
identifier="08fd8713",
origin=ori,
),
],
"pandas": [
Spec(name="pandas", which="conda", identifier="9e467fa1"),
Spec(name="pandas", which="pip", identifier="9e467fa1"),
Spec(
name="pandas",
which="conda",
identifier="9e467fa1",
origin=ori,
),
Spec(
name="pandas",
which="pip",
identifier="9e467fa1",
origin=ori,
),
],
},
)
Expand Down
Loading
Loading