Skip to content

Commit

Permalink
Update conda inspect channels (conda#5033)
Browse files Browse the repository at this point in the history
Use modern `solver` & `transactions` logic instead of legacy `get_index` & `actions`.

---------

Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
  • Loading branch information
kenodegard and jaimergp authored Dec 8, 2023
1 parent 5eba8d6 commit 37ab8d3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 69 deletions.
16 changes: 7 additions & 9 deletions conda_build/cli/main_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,10 @@ def parse_args(args):
"--test-installable",
"-t",
action="store_true",
help="""Test every package in the channel to see if it is installable
by conda.""",
help=(
"DEPRECATED. This is the default (and only) behavior. "
"Test every package in the channel to see if it is installable by conda."
),
)
channels.add_argument(
"channel",
Expand Down Expand Up @@ -184,13 +186,9 @@ def execute(args):

if not args.subcommand:
parser.print_help()
exit()

sys.exit(0)
elif args.subcommand == "channels":
if not args.test_installable:
parser.error("At least one option (--test-installable) is required.")
else:
print(api.test_installable(args.channel))
print(api.test_installable(args.channel))
elif args.subcommand == "linkages":
print(
api.inspect_linkages(
Expand Down Expand Up @@ -219,7 +217,7 @@ def execute(args):
elif args.subcommand == "hash-inputs":
pprint(api.inspect_hash_inputs(args.packages))
else:
raise ValueError(f"Unrecognized subcommand: {args.subcommand}.")
parser.error(f"Unrecognized subcommand: {args.subcommand}.")


@deprecated("3.26.0", "24.1.0", addendum="Use `conda inspect` instead.")
Expand Down
96 changes: 36 additions & 60 deletions conda_build/inspect_pkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,24 @@

import json
import os
import re
import sys
import tempfile
from collections import defaultdict
from functools import lru_cache
from itertools import groupby
from operator import itemgetter
from os.path import abspath, basename, dirname, exists, join
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Iterable, Literal

from conda.api import Solver
from conda.core.index import get_index
from conda.core.prefix_data import PrefixData
from conda.models.dist import Dist
from conda.models.records import PrefixRecord
from conda.resolve import MatchSpec

from conda_build.conda_interface import (
display_actions,
get_index,
install_actions,
linked_data,
specs_from_args,
)
Expand All @@ -39,12 +37,14 @@
ensure_list,
get_logger,
package_has_file,
rm_rf,
)

from . import conda_interface
from .deprecations import deprecated
from .utils import on_mac, on_win, samefile

log = get_logger(__name__)


@deprecated("3.28.0", "24.1.0")
@lru_cache(maxsize=None)
Expand Down Expand Up @@ -103,23 +103,21 @@ def __str__(self):
untracked_package = _untracked_package()


@deprecated.argument("24.1.0", "24.3.0", "platform", rename="subdir")
@deprecated.argument("24.1.0", "24.3.0", "prepend")
@deprecated.argument("24.1.0", "24.3.0", "minimal_hint")
def check_install(
packages, platform=None, channel_urls=(), prepend=True, minimal_hint=False
):
prefix = tempfile.mkdtemp("conda")
try:
specs = specs_from_args(packages)
index = get_index(
channel_urls=channel_urls, prepend=prepend, platform=platform, prefix=prefix
)
actions = install_actions(
prefix, index, specs, pinned=False, minimal_hint=minimal_hint
)
display_actions(actions, index)
return actions
finally:
rm_rf(prefix)
return None
packages: Iterable[str],
subdir: str | None = None,
channel_urls: Iterable[str] = (),
) -> None:
with TemporaryDirectory() as prefix:
Solver(
prefix,
channel_urls,
[subdir or conda_interface.subdir],
specs_from_args(packages),
).solve_for_transaction(ignore_pinned=True).print_transaction_summary()


def print_linkages(
Expand Down Expand Up @@ -183,61 +181,39 @@ def replace_path(binary, path, prefix):
return "not found"


def test_installable(channel="defaults"):
def test_installable(channel: str = "defaults") -> bool:
success = True
log = get_logger(__name__)
has_py = re.compile(r"py(\d)(\d)")
for platform in ["osx-64", "linux-32", "linux-64", "win-32", "win-64"]:
log.info("######## Testing platform %s ########", platform)
channels = [channel]
index = get_index(channel_urls=channels, prepend=False, platform=platform)
for _, rec in index.items():
# If we give channels at the command line, only look at
# packages from those channels (not defaults).
if channel != "defaults" and rec.get("schannel", "defaults") == "defaults":
continue
name = rec["name"]
for subdir in ["osx-64", "linux-32", "linux-64", "win-32", "win-64"]:
log.info("######## Testing subdir %s ########", subdir)
for prec in get_index(channel_urls=[channel], prepend=False, platform=subdir):
name = prec["name"]
if name in {"conda", "conda-build"}:
# conda can only be installed in the root environment
continue
if name.endswith("@"):
elif name.endswith("@"):
# this is a 'virtual' feature record that conda adds to the index for the solver
# and should be ignored here
continue
# Don't fail just because the package is a different version of Python
# than the default. We should probably check depends rather than the
# build string.
build = rec["build"]
match = has_py.search(build)
assert match if "py" in build else True, build
if match:
additional_packages = [f"python={match.group(1)}.{match.group(2)}"]
else:
additional_packages = []

version = rec["version"]
version = prec["version"]
log.info("Testing %s=%s", name, version)

try:
install_steps = check_install(
[name + "=" + version] + additional_packages,
channel_urls=channels,
check_install(
[f"{name}={version}"],
channel_urls=[channel],
prepend=False,
platform=platform,
subdir=subdir,
)
success &= bool(install_steps)
except KeyboardInterrupt:
raise
# sys.exit raises an exception that doesn't subclass from Exception
except BaseException as e:
except Exception as err:
success = False
log.error(
"FAIL: %s %s on %s with %s (%s)",
"[%s/%s::%s=%s] %s",
channel,
subdir,
name,
version,
platform,
additional_packages,
e,
repr(err),
)
return success

Expand Down
22 changes: 22 additions & 0 deletions news/5033-update-conda-inspect-channels
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
### Enhancements

* Update `conda inspect channels` to use updated solver/transaction logic. (#5033)

### Bug fixes

* <news item>

### Deprecations

* Mark `conda inspect channels --test-installable` as pending deprecation. (#5033)
* Mark `conda_build.inspect_pkg.check_install(package)` as pending deprecation in favor of `conda_build.inspect_pkg.check_install(subdir)`. (#5033)
* Mark `conda_build.inspect_pkg.check_install(prepend)` as pending deprecation. (#5033)
* Mark `conda_build.inspect_pkg.check_install(minimal_hint)` as pending deprecation. (#5033)

### Docs

* <news item>

### Other

* <news item>

0 comments on commit 37ab8d3

Please sign in to comment.