Compare commits
1 Commits
develop
...
install-st
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6cbe4e1311 |
@ -115,7 +115,7 @@ def emulate_env_utility(cmd_name, context: Context, args):
|
|||||||
f"Not all dependencies of {spec.name} are installed. "
|
f"Not all dependencies of {spec.name} are installed. "
|
||||||
f"Cannot setup {context} environment:",
|
f"Cannot setup {context} environment:",
|
||||||
spec.tree(
|
spec.tree(
|
||||||
status_fn=spack.spec.Spec.install_status,
|
install_status=True,
|
||||||
hashlen=7,
|
hashlen=7,
|
||||||
hashes=True,
|
hashes=True,
|
||||||
# This shows more than necessary, but we cannot dynamically change deptypes
|
# This shows more than necessary, but we cannot dynamically change deptypes
|
||||||
|
@ -135,8 +135,6 @@ def _process_result(result, show, required_format, kwargs):
|
|||||||
|
|
||||||
def solve(parser, args):
|
def solve(parser, args):
|
||||||
# these are the same options as `spack spec`
|
# these are the same options as `spack spec`
|
||||||
install_status_fn = spack.spec.Spec.install_status
|
|
||||||
|
|
||||||
fmt = spack.spec.DISPLAY_FORMAT
|
fmt = spack.spec.DISPLAY_FORMAT
|
||||||
if args.namespaces:
|
if args.namespaces:
|
||||||
fmt = "{namespace}." + fmt
|
fmt = "{namespace}." + fmt
|
||||||
@ -146,7 +144,7 @@ def solve(parser, args):
|
|||||||
"format": fmt,
|
"format": fmt,
|
||||||
"hashlen": None if args.very_long else 7,
|
"hashlen": None if args.very_long else 7,
|
||||||
"show_types": args.types,
|
"show_types": args.types,
|
||||||
"status_fn": install_status_fn if args.install_status else None,
|
"install_status": args.install_status,
|
||||||
"hashes": args.long or args.very_long,
|
"hashes": args.long or args.very_long,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +75,6 @@ def setup_parser(subparser):
|
|||||||
|
|
||||||
|
|
||||||
def spec(parser, args):
|
def spec(parser, args):
|
||||||
install_status_fn = spack.spec.Spec.install_status
|
|
||||||
|
|
||||||
fmt = spack.spec.DISPLAY_FORMAT
|
fmt = spack.spec.DISPLAY_FORMAT
|
||||||
if args.namespaces:
|
if args.namespaces:
|
||||||
fmt = "{namespace}." + fmt
|
fmt = "{namespace}." + fmt
|
||||||
@ -86,7 +84,7 @@ def spec(parser, args):
|
|||||||
"format": fmt,
|
"format": fmt,
|
||||||
"hashlen": None if args.very_long else 7,
|
"hashlen": None if args.very_long else 7,
|
||||||
"show_types": args.types,
|
"show_types": args.types,
|
||||||
"status_fn": install_status_fn if args.install_status else None,
|
"install_status": args.install_status,
|
||||||
}
|
}
|
||||||
|
|
||||||
# use a read transaction if we are getting install status for every
|
# use a read transaction if we are getting install status for every
|
||||||
|
@ -2212,7 +2212,7 @@ def _tree_to_display(spec):
|
|||||||
return spec.tree(
|
return spec.tree(
|
||||||
recurse_dependencies=True,
|
recurse_dependencies=True,
|
||||||
format=spack.spec.DISPLAY_FORMAT,
|
format=spack.spec.DISPLAY_FORMAT,
|
||||||
status_fn=spack.spec.Spec.install_status,
|
install_status=True,
|
||||||
hashlen=7,
|
hashlen=7,
|
||||||
hashes=True,
|
hashes=True,
|
||||||
)
|
)
|
||||||
|
@ -186,11 +186,11 @@ class InstallStatus(enum.Enum):
|
|||||||
Options are artificially disjoint for display purposes
|
Options are artificially disjoint for display purposes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
installed = "@g{[+]} "
|
INSTALLED = "@g{[+]}"
|
||||||
upstream = "@g{[^]} "
|
UPSTREAM = "@g{[^]}"
|
||||||
external = "@g{[e]} "
|
EXTERNAL = "@g{[e]}"
|
||||||
absent = "@K{ - } "
|
ABSENT = "@K{ - }"
|
||||||
missing = "@r{[-]} "
|
MISSING = "@r{[-]}"
|
||||||
|
|
||||||
|
|
||||||
def colorize_spec(spec):
|
def colorize_spec(spec):
|
||||||
@ -4319,8 +4319,7 @@ def colorized(self):
|
|||||||
return colorize_spec(self)
|
return colorize_spec(self)
|
||||||
|
|
||||||
def format(self, format_string=DEFAULT_FORMAT, **kwargs):
|
def format(self, format_string=DEFAULT_FORMAT, **kwargs):
|
||||||
r"""Prints out particular pieces of a spec, depending on what is
|
r"""Prints out particular pieces of a spec, depending on what is in the format string.
|
||||||
in the format string.
|
|
||||||
|
|
||||||
Using the ``{attribute}`` syntax, any field of the spec can be
|
Using the ``{attribute}`` syntax, any field of the spec can be
|
||||||
selected. Those attributes can be recursive. For example,
|
selected. Those attributes can be recursive. For example,
|
||||||
@ -4446,6 +4445,9 @@ def write_attribute(spec, attribute, color):
|
|||||||
elif attribute == "spack_install":
|
elif attribute == "spack_install":
|
||||||
write(morph(spec, spack.store.STORE.layout.root))
|
write(morph(spec, spack.store.STORE.layout.root))
|
||||||
return
|
return
|
||||||
|
elif re.match(r"install_status", attribute):
|
||||||
|
write(self.install_status_symbol())
|
||||||
|
return
|
||||||
elif re.match(r"hash(:\d)?", attribute):
|
elif re.match(r"hash(:\d)?", attribute):
|
||||||
col = "#"
|
col = "#"
|
||||||
if ":" in attribute:
|
if ":" in attribute:
|
||||||
@ -4540,8 +4542,18 @@ def write_attribute(spec, attribute, color):
|
|||||||
"Format string terminated while reading attribute." "Missing terminating }."
|
"Format string terminated while reading attribute." "Missing terminating }."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# remove leading whitespace from directives that add it for internal formatting.
|
||||||
|
# Arch, compiler flags, and variants add spaces for spec format correctness, but
|
||||||
|
# we don't really want them in formatted string output. We do want to preserve
|
||||||
|
# whitespace from the format string.
|
||||||
formatted_spec = out.getvalue()
|
formatted_spec = out.getvalue()
|
||||||
return formatted_spec.strip()
|
whitespace_attrs = [r"{arch=[^}]*}", r"{architecture}", r"{compiler_flags}", r"{variants}"]
|
||||||
|
if any(re.match(rx, format_string) for rx in whitespace_attrs):
|
||||||
|
formatted_spec = formatted_spec.lstrip()
|
||||||
|
if any(re.search(f"{rx}$", format_string) for rx in whitespace_attrs):
|
||||||
|
formatted_spec = formatted_spec.rstrip()
|
||||||
|
|
||||||
|
return formatted_spec
|
||||||
|
|
||||||
def cformat(self, *args, **kwargs):
|
def cformat(self, *args, **kwargs):
|
||||||
"""Same as format, but color defaults to auto instead of False."""
|
"""Same as format, but color defaults to auto instead of False."""
|
||||||
@ -4611,20 +4623,25 @@ def colored_str(self):
|
|||||||
def install_status(self):
|
def install_status(self):
|
||||||
"""Helper for tree to print DB install status."""
|
"""Helper for tree to print DB install status."""
|
||||||
if not self.concrete:
|
if not self.concrete:
|
||||||
return InstallStatus.absent
|
return InstallStatus.ABSENT
|
||||||
|
|
||||||
if self.external:
|
if self.external:
|
||||||
return InstallStatus.external
|
return InstallStatus.EXTERNAL
|
||||||
|
|
||||||
upstream, record = spack.store.STORE.db.query_by_spec_hash(self.dag_hash())
|
upstream, record = spack.store.STORE.db.query_by_spec_hash(self.dag_hash())
|
||||||
if not record:
|
if not record:
|
||||||
return InstallStatus.absent
|
return InstallStatus.ABSENT
|
||||||
elif upstream and record.installed:
|
elif upstream and record.installed:
|
||||||
return InstallStatus.upstream
|
return InstallStatus.UPSTREAM
|
||||||
elif record.installed:
|
elif record.installed:
|
||||||
return InstallStatus.installed
|
return InstallStatus.INSTALLED
|
||||||
else:
|
else:
|
||||||
return InstallStatus.missing
|
return InstallStatus.MISSING
|
||||||
|
|
||||||
|
def install_status_symbol(self):
|
||||||
|
"""Get an install status symbol."""
|
||||||
|
status = self.install_status()
|
||||||
|
return clr.colorize(status.value)
|
||||||
|
|
||||||
def _installed_explicitly(self):
|
def _installed_explicitly(self):
|
||||||
"""Helper for tree to print DB install status."""
|
"""Helper for tree to print DB install status."""
|
||||||
@ -4650,7 +4667,7 @@ def tree(
|
|||||||
show_types: bool = False,
|
show_types: bool = False,
|
||||||
depth_first: bool = False,
|
depth_first: bool = False,
|
||||||
recurse_dependencies: bool = True,
|
recurse_dependencies: bool = True,
|
||||||
status_fn: Optional[Callable[["Spec"], InstallStatus]] = None,
|
install_status: bool = False,
|
||||||
prefix: Optional[Callable[["Spec"], str]] = None,
|
prefix: Optional[Callable[["Spec"], str]] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Prints out this spec and its dependencies, tree-formatted
|
"""Prints out this spec and its dependencies, tree-formatted
|
||||||
@ -4671,8 +4688,7 @@ def tree(
|
|||||||
show_types: if True, show the (merged) dependency type of a node
|
show_types: if True, show the (merged) dependency type of a node
|
||||||
depth_first: if True, traverse the DAG depth first when representing it as a tree
|
depth_first: if True, traverse the DAG depth first when representing it as a tree
|
||||||
recurse_dependencies: if True, recurse on dependencies
|
recurse_dependencies: if True, recurse on dependencies
|
||||||
status_fn: optional callable that takes a node as an argument and return its
|
install_status: if True, show installation status next to each spec
|
||||||
installation status
|
|
||||||
prefix: optional callable that takes a node as an argument and return its
|
prefix: optional callable that takes a node as an argument and return its
|
||||||
installation prefix
|
installation prefix
|
||||||
"""
|
"""
|
||||||
@ -4686,6 +4702,9 @@ def tree(
|
|||||||
):
|
):
|
||||||
node = dep_spec.spec
|
node = dep_spec.spec
|
||||||
|
|
||||||
|
if install_status:
|
||||||
|
out += node.format("{install_status} ")
|
||||||
|
|
||||||
if prefix is not None:
|
if prefix is not None:
|
||||||
out += prefix(node)
|
out += prefix(node)
|
||||||
out += " " * indent
|
out += " " * indent
|
||||||
@ -4693,15 +4712,6 @@ def tree(
|
|||||||
if depth:
|
if depth:
|
||||||
out += "%-4d" % d
|
out += "%-4d" % d
|
||||||
|
|
||||||
if status_fn:
|
|
||||||
status = status_fn(node)
|
|
||||||
if status in list(InstallStatus):
|
|
||||||
out += clr.colorize(status.value, color=color)
|
|
||||||
elif status:
|
|
||||||
out += clr.colorize("@g{[+]} ", color=color)
|
|
||||||
else:
|
|
||||||
out += clr.colorize("@r{[-]} ", color=color)
|
|
||||||
|
|
||||||
if hashes:
|
if hashes:
|
||||||
out += clr.colorize("@K{%s} ", color=color) % node.dag_hash(hashlen)
|
out += clr.colorize("@K{%s} ", color=color) % node.dag_hash(hashlen)
|
||||||
|
|
||||||
|
@ -703,6 +703,13 @@ def check_prop(check_spec, fmt_str, prop, getter):
|
|||||||
actual = spec.format(named_str)
|
actual = spec.format(named_str)
|
||||||
assert expected == actual
|
assert expected == actual
|
||||||
|
|
||||||
|
def test_spec_format_instalL_status(self, database):
|
||||||
|
installed = database.query_one("mpileaks^zmpi")
|
||||||
|
assert installed.format("{install_status}") == "[+]"
|
||||||
|
|
||||||
|
not_installed = Spec("foo")
|
||||||
|
assert not_installed.format("{install_status}") == " - "
|
||||||
|
|
||||||
def test_spec_formatting_escapes(self, default_mock_concretization):
|
def test_spec_formatting_escapes(self, default_mock_concretization):
|
||||||
spec = default_mock_concretization("multivalue-variant cflags=-O2")
|
spec = default_mock_concretization("multivalue-variant cflags=-O2")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user