Skip to content

Commit

Permalink
Merge pull request #56 from mariusvniekerk/fix-matchspecs
Browse files Browse the repository at this point in the history
Fix incorrect matchspec construction
  • Loading branch information
scopatz authored Oct 7, 2020
2 parents 2dd88f7 + 5c2d0f6 commit 4049bfc
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 49 deletions.
87 changes: 48 additions & 39 deletions conda_lock/conda_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,46 +197,11 @@ def make_lock_files(
else:
channels = lock_spec.channels

dry_run_install = solve_specs_for_arch(
conda=conda,
platform=lock_spec.platform,
channels=channels,
specs=lock_spec.specs,
lockfile_contents = create_lockfile_from_spec(
channels=channels, conda=conda, spec=lock_spec
)
with open(f"conda-{plat}.lock", "w") as fo:
fo.write(f"# platform: {plat}\n")
fo.write(f"# env_hash: {lock_spec.env_hash()}\n")
fo.write("@EXPLICIT\n")
link_actions = dry_run_install["actions"]["LINK"]
for link in link_actions:
link[
"url_base"
] = f"{link['base_url']}/{link['platform']}/{link['dist_name']}"
link["url"] = f"{link['url_base']}.tar.bz2"
link["url_conda"] = f"{link['url_base']}.conda"
link_dists = {link["dist_name"] for link in link_actions}

fetch_actions = dry_run_install["actions"]["FETCH"]

fetch_by_dist_name = {
fn_to_dist_name(pkg["fn"]): pkg for pkg in fetch_actions
}

non_fetch_packages = link_dists - set(fetch_by_dist_name)
if len(non_fetch_packages) > 0:
for search_res in search_for_md5s(
conda,
[x for x in link_actions if x["dist_name"] in non_fetch_packages],
plat,
):
dist_name = fn_to_dist_name(search_res["fn"])
fetch_by_dist_name[dist_name] = search_res

for pkg in link_actions:
url = fetch_by_dist_name[pkg["dist_name"]]["url"]
md5 = fetch_by_dist_name[pkg["dist_name"]]["md5"]
fo.write(f"{url}#{md5}")
fo.write("\n")
with open(f"conda-{lock_spec.platform}.lock", "w") as fo:
fo.write("\n".join(lockfile_contents) + "\n")

print("To use the generated lock files create a new environment:", file=sys.stderr)
print("", file=sys.stderr)
Expand All @@ -246,6 +211,50 @@ def make_lock_files(
print("", file=sys.stderr)


def create_lockfile_from_spec(
*, channels: Sequence[str], conda: PathLike, spec: LockSpecification
) -> List[str]:
dry_run_install = solve_specs_for_arch(
conda=conda,
platform=spec.platform,
channels=channels,
specs=spec.specs,
)
lockfile_contents = [
f"# platform: {spec.platform}",
f"# env_hash: {spec.env_hash()}\n",
"@EXPLICIT\n",
]

link_actions = dry_run_install["actions"]["LINK"]
for link in link_actions:
link["url_base"] = f"{link['base_url']}/{link['platform']}/{link['dist_name']}"
link["url"] = f"{link['url_base']}.tar.bz2"
link["url_conda"] = f"{link['url_base']}.conda"
link_dists = {link["dist_name"] for link in link_actions}

fetch_actions = dry_run_install["actions"]["FETCH"]

fetch_by_dist_name = {fn_to_dist_name(pkg["fn"]): pkg for pkg in fetch_actions}

non_fetch_packages = link_dists - set(fetch_by_dist_name)
if len(non_fetch_packages) > 0:
for search_res in search_for_md5s(
conda,
[x for x in link_actions if x["dist_name"] in non_fetch_packages],
spec.platform,
):
dist_name = fn_to_dist_name(search_res["fn"])
fetch_by_dist_name[dist_name] = search_res

for pkg in link_actions:
url = fetch_by_dist_name[pkg["dist_name"]]["url"]
md5 = fetch_by_dist_name[pkg["dist_name"]]["md5"]
lockfile_contents.append(f"{url}#{md5}")

return lockfile_contents


def main_on_docker(env_file, platforms):
env_path = pathlib.Path(env_file)
platform_arg = []
Expand Down
19 changes: 10 additions & 9 deletions conda_lock/src_parser/pyproject_toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,7 @@ def parse_poetry_pyproject_toml(
f"Unsupported type for dependency: {depname}: {depattrs:r}"
)
conda_version = poetry_version_to_conda_version(poetry_version_spec)

if conda_version:
spec = f"{conda_dep_name}[version{conda_version}]"
else:
spec = f"{conda_dep_name}"
spec = to_match_spec(conda_dep_name, conda_version)

if conda_dep_name == "python":
specs.insert(0, spec)
Expand All @@ -106,6 +102,14 @@ def parse_poetry_pyproject_toml(
return LockSpecification(specs=specs, channels=channels, platform=platform)


def to_match_spec(conda_dep_name, conda_version):
if conda_version:
spec = f"{conda_dep_name}[version='{conda_version}']"
else:
spec = f"{conda_dep_name}"
return spec


def parse_pyproject_toml(
pyproject_toml: pathlib.Path, platform: str, include_dev_dependencies: bool
):
Expand Down Expand Up @@ -137,10 +141,7 @@ def python_requirement_to_conda_spec(requirement: str):
conda_version = poetry_version_to_conda_version(collapsed_version)

conda_dep_name = normalize_pypi_name(name)
if conda_version:
return f"{conda_dep_name}[version{conda_version}]"
else:
return f"{conda_dep_name}"
return to_match_spec(conda_dep_name, conda_version)


def parse_flit_pyproject_toml(
Expand Down
36 changes: 35 additions & 1 deletion tests/test_conda_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@

import pytest

from conda_lock.conda_lock import parse_meta_yaml_file, run_lock
from conda_lock.conda_lock import (
create_lockfile_from_spec,
determine_conda_executable,
parse_meta_yaml_file,
run_lock,
)
from conda_lock.src_parser import LockSpecification
from conda_lock.src_parser.environment_yaml import parse_environment_file
from conda_lock.src_parser.pyproject_toml import (
parse_flit_pyproject_toml,
parse_poetry_pyproject_toml,
poetry_version_to_conda_version,
to_match_spec,
)


Expand Down Expand Up @@ -110,3 +118,29 @@ def test_run_lock_mamba(monkeypatch, zlib_environment):
raise pytest.skip("mamba is not installed")
monkeypatch.chdir(zlib_environment.parent)
run_lock(zlib_environment, conda_exe="mamba")


@pytest.mark.parametrize(
"package,version,url_pattern",
[
("python", ">=3.6,<3.7", "/python-3.6"),
("python", "~3.6", "/python-3.6"),
("python", "^2.7", "/python-2.7"),
],
)
def test_poetry_version_parsing_constraints(package, version, url_pattern):
_conda_exe = determine_conda_executable("conda", no_mamba=True)
spec = LockSpecification(
specs=[to_match_spec(package, poetry_version_to_conda_version(version))],
channels=["conda-forge"],
platform="linux-64",
)
lockfile_contents = create_lockfile_from_spec(
conda=_conda_exe, channels=spec.channels, spec=spec
)

for line in lockfile_contents:
if url_pattern in line:
break
else:
raise ValueError(f"could not find {package} {version}")

0 comments on commit 4049bfc

Please sign in to comment.