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

Massage queries so they are understood by libmambapy.Query #328

Merged
merged 7 commits into from
Oct 24, 2023
Merged
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
3 changes: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ jobs:
bash -c "sudo env CONDA_SOLVER=classic \
/opt/conda/condabin/conda install -p /opt/conda \
--repodata-fn=repodata.json --update-specs \
--file /opt/conda-src/tests/requirements.txt \
--file /opt/conda-src/tests/requirements-s3.txt \
--file /opt/conda-libmamba-solver-src/dev/requirements.txt \
--file /opt/conda-libmamba-solver-src/tests/requirements.txt &&
sudo /opt/conda/bin/python -m pip install /opt/conda-libmamba-solver-src --no-deps -vvv &&
Expand Down Expand Up @@ -158,6 +160,7 @@ jobs:
# install all test requirements
conda install --yes \
--file tests/requirements.txt \
--file tests/requirements-s3.txt \
--file ../conda-libmamba-solver/dev/requirements.txt \
--file ../conda-libmamba-solver/tests/requirements.txt \
python=${{ matrix.python-version }}
Expand Down
41 changes: 35 additions & 6 deletions conda_libmamba_solver/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,20 +320,26 @@ def _load_installed(self, records: Iterable[PackageRecord]) -> api.Repo:
repo.set_installed()
return repo

def whoneeds(self, query: str, records=True) -> Union[Iterable[PackageRecord], dict, str]:
result_str = self._query.whoneeds(query, self._format)
def whoneeds(
self, query: Union[str, MatchSpec], records=True
) -> Union[Iterable[PackageRecord], dict, str]:
result_str = self._query.whoneeds(self._prepare_query(query), self._format)
if self._format == api.QueryFormat.JSON:
return self._process_query_result(result_str, records=records)
return result_str

def depends(self, query: str, records=True) -> Union[Iterable[PackageRecord], dict, str]:
result_str = self._query.depends(query, self._format)
def depends(
self, query: Union[str, MatchSpec], records=True
) -> Union[Iterable[PackageRecord], dict, str]:
result_str = self._query.depends(self._prepare_query(query), self._format)
if self._format == api.QueryFormat.JSON:
return self._process_query_result(result_str, records=records)
return result_str

def search(self, query: str, records=True) -> Union[Iterable[PackageRecord], dict, str]:
result_str = self._query.find(query, self._format)
def search(
self, query: Union[str, MatchSpec], records=True
) -> Union[Iterable[PackageRecord], dict, str]:
result_str = self._query.find(self._prepare_query(query), self._format)
if self._format == api.QueryFormat.JSON:
return self._process_query_result(result_str, records=records)
return result_str
Expand All @@ -349,6 +355,29 @@ def explicit_pool(self, specs: Iterable[MatchSpec]) -> Iterable[str]:
explicit_pool.add(record.name)
return tuple(explicit_pool)

def _prepare_query(self, query: Union[str, MatchSpec]) -> str:
if isinstance(query, str):
if "[" not in query:
return query
query = MatchSpec(query)
# libmambapy.Query only supports some matchspec syntax
# https://github.com/conda/conda-libmamba-solver/issues/327
# NOTE: Channel specs are currently ignored by libmambapy.Query searches
# if query.get_raw_value("channel"):
# result = f"{query.get_raw_value('channel')}::{query.name}"
# if query.version and query.get_raw_value("version").startswith((">", "<", "!", "=")):
# result += query.get_raw_value("version")
# elif query.version:
# result += f"={query.get_raw_value('version')}"
# else:
# result += "=*"
# if query.get_raw_value("build"):
# result += f"={query.get_raw_value('build')}"
# return result
if not query.get_raw_value("version"):
query = MatchSpec(query, version="*")
return query.conda_build_form()

