# Copyright (C) 2012 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause
from collections import defaultdict
from datetime import datetime, timezone
from ..base.context import context
from ..cli.common import stdout_json
from ..common.io import Spinner, dashlist
from ..core.envs_manager import query_all_prefixes
from ..core.index import calculate_channel_urls
from ..core.subdir_data import SubdirData
from ..models.match_spec import MatchSpec
from ..models.records import PackageRecord
from ..models.version import VersionOrder
from ..utils import human_bytes
def execute(args, parser):
spec = MatchSpec(args.match_spec)
if spec.get_exact_value("subdir"):
subdirs = (spec.get_exact_value("subdir"),)
else:
subdirs = context.subdirs
if args.envs:
with Spinner(
"Searching environments for %s" % spec,
not context.verbosity and not context.quiet,
context.json,
):
prefix_matches = query_all_prefixes(spec)
ordered_result = tuple(
{
"location": prefix,
"package_records": tuple(
sorted(
(
PackageRecord.from_objects(prefix_rec)
for prefix_rec in prefix_recs
),
key=lambda prec: prec._pkey,
)
),
}
for prefix, prefix_recs in prefix_matches
)
if context.json:
stdout_json(ordered_result)
elif args.info:
for pkg_group in ordered_result:
for prec in pkg_group["package_records"]:
pretty_record(prec)
else:
builder = [
"# %-13s %15s %15s %-20s %-20s"
% (
"Name",
"Version",
"Build",
"Channel",
"Location",
)
]
for pkg_group in ordered_result:
for prec in pkg_group["package_records"]:
builder.append(
"%-15s %15s %15s %-20s %-20s"
% (
prec.name,
prec.version,
prec.build,
prec.channel.name,
pkg_group["location"],
)
)
print("\n".join(builder))
return 0
with Spinner(
"Loading channels", not context.verbosity and not context.quiet, context.json
):
spec_channel = spec.get_exact_value("channel")
channel_urls = (spec_channel,) if spec_channel else context.channels
matches = sorted(
SubdirData.query_all(spec, channel_urls, subdirs),
key=lambda rec: (rec.name, VersionOrder(rec.version), rec.build),
)
if not matches and spec.get_exact_value("name"):
flex_spec = MatchSpec(spec, name="*%s*" % spec.name)
if not context.json:
print(f"No match found for: {spec}. Search: {flex_spec}")
matches = sorted(
SubdirData.query_all(flex_spec, channel_urls, subdirs),
key=lambda rec: (rec.name, VersionOrder(rec.version), rec.build),
)
if not matches:
channels_urls = tuple(
calculate_channel_urls(
channel_urls=context.channels,
prepend=not args.override_channels,
platform=subdirs[0],
use_local=args.use_local,
)
)
from ..exceptions import PackagesNotFoundError
raise PackagesNotFoundError((str(spec),), channels_urls)
if context.json:
json_obj = defaultdict(list)
for match in matches:
json_obj[match.name].append(match)
stdout_json(json_obj)
elif args.info:
for record in matches:
pretty_record(record)
else:
builder = [
"# %-18s %15s %15s %-20s"
% (
"Name",
"Version",
"Build",
"Channel",
)
]
for record in matches:
builder.append(
"%-20s %15s %15s %-20s"
% (
record.name,
record.version,
record.build,
record.channel.name,
)
)
print("\n".join(builder))
def pretty_record(record):
def push_line(display_name, attr_name):
value = getattr(record, attr_name, None)
if value is not None:
builder.append("%-12s: %s" % (display_name, value))
builder = []
builder.append(record.name + " " + record.version + " " + record.build)
builder.append("-" * len(builder[0]))
push_line("file name", "fn")
push_line("name", "name")
push_line("version", "version")
push_line("build", "build")
push_line("build number", "build_number")
builder.append("%-12s: %s" % ("size", human_bytes(record.size)))
push_line("license", "license")
push_line("subdir", "subdir")
push_line("url", "url")
push_line("md5", "md5")
if record.timestamp:
date_str = datetime.fromtimestamp(record.timestamp, timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S %Z"
)
builder.append("%-12s: %s" % ("timestamp", date_str))
if record.track_features:
builder.append(
"%-12s: %s" % ("track_features", dashlist(record.track_features))
)
if record.constrains:
builder.append("%-12s: %s" % ("constraints", dashlist(record.constrains)))
builder.append(
"%-12s: %s"
% ("dependencies", dashlist(record.depends) if record.depends else "[]")
)
builder.append("\n")
print("\n".join(builder))