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

Fix cache zip and expanduser errors #110

Merged
merged 10 commits into from
May 27, 2023
7 changes: 7 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ on:
- "docs/**"
branches:
- main


jobs:
package:
name: Build package
Expand Down Expand Up @@ -79,6 +81,9 @@ jobs:
shell: bash
run: |
./conda.exe create -p $HOME/miniconda conda=${{ matrix.conda-version }} python=${{ matrix.python-version }}
- name: Update with test dependencies
shell: bash
run: |
if [ $RUNNER_OS == 'Windows' ]; then
source $HOME/miniconda/Scripts/activate root && conda env update -f etc/test-environment.yml -p $HOME/miniconda && $HOME/miniconda/Scripts/pip install --no-deps .
else
Expand All @@ -98,6 +103,8 @@ jobs:
fi
- name: py.test
shell: bash
env:
CONDA_DEFAULT_CHANNELS: conda-forge
run: |
if [ $RUNNER_OS == 'Windows' ]; then
source $HOME/miniconda/Scripts/activate root && \
Expand Down
9 changes: 5 additions & 4 deletions src/conda_project/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class CondaProject:
"""

def __init__(self, directory: Union[Path, str] = "."):
self.directory = Path(directory).resolve()
self.directory = Path(directory).expanduser().resolve()
logger.info(f"created Project instance at {self.directory}")

self.project_yaml_path = find_file(self.directory, PROJECT_YAML_FILENAMES)
Expand Down Expand Up @@ -148,14 +148,15 @@ def from_archive(
):
"""Extra a conda-project archive and load the project"""

if isinstance(output_directory, str):
output_directory = Path(output_directory)
output_directory = Path(output_directory).expanduser()

storage_options = {} if storage_options is None else storage_options
protocol, _ = split_protocol(fn)
if protocol is not None:
options = {protocol: storage_options}
fn = f"simplecache::{fn}"
else:
fn = Path(fn).expanduser()
options = {}

files = fsspec.open_files(f"libarchive://**::{fn}", **options)
Expand Down Expand Up @@ -243,7 +244,7 @@ def init(

"""

directory = Path(directory).resolve()
directory = Path(directory).expanduser().resolve()
if not directory.exists():
directory.mkdir(parents=True)

Expand Down
35 changes: 35 additions & 0 deletions tests/test_archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from conda_project.exceptions import CondaProjectError
from conda_project.project import CondaProject
from conda_project.utils import is_windows

ASSETS_DIR = Path(__file__).parents[0] / "assets"

Expand Down Expand Up @@ -123,3 +124,37 @@ def test_archive_storage_options(mocker):
assert mocked_open_files.call_args_list[0].kwargs == {
"file": {"key1": "valueA", "key2": "valueB"}
}
assert "simplecache" in mocked_open_files.call_args_list[0].args[0]


def test_archive_path_expanduser(mocker):
from pathlib import Path

expanduser = mocker.spy(Path, "expanduser")

archive = "~__a-conda-project-user__/project.tar.gz"
if is_windows():
with pytest.raises(FileNotFoundError):
_ = CondaProject.from_archive(fn=archive)
else:
with pytest.raises(RuntimeError):
_ = CondaProject.from_archive(fn=archive)

assert expanduser.call_count == 2


def test_archive_output_directory_expanduser(mocker):
from pathlib import Path

expanduser = mocker.spy(Path, "expanduser")

archive = ASSETS_DIR / "top-level-dir.tar.gz"

output_directory = "~__a-conda-project-user__/project"
if is_windows():
_ = CondaProject.from_archive(fn=archive, output_directory=output_directory)
assert expanduser.call_count == 3
else:
with pytest.raises(RuntimeError):
_ = CondaProject.from_archive(fn=archive, output_directory=output_directory)
assert expanduser.call_count == 1
188 changes: 188 additions & 0 deletions tests/test_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Copyright (C) 2022 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause
import logging
import os
from textwrap import dedent

import pytest
from ruamel.yaml import YAML

from conda_project.exceptions import CondaProjectError
from conda_project.project import DEFAULT_PLATFORMS, CondaProject
from conda_project.utils import is_windows


def test_project_init_expanduser(mocker):
from pathlib import Path

expanduser = mocker.spy(Path, "expanduser")

project_directory = "~__a-conda-project-user__/project"

if is_windows():
_ = CondaProject(project_directory)
else:
with pytest.raises(RuntimeError):
_ = CondaProject(project_directory)

assert expanduser.call_count == 1