def _process_query_result(
self,
result_str,
Expand Down
2 changes: 1 addition & 1 deletion conda_libmamba_solver/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def compatible_specs(index, specs, raise_not_found=True):

matched = None
for spec in specs:
results = set(index.search(str(spec)))
results = set(index.search(spec))
if not results:
if raise_not_found:
exc = PackagesNotFoundError([spec], index._channels)
Expand Down
1 change: 1 addition & 0 deletions dev/linux/upstream_integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ sudo su root -c "/opt/conda/bin/conda install -yq conda-build"
# CONDA LIBMAMBA SOLVER CHANGES
sudo /opt/conda/bin/conda install --quiet -y --solver=classic --repodata-fn repodata.json \
--file "${CONDA_SRC}/tests/requirements.txt" \
--file "${CONDA_SRC}/tests/requirements-s3.txt" \
--file "${CONDA_LIBMAMBA_SOLVER_SRC}/dev/requirements.txt"
sudo /opt/conda/bin/python -m pip install "$CONDA_LIBMAMBA_SOLVER_SRC/dev/collect_upstream_conda_tests/"
sudo /opt/conda/bin/python -m pip install "$CONDA_LIBMAMBA_SOLVER_SRC" --no-deps -vvv
Expand Down
1 change: 1 addition & 0 deletions dev/linux/upstream_unit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ eval "$(sudo /opt/conda/bin/python -m conda init --dev bash)"
# CONDA LIBMAMBA SOLVER CHANGES
sudo /opt/conda/bin/conda install --quiet -y --solver=classic --repodata-fn repodata.json \
--file "${CONDA_SRC}/tests/requirements.txt" \
--file "${CONDA_SRC}/tests/requirements-s3.txt" \
--file "${CONDA_LIBMAMBA_SOLVER_SRC}/dev/requirements.txt"
sudo /opt/conda/bin/python -m pip install "$CONDA_LIBMAMBA_SOLVER_SRC/dev/collect_upstream_conda_tests/"
sudo /opt/conda/bin/python -m pip install "$CONDA_LIBMAMBA_SOLVER_SRC" --no-deps -vvv
Expand Down
19 changes: 19 additions & 0 deletions news/328-pins-queries
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
### Enhancements

* <news item>

### Bug fixes

* Massage bracket-containing specs (e.g. `ca-certificates[version='>=2023']`) so they are understood by `libmambapy.Query`, fixing a bug where `conda` would erroneously complain about no package records matching the configured pinned specs. (#327 via #328)

### Deprecations

* <news item>

### Docs

* <news item>

### Other

* <news item>
28 changes: 28 additions & 0 deletions tests/test_repoquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# SPDX-License-Identifier: BSD-3-Clause
import json

from conda_libmamba_solver.index import LibMambaIndexHelper

from .utils import conda_subprocess


Expand All @@ -18,3 +20,29 @@ def test_repoquery():
assert data["result"]["status"] == "OK"
assert len(data["result"]["pkgs"]) > 0
assert len([p for p in data["result"]["pkgs"] if p["name"] == "python"]) == 1


def test_query_search():
index = LibMambaIndexHelper(channels=["conda-forge"])
for query in (
"ca-certificates",
"ca-certificates =2022.9.24",
"ca-certificates >=2022.9.24",
"ca-certificates >2022.9.24",
"ca-certificates<2022.9.24,>2020",
"ca-certificates<=2022.9.24,>2020",
"ca-certificates !=2022.9.24,>2020",
"ca-certificates=*=*_0",
# TODO: channel specs are accepted but they seem to be ignored by libmambapy.Query!
# "defaults::ca-certificates",
# "defaults::ca-certificates=2022.9.24",
# "defaults::ca-certificates[version='>=2022.9.24']",
# "defaults::ca-certificates[build='*_0']",
):
results = index.search(query)
assert len(results) > 0, query

assert index.search("ca-certificates=*=*_0") == index.search("ca-certificates[build='*_0']")
assert index.search("ca-certificates >=2022.9.24") == index.search(
"ca-certificates[version='>=2022.9.24']"
)
37 changes: 37 additions & 0 deletions tests/test_solvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,3 +385,40 @@ def test_locking_pins():
assert not retcode
assert data.get("success")
assert data["message"] == "All requested packages already installed."


def test_ca_certificates_pins():
ca_certificates_pin = "ca-certificates=2023"
with make_temp_env() as prefix:
Path(prefix, "conda-meta").mkdir(exist_ok=True)
Path(prefix, "conda-meta", "pinned").write_text(f"{ca_certificates_pin}\n")

for cli_spec in (
"ca-certificates",
"ca-certificates=2023",
"ca-certificates>0",
"ca-certificates<2024",
"ca-certificates!=2022",
):
out, err, retcode = run_command(
"install",
prefix,
cli_spec,
"--dry-run",
"--json",
"--override-channels",
"-c",
"conda-forge",
use_exception_handler=True,
)
data = json.loads(out)
assert not retcode
assert data.get("success")
assert data.get("dry_run")

for pkg in data["actions"]["LINK"]:
if pkg["name"] == "ca-certificates":
assert pkg["version"].startswith("2023."), cli_spec
break
else:
raise AssertionError("ca-certificates not found in LINK actions")
Loading