mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2026-10-22 17:22:09 +03:00
[#1438] Document Existing Traces
This commit is contained in:
2 files changed
+269
No files matched your search
@@ -0,0 +1,142 @@
|
||||
r"""
|
||||
Search paths for trace_if calls, validate TRACEDOC comments, and optionally generate /docs/Available-Traces.md.
|
||||
|
||||
Example usage: python .\scripts\find_trace_strings.py --directory . --ignore dist.win32 --ignore tests
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import ast
|
||||
import datetime
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def get_func_name(thing: ast.AST) -> str:
|
||||
"""Get the name of a function from a Call node."""
|
||||
if isinstance(thing, ast.Name):
|
||||
return thing.id
|
||||
if isinstance(thing, ast.Attribute):
|
||||
return thing.attr
|
||||
return ""
|
||||
|
||||
|
||||
def find_trace_calls(statement: ast.AST) -> list[ast.Call]:
|
||||
"""Recursively find 'trace_if' ast.Calls."""
|
||||
out = []
|
||||
for n in ast.iter_child_nodes(statement):
|
||||
out.extend(find_trace_calls(n))
|
||||
|
||||
if isinstance(statement, ast.Call) and get_func_name(statement.func) == "trace_if":
|
||||
out.append(statement)
|
||||
return out
|
||||
|
||||
|
||||
COMMENT_SAME_LINE_RE = re.compile(r"^.*(#.*)$")
|
||||
COMMENT_OWN_LINE_RE = re.compile(r"^\s*?(#.*)$")
|
||||
|
||||
|
||||
def _has_tracedoc(line: str, pattern: re.Pattern) -> bool:
|
||||
match = pattern.match(line)
|
||||
if match:
|
||||
return match.group(1).strip().startswith("# TRACEDOC:")
|
||||
return False
|
||||
|
||||
|
||||
def generate_markdown(all_found_data: list[dict], project_root: pathlib.Path):
|
||||
"""Generate the Available-Traces.md file with fixed-width column formatting."""
|
||||
docs_dir = project_root / "docs"
|
||||
docs_dir.mkdir(exist_ok=True)
|
||||
|
||||
sorted_data = sorted(all_found_data, key=lambda x: x["key"])
|
||||
|
||||
h_key, h_msg, h_loc = "Trace Key", "Enables Log Message", "Source Location"
|
||||
|
||||
# Pre-format content to calculate widths correctly including backticks
|
||||
formatted_rows = []
|
||||
for entry in sorted_data:
|
||||
formatted_rows.append(
|
||||
{
|
||||
"key": f"`{entry['key']}`",
|
||||
"msg": f"`{entry['message'].replace('|', '\\|')}`",
|
||||
"loc": f"{entry['file']}:{entry['line']}",
|
||||
}
|
||||
)
|
||||
|
||||
# Calculate widths based on headers and formatted content
|
||||
w_key = max(len(h_key), max((len(r["key"]) for r in formatted_rows), default=0))
|
||||
w_msg = max(len(h_msg), max((len(r["msg"]) for r in formatted_rows), default=0))
|
||||
w_loc = max(len(h_loc), max((len(r["loc"]) for r in formatted_rows), default=0))
|
||||
|
||||
lines = [
|
||||
"# Available Traces",
|
||||
f"This file was last updated on {datetime.date.today()}."
|
||||
"",
|
||||
"This document lists all of the available `--trace-on` options to enable additional debug logging.",
|
||||
"",
|
||||
f"| {h_key:<{w_key}} | {h_msg:<{w_msg}} | {h_loc:<{w_loc}} |",
|
||||
f"|{'-' * w_key}--|{'-' * w_msg}--|{'-' * w_loc}--|",
|
||||
]
|
||||
|
||||
for r in formatted_rows:
|
||||
lines.append(
|
||||
f"| {r['key']:<{w_key}} | {r['msg']:<{w_msg}} | {r['loc']:<{w_loc}} |"
|
||||
)
|
||||
|
||||
output_path = docs_dir / "Available-Traces.md"
|
||||
output_path.write_text("\n".join(lines), encoding="utf-8")
|
||||
print(f"\nDocumentation updated: {output_path}")
|
||||
|
||||
|
||||
def main(): # noqa: CCR001
|
||||
"""Run the Traceon Doc Checker and update the docs."""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--directory", default=".", help="Project root directory")
|
||||
parser.add_argument(
|
||||
"--ignore", action="append", default=["venv", ".venv", ".git", "docs"]
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
root = pathlib.Path(args.directory).resolve()
|
||||
all_traces_for_md = []
|
||||
global_success = True
|
||||
|
||||
for path in root.rglob("*.py"):
|
||||
if any(ignored in path.parts for ignored in args.ignore):
|
||||
continue
|
||||
|
||||
try:
|
||||
data = path.read_text(encoding="utf-8")
|
||||
parsed = ast.parse(data)
|
||||
except (SyntaxError, UnicodeDecodeError):
|
||||
continue
|
||||
|
||||
calls = []
|
||||
for statement in parsed.body:
|
||||
calls.extend(find_trace_calls(statement))
|
||||
|
||||
for call in calls:
|
||||
# Store data in case we need to update docs
|
||||
trace_key = ast.unparse(call.args[0]).strip("'\"") if call.args else "N/A"
|
||||
log_msg = ast.unparse(call.args[1]) if len(call.args) > 1 else "N/A"
|
||||
|
||||
all_traces_for_md.append(
|
||||
{
|
||||
"key": trace_key,
|
||||
"message": log_msg,
|
||||
"file": path.relative_to(root),
|
||||
"line": call.lineno,
|
||||
}
|
||||
)
|
||||
|
||||
if all_traces_for_md:
|
||||
generate_markdown(all_traces_for_md, root)
|
||||
|
||||
if not global_success:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user