diff --git a/conda_build/cli/main_inspect.py b/conda_build/cli/main_inspect.py index 79e0594a4f..05f76c0fbc 100644 --- a/conda_build/cli/main_inspect.py +++ b/conda_build/cli/main_inspect.py @@ -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", @@ -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( @@ -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", "4.0.0", addendum="Use `conda inspect` instead.") diff --git a/conda_build/inspect_pkg.py b/conda_build/inspect_pkg.py index e8b94978c1..d749421287 100644 --- a/conda_build/inspect_pkg.py +++ b/conda_build/inspect_pkg.py @@ -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, ) @@ -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 +log = get_logger(__name__) + @deprecated("3.28.0", "4.0.0") @lru_cache(maxsize=None) @@ -110,23 +110,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( @@ -190,61 +188,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 diff --git a/news/5033-update-conda-inspect-channels b/news/5033-update-conda-inspect-channels new file mode 100644 index 0000000000..13fba0b6b4 --- /dev/null +++ b/news/5033-update-conda-inspect-channels @@ -0,0 +1,22 @@ +### Enhancements + +* Update `conda inspect channels` to use updated solver/transaction logic. (#5033) + +### Bug fixes + +* + +### 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 + +* + +### Other + +*