find/list: display package counts last (#32946)

* find/list: display package counts last

We have over 6,600 packages now, and `spack list` still displays the number of packages
before it lists them all. This is useless for large sets of results (e.g., with no args)
as the number has scrolled way off the screen before you can see it. The same is true
for `spack find` with large installations.

This PR changes `spack find` and `spack list` so that they display the package count
last.

* add some quick testing

Co-authored-by: Danny McClanahan <1305167+cosmicexplorer@users.noreply.github.com>
This commit is contained in:
Todd Gamblin 2022-10-04 10:56:46 -07:00 committed by GitHub
parent 450a3074e2
commit 8c50b44bfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 53 additions and 6 deletions

View File

@ -203,7 +203,16 @@ def decorator(spec, fmt):
return decorator, added, roots, removed return decorator, added, roots, removed
def display_env(env, args, decorator): def display_env(env, args, decorator, results):
"""Display extra find output when running in an environment.
Find in an environment outputs 2 or 3 sections:
1. Root specs
2. Concretized roots (if asked for with -c)
3. Installed specs
"""
tty.msg("In environment %s" % env.name) tty.msg("In environment %s" % env.name)
if not env.user_specs: if not env.user_specs:
@ -234,6 +243,12 @@ def display_env(env, args, decorator):
cmd.display_specs(env.specs_by_hash.values(), args, decorator=decorator) cmd.display_specs(env.specs_by_hash.values(), args, decorator=decorator)
print() print()
# Display a header for the installed packages section IF there are installed
# packages. If there aren't any, we'll just end up printing "0 installed packages"
# later.
if results:
tty.msg("Installed packages")
def find(parser, args): def find(parser, args):
if args.bootstrap: if args.bootstrap:
@ -286,10 +301,11 @@ def _find(parser, args):
else: else:
if not args.format: if not args.format:
if env: if env:
display_env(env, args, decorator) display_env(env, args, decorator, results)
cmd.display_specs(results, args, decorator=decorator, all_headers=True)
# print number of installed packages last (as the list may be long)
if sys.stdout.isatty() and args.groups: if sys.stdout.isatty() and args.groups:
pkg_type = "loaded" if args.loaded else "installed" pkg_type = "loaded" if args.loaded else "installed"
spack.cmd.print_how_many_pkgs(results, pkg_type) spack.cmd.print_how_many_pkgs(results, pkg_type)
cmd.display_specs(results, args, decorator=decorator, all_headers=True)

View File

@ -122,9 +122,9 @@ def match(p, f):
@formatter @formatter
def name_only(pkgs, out): def name_only(pkgs, out):
indent = 0 indent = 0
if out.isatty():
tty.msg("%d packages." % len(pkgs))
colify(pkgs, indent=indent, output=out) colify(pkgs, indent=indent, output=out)
if out.isatty():
tty.msg("%d packages" % len(pkgs))
def github_url(pkg): def github_url(pkg):

View File

@ -7,6 +7,7 @@
import json import json
import os import os
import sys import sys
from textwrap import dedent
import pytest import pytest
@ -128,6 +129,19 @@ def test_namespaces_shown_correctly(database):
assert "builtin.mock.zmpi" in out assert "builtin.mock.zmpi" in out
@pytest.mark.db
def test_find_cli_output_format(database, mock_tty_stdout):
out = find("zmpi")
assert out.endswith(
dedent(
"""\
zmpi@1.0
==> 1 installed package
"""
)
)
def _check_json_output(spec_list): def _check_json_output(spec_list):
assert len(spec_list) == 3 assert len(spec_list) == 3
assert all(spec["name"] == "mpileaks" for spec in spec_list) assert all(spec["name"] == "mpileaks" for spec in spec_list)

View File

@ -3,6 +3,8 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
from textwrap import dedent
from spack.main import SpackCommand from spack.main import SpackCommand
list = SpackCommand("list") list = SpackCommand("list")
@ -14,6 +16,16 @@ def test_list():
assert "hdf5" in output assert "hdf5" in output
def test_list_cli_output_format(mock_tty_stdout):
out = list("mpileaks")
assert out == dedent(
"""\
mpileaks
==> 1 packages
"""
)
def test_list_filter(mock_packages): def test_list_filter(mock_packages):
output = list("py-*") output = list("py-*")
assert "py-extension1" in output assert "py-extension1" in output

View File

@ -1764,3 +1764,8 @@ def _spider(*args, **kwargs):
monkeypatch.setattr(spack.util.web, "spider", _spider) monkeypatch.setattr(spack.util.web, "spider", _spider)
yield yield
@pytest.fixture(scope="function")
def mock_tty_stdout(monkeypatch):
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)