Skip to content

Commit

Permalink
Merge pull request #499 from jacksmith15/feat/464/support-v2-lockfile…
Browse files Browse the repository at this point in the history
…s-with-any-name

Detect lockfile type based on contents rather than filename
  • Loading branch information
maresb authored Sep 8, 2023
2 parents 18d77b2 + cb36182 commit 5cd7ab7
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 10 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ and update operations. You can supply a different filename with e.g.
conda-lock --lockfile superspecial.conda-lock.yml
```

The extension `.conda-lock.yml` will be added if not present. Rendered
environment files (env or explicit) must end with `.lock` and will be named as
`"conda-{platform}.lock"` by default.
Rendered `explicit` and `env` lockfiles will be named as `"conda-{platform}.lock"` and `"conda-{platform}.lock.yml` respectively by default.

If you want to override that call conda-lock as follows.
```bash
Expand All @@ -89,7 +87,7 @@ conda-lock -k explicit --filename-template "specific-{platform}.conda.lock"
Conda-lock will build a spec list from several files if requested.

```bash
conda-lock -f base.yml -f specific.yml -p linux-64 --filename-template "specific-{platform}.lock"
conda-lock -f base.yml -f specific.yml -p linux-64 -k explicit --filename-template "specific-{platform}.lock"
````

In this case all dependencies are combined, and the ordered union of all `channels` is used as the final
Expand Down
36 changes: 31 additions & 5 deletions conda_lock/conda_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import yaml

from ensureconda.api import ensureconda
from ensureconda.resolve import platform_subdir
from typing_extensions import Literal

from conda_lock.click_helpers import OrderedGroup
Expand All @@ -54,7 +55,11 @@
determine_conda_executable,
is_micromamba,
)
from conda_lock.lockfile import parse_conda_lock_file, write_conda_lock_file
from conda_lock.lockfile import (
UnknownLockfileVersion,
parse_conda_lock_file,
write_conda_lock_file,
)
from conda_lock.lockfile.v2prelim.models import (
GitMeta,
InputMeta,
Expand Down Expand Up @@ -139,6 +144,10 @@
"""


class UnknownLockfileKind(ValueError):
pass


def _extract_platform(line: str) -> Optional[str]:
search = PLATFORM_PATTERN.search(line)
if search:
Expand Down Expand Up @@ -932,13 +941,11 @@ def _render_lockfile_for_install(
Optional dependency groups to include in output
"""

if not filename.name.endswith(DEFAULT_LOCKFILE_NAME):
kind = _detect_lockfile_kind(pathlib.Path(filename))
if kind in ("explicit", "env"):
yield filename
return

from ensureconda.resolve import platform_subdir

lock_content = parse_conda_lock_file(pathlib.Path(filename))

platform = platform_subdir()
Expand Down Expand Up @@ -984,6 +991,25 @@ def _render_lockfile_for_install(
yield path


def _detect_lockfile_kind(path: pathlib.Path) -> TKindAll:
content = path.read_text(encoding="utf-8")
if "@EXPLICIT" in {line.strip() for line in content.splitlines()}:
return "explicit"
try:
lockfile = yaml.safe_load(content)
if {"channels", "dependencies"} <= set(lockfile):
return "env"
if "version" in lockfile:
# Version validation is handled by `lockfile.parse_conda_lock_file`
return "lock"
raise UnknownLockfileKind(f"Could not detect the kind of lockfile at {path}")
except yaml.YAMLError:
raise UnknownLockfileKind(
f"Could not detect the kind of lockfile at {path}. Note that explicit "
"lockfiles must contain the line '@EXPLICIT'."
)


def run_lock(
environment_files: List[pathlib.Path],
*,
Expand Down
12 changes: 11 additions & 1 deletion conda_lock/lockfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
from conda_lock.models.lock_spec import Dependency


class MissingLockfileVersion(ValueError):
pass


class UnknownLockfileVersion(ValueError):
pass


def _seperator_munge_get(
d: Mapping[str, Union[List[LockedDependency], LockedDependency]], key: str
) -> Union[List[LockedDependency], LockedDependency]:
Expand Down Expand Up @@ -135,8 +143,10 @@ def parse_conda_lock_file(path: pathlib.Path) -> Lockfile:
version = content.pop("version", None)
if version == 1:
return lockfile_v1_to_v2(LockfileV1.parse_obj(content))
elif version is None:
raise MissingLockfileVersion(f"{path} is missing a version")
else:
raise ValueError(f"{path} has unknown version {version}")
raise UnknownLockfileVersion(f"{path} has unknown version {version}")


def write_conda_lock_file(
Expand Down

0 comments on commit 5cd7ab7

Please sign in to comment.