Files
openvino/docs/scripts/tests/utils/log.py
T
Ilya Churaev 0c9abf43a9 Updated copyright headers (#15124)
* Updated copyright headers

* Revert "Fixed linker warnings in docs snippets on Windows (#15119)"

This reverts commit 372699ec49.
2023-01-16 11:02:17 +04:00

121 lines
4.3 KiB
Python

# Copyright (C) 2018-2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
"""
Doxygen and Sphinx logs parsing routines
"""
import re
from pathlib import Path
class LogParser:
"""
This class reads a log file and converts it to a structured format represented as a python `dict`
"""
exclude_symbols = (
'\x1b[91m',
''
)
# a regex that is used to match log lines containing a filepath,
# a line number, and an error,warning or critical
regex = r'^(?!\*)(.*?):?([0-9]*):? ?(warning|error|critical): (.+)'
def __init__(self, log: Path, strip: str, xfail_list: list, suppress_warnings: list):
"""
Initialize a LogParser object for parsing doxygen and sphinx logs
:param log: Path to a log file represented as a `pathlib.Path` object
:param strip: A part of the filepath that should be removed
:param suppress_warnings: A list of warnings that should be ignored
:param xfail_list: A list of filepaths that should be ignored
"""
self.log = log
if not strip.endswith('/'):
strip = strip + '/'
self.strip = strip.replace('\\', '/').lower()
self.xfail_list = xfail_list
self.suppress_warnings = suppress_warnings
self.out = dict()
def get_match(self, line: str):
"""
Match a log line against the regex defined by this class
"""
return re.match(self.regex, line)
def preprocess_line(self, line):
"""
Clear log line from unwanted symbols
"""
for sym in self.exclude_symbols:
line = line.replace(sym, '')
return line.strip().lower()
def strip_path(self, path):
"""
Strip `path` components ends on `strip`
"""
path = path.replace('\\', '/').lower()
new_path = path.split(self.strip)[-1]
if new_path.startswith('build/docs/'):
new_path = new_path.split('build/docs/')[-1]
return new_path
def filter(self):
"""
Filter out a log file to remove files or warning based on the values provided in `strip`,
`suppress_warnings`, and 'xfail_list`
"""
filtered_out = dict()
for filepath, warnings in self.out.items():
filepath = self.strip_path(filepath)
if filepath in self.xfail_list:
continue
warnings = list(filter(lambda item: not self.is_suppressed(item), warnings))
if warnings:
filtered_out[filepath] = warnings
return filtered_out
def is_suppressed(self, line):
return any([re.search(re.compile(warning, re.IGNORECASE), line) for warning in self.suppress_warnings])
def parse(self):
"""
Parse a log file to convert it to a structured format
"""
with open(self.log, 'r', errors='ignore') as f:
log_lines = f.readlines()
# iterate each line in the log file
i = 0
while i < len(log_lines):
j = i + 1
line = self.preprocess_line(log_lines[i])
match = self.get_match(line)
# if match is true then we found a line containing a filepath,
# a line number, and a warning/error
if match and not self.is_suppressed(line):
filepath = match.group(1) or 'warning'
linenum = match.group(2)
warning = match.group(4)
if not filepath in self.out:
self.out[filepath] = set()
if linenum:
warning = f'{warning} line ({linenum})'
self.out[filepath].add(warning)
# in this case, the filepath might contain several errors on separate lines,
# so we need to iterate next lines until we find a line
# that matches the regex defined in this class
while j < len(log_lines):
next_line = self.preprocess_line(log_lines[j])
match = self.get_match(next_line)
if match:
break
if next_line:
self.out[filepath].add(self.preprocess_line(next_line))
j += 1
i = j
return self.out