Restructure sources into app package with unified entry point and update documentation
This commit is contained in:
1 parent
540154d426
commit
f78faf8f8a
18 files changed
+167
-129
No files matched your search
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Text rendering helpers for the intrusion-detection system."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Callable, Sequence
|
||||
|
||||
#: (header, getter) pair used for CSV + console tables
|
||||
Column = tuple[str, Callable[[Any], Any]]
|
||||
|
||||
|
||||
def columns_header(columns: Sequence[Column]) -> list[str]:
|
||||
return [c[0] for c in columns]
|
||||
|
||||
|
||||
def columns_row(columns: Sequence[Column], obj: Any) -> list[Any]:
|
||||
return [fn(obj) for _, fn in columns]
|
||||
|
||||
|
||||
def render_table(headers: Sequence[str], rows: Sequence[Sequence[Any]],
|
||||
max_width: int = 48) -> str:
|
||||
"""Aligned fixed-width text table. Numeric columns right-aligned."""
|
||||
def cell(v: Any) -> str:
|
||||
s = "" if v is None else str(v)
|
||||
return s if len(s) <= max_width else s[:max_width - 1] + "~"
|
||||
|
||||
body = [[cell(v) for v in row] for row in rows]
|
||||
aligns = []
|
||||
for i in range(len(headers)):
|
||||
numeric = bool(rows) and all(
|
||||
isinstance(row[i], (int, float)) and not isinstance(row[i], bool)
|
||||
for row in rows)
|
||||
aligns.append(">" if numeric else "<")
|
||||
widths = [len(h) for h in headers]
|
||||
for row in body:
|
||||
for i, v in enumerate(row):
|
||||
widths[i] = max(widths[i], len(v))
|
||||
|
||||
def line(values: Sequence[str]) -> str:
|
||||
return " ".join(
|
||||
f"{v:{a}{w}}" for v, a, w in zip(values, aligns, widths)).rstrip()
|
||||
|
||||
out = [line(list(headers)), "-" * (sum(widths) + 2 * (len(widths) - 1))]
|
||||
out += [line(row) for row in body]
|
||||
return "\n".join(out)
|
||||
|
||||
|
||||
def render_kv(rows: Sequence[tuple[str, Any]]) -> str:
|
||||
width = max((len(k) for k, _ in rows), default=0) + 1
|
||||
return "\n".join(f"{k + ':':<{width + 1}} {v}" for k, v in rows)
|
||||
|
||||
|
||||
def timestamp_name() -> str:
|
||||
return datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
Reference in new issue
Block a user