Source code for spack.util.log_parse
# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from typing import Container, Iterator, List, Optional, TextIO, Union
from spack.util.ctest_log_parser import ALL_SEVERITIES, Block, CTestLogParser, Severity
from spack.util.tty.color import cescape, colorize
__all__ = ["scan_log", "write_block", "write_log_context"]
_PARSER: Optional[CTestLogParser] = None
[docs]
def scan_log(
stream: Union[str, TextIO, List[str]],
context: int = 6,
tail: Optional[int] = 0,
severities: Container[Severity] = ALL_SEVERITIES,
profile: bool = False,
) -> Iterator[Block]:
"""Scan a build log for errors and warnings and yield the blocks worth showing.
Args:
stream: build log name or file object
context: lines of context to show around each matched line
tail: also show the last this many lines, whether or not anything matched; None shows
the whole log
severities: only match lines of these severities
profile: print out profile information for parsing
Yields:
:class:`~spack.util.ctest_log_parser.Block` objects in increasing line order.
"""
global _PARSER
if profile:
parser = CTestLogParser(profile=True)
elif _PARSER is None:
_PARSER = parser = CTestLogParser()
else:
parser = _PARSER
yield from parser.scan(stream, context, tail, severities)
if profile:
parser.print_timings()
[docs]
def write_block(out: TextIO, block: Block) -> None:
"""Write a block of log lines to a stream, under a header giving its line range.
Matched lines are prefixed with a ``>``, red for errors and yellow for warnings; the lines of
context around them are indented instead.
"""
out.write(colorize("@c{-- lines %d to %d --}\n" % (block.start, block.end)))
for line_no, text in enumerate(block.lines, block.start):
match = block.matches.get(line_no)
if match is None:
out.write(" %s\n" % text)
else:
out.write(colorize("@%s{> %s}\n" % (match.severity.value, cescape(text))))
[docs]
def write_log_context(
out: TextIO, stream: Union[str, TextIO, List[str]], context: int = 6, tail: Optional[int] = 0
) -> None:
"""Write the interesting parts of a build log to a stream."""
for block in scan_log(stream, context, tail):
write_block(out, block)