def test_project_init_new_directory(tmp_path, capsys):
project_directory = tmp_path / "new-project"
assert not os.path.exists(project_directory)

p = CondaProject.init(project_directory, lock_dependencies=False, verbose=True)

assert os.path.exists(project_directory)
assert p.project_yaml_path.exists()
assert p.default_environment.sources[0].exists()
assert not p.default_environment.is_locked

assert p.condarc.exists()
with p.condarc.open() as f:
condarc = YAML().load(f)
assert condarc == {}

out, _ = capsys.readouterr()
assert f"Project created at {project_directory}\n" == out


def test_project_init_twice(tmp_path, capsys):
_ = CondaProject.init(tmp_path, lock_dependencies=False)
p = CondaProject.init(tmp_path, lock_dependencies=False, verbose=True)

out, _ = capsys.readouterr()
assert f"Existing project file found at {p.project_yaml_path}.\n" == out


def test_project_init_default_platforms(tmp_path):
p = CondaProject.init(tmp_path, lock_dependencies=False)

with p.default_environment.sources[0].open() as f:
env = YAML().load(f)

assert env["platforms"] == list(DEFAULT_PLATFORMS)


def test_project_init_specific_platforms(tmp_path):
p = CondaProject.init(tmp_path, platforms=["linux-64"], lock_dependencies=False)

with p.default_environment.sources[0].open() as f:
env = YAML().load(f)

assert env["platforms"] == ["linux-64"]


def test_project_init_specific_channels(tmp_path):
p = CondaProject.init(
tmp_path,
dependencies=["python=3.8", "numpy"],
channels=["conda-forge", "defaults"],
lock_dependencies=False,
)

with p.default_environment.sources[0].open() as f:
env = YAML().load(f)

assert env["dependencies"] == ["python=3.8", "numpy"]
assert env["channels"] == ["conda-forge", "defaults"]


def test_project_init_default_channel(tmp_path):
p = CondaProject.init(
tmp_path, dependencies=["python=3.8", "numpy"], lock_dependencies=False
)

with p.default_environment.sources[0].open() as f:
env = YAML().load(f)

assert env["dependencies"] == ["python=3.8", "numpy"]
assert env["channels"] == ["defaults"]


def test_project_init_conda_configs(tmp_path):
p = CondaProject.init(
tmp_path,
dependencies=["python=3.8", "numpy"],
conda_configs=["experimental_solver=libmamba"],
lock_dependencies=False,
)

with p.condarc.open() as f:
condarc = YAML().load(f)

assert condarc["experimental_solver"] == "libmamba"


@pytest.mark.slow
def test_project_init_and_lock(tmp_path):
p = CondaProject.init(tmp_path, dependencies=["python=3.8"], lock_dependencies=True)
assert p.default_environment.lockfile.exists()
assert p.default_environment.lockfile == tmp_path / "conda-lock.default.yml"


def test_project_directory_expanduser(mocker):
from pathlib import Path

expanduser = mocker.spy(Path, "expanduser")

directory = "~__a-conda-project-user__/project"
if is_windows():
_ = CondaProject(directory)
else:
with pytest.raises(RuntimeError):
_ = CondaProject(directory)

assert expanduser.call_count == 1


def test_conda_project_init_empty_dir(tmp_path, caplog):
caplog.set_level(logging.INFO)

with pytest.raises(CondaProjectError) as excinfo:
CondaProject(tmp_path)
assert "No conda environment.yml or environment.yaml file was found" in str(
excinfo.value
)

assert "No conda-project.yml or conda-project.yaml file was found" in caplog.text


def test_conda_project_init_with_env_yaml(project_directory_factory):
env_yaml = dedent(
"""\
name: test
dependencies: []
"""
)
project_path = project_directory_factory(env_yaml=env_yaml)
project = CondaProject(project_path)

assert project.default_environment == project.environments["default"]

assert (
project.default_environment.lockfile
== project.directory / "conda-lock.default.yml"
)
assert project.default_environment.sources == (
(project.directory / "environment").with_suffix(
project_directory_factory._suffix
),
)
assert project.default_environment.prefix == project.directory / "envs" / "default"


def test_project_init_resolves_cwd(monkeypatch, project_directory_factory):
project_path = project_directory_factory(env_yaml="")
monkeypatch.chdir(project_path)

project = CondaProject()
assert project.directory.samefile(project_path)


def test_project_init_path(project_directory_factory):
project_path = project_directory_factory(env_yaml="")

project = CondaProject(project_path)
assert project.directory.samefile(project_path)
Loading