File indexing completed on 2025-01-30 09:13:26
0001
0002 import argparse
0003 import sys
0004 from pathlib import Path
0005 import json
0006 import itertools
0007 import fnmatch
0008 import re
0009
0010 import yaml
0011 from rich.console import Console, Group
0012 from rich.text import Text
0013 from rich.panel import Panel
0014 from rich.rule import Rule
0015 from rich.emoji import Emoji
0016 from rich.table import Table
0017
0018
0019 from item import ItemCollection
0020
0021
0022 def main():
0023 p = argparse.ArgumentParser()
0024 p.add_argument("--report", type=Path, required=True)
0025 p.add_argument("--config", type=Path, required=True)
0026 p.add_argument("--strip-prefix-path", type=Path)
0027
0028 args = p.parse_args()
0029
0030 console = Console()
0031
0032 with args.config.open() as fh:
0033 config = yaml.safe_load(fh)
0034
0035 data = []
0036 with args.report.open() as fh:
0037 data = ItemCollection(root=json.load(fh)).root
0038 for item in data:
0039 if args.strip_prefix_path and not item.path.is_absolute:
0040 item.path = item.path.relative_to(args.strip_prefix_path)
0041
0042 counts = config["limits"].copy()
0043
0044 kf = lambda i: i.path
0045 for file, items in itertools.groupby(sorted(data, key=kf), key=kf):
0046 output = []
0047 for item in items:
0048 emoji = Emoji(
0049 {"warning": "yellow_circle", "error": "red_circle"}[item.severity]
0050 )
0051
0052 style = "bold "
0053 if item.severity == "warning":
0054 style += "yellow"
0055 elif item.severity == "error":
0056 style += "red"
0057
0058 s = Text()
0059 s.append(f"{emoji}")
0060 s.append(f" {item.path}:{item.line}:{item.col}", style="bold")
0061 s.append(f" {item.severity.upper()} ", style=style)
0062 s.append("[")
0063 s.append(item.code, style="bold")
0064 s.append(f"]")
0065
0066 def subpath(m):
0067 return f"[bold]{m.group(1)}[/bold]:"
0068
0069 message = re.sub(r"([\w/.\-+]+:\d+:\d+):", subpath, item.message)
0070
0071 accounted_for = False
0072 for pattern in config["limits"].keys():
0073 if not fnmatch.fnmatch(item.code, pattern):
0074 continue
0075 counts[pattern] += 1
0076 accounted_for = True
0077
0078 if accounted_for:
0079 output.append(s)
0080 output.append(Panel(message))
0081 output.append(Rule())
0082 pass
0083 else:
0084 counts.setdefault(item.code, 0)
0085 counts[item.code] += 1
0086
0087
0088 if len(output) > 0:
0089 console.print(Panel(Group(*output), title=str(file)))
0090
0091 table = Table()
0092 table.add_column("", width=2)
0093 table.add_column("code / pattern")
0094 table.add_column("count", justify="right")
0095 table.add_column("limit", justify="right")
0096 exit = 0
0097 for pattern, count in counts.items():
0098 limit = config["limits"].get(pattern, float("inf"))
0099 emoji = Emoji("green_circle")
0100 style = "green"
0101 if limit == float("inf"):
0102 emoji = Emoji("white_circle")
0103 style = "white"
0104 elif count > limit:
0105 exit = 1
0106 emoji = Emoji("red_circle")
0107 style = "red bold"
0108 table.add_row(emoji, pattern, str(count), str(limit), style=style)
0109
0110 console.rule()
0111 console.print(Panel.fit(table, title="Results"), justify="center")
0112
0113 if exit != 0:
0114 console.print(
0115 Panel(
0116 Text(f"{Emoji('red_circle')} FAILURE", justify="center"),
0117 style="red bold",
0118 )
0119 )
0120 else:
0121 console.print(
0122 Panel(
0123 Text(f"{Emoji('green_circle')} SUCCESS", justify="center"),
0124 style="green bold",
0125 )
0126 )
0127
0128 sys.exit(exit)
0129
0130
0131 if "__main__" == __name__:
0132 main()