llm-code-validator 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,66 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+
6
+ from .core import check_file
7
+ from .diagnostics import Diagnostic
8
+ from .versioning import VersionContext
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class FixResult:
13
+ path: str
14
+ changed: bool
15
+ previews: list[str]
16
+ skipped: list[str]
17
+
18
+
19
+ def _line_replacement(line: str, diagnostic: Diagnostic) -> str | None:
20
+ if diagnostic.fix.safety != "safe_fix" or not diagnostic.replacement:
21
+ return None
22
+ if line.lstrip().startswith("from ") and diagnostic.replacement.startswith("from "):
23
+ indent = line[: len(line) - len(line.lstrip())]
24
+ return indent + diagnostic.replacement
25
+ if diagnostic.symbol in line:
26
+ return line.replace(diagnostic.symbol, diagnostic.replacement, 1)
27
+ old_token = diagnostic.symbol.split(".")[-1]
28
+ if old_token not in line:
29
+ return None
30
+ return line.replace(old_token, diagnostic.replacement, 1)
31
+
32
+
33
+ def fix_file(path: str | Path, write: bool = False, version_context: VersionContext | None = None) -> FixResult:
34
+ file_path = Path(path)
35
+ source = file_path.read_text(encoding="utf-8")
36
+ keep_final_newline = source.endswith("\n")
37
+ lines = source.splitlines()
38
+ result = check_file(file_path, version_context)
39
+ previews: list[str] = []
40
+ skipped: list[str] = []
41
+ changed = False
42
+
43
+ for diagnostic in result.diagnostics:
44
+ if diagnostic.line < 1 or diagnostic.line > len(lines):
45
+ skipped.append(f"{diagnostic.path}:{diagnostic.line} {diagnostic.code} cannot locate line")
46
+ continue
47
+ old_line = lines[diagnostic.line - 1]
48
+ new_line = _line_replacement(old_line, diagnostic)
49
+ if new_line is None:
50
+ skipped.append(
51
+ f"{diagnostic.path}:{diagnostic.line} {diagnostic.code} skipped "
52
+ f"({diagnostic.fix.safety})"
53
+ )
54
+ continue
55
+ previews.append(f"{diagnostic.path}:{diagnostic.line}\n old: {old_line}\n new: {new_line}")
56
+ if write:
57
+ lines[diagnostic.line - 1] = new_line
58
+ changed = True
59
+
60
+ if write and changed:
61
+ updated = "\n".join(lines)
62
+ if keep_final_newline:
63
+ updated += "\n"
64
+ file_path.write_text(updated, encoding="utf-8")
65
+
66
+ return FixResult(str(file_path), changed, previews, skipped)
@@ -0,0 +1,43 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+
5
+ from .diagnostics import CheckResult
6
+
7
+
8
+ def format_text(result: CheckResult) -> str:
9
+ lines: list[str] = []
10
+ for diagnostic in result.diagnostics:
11
+ qualified_symbol = (
12
+ diagnostic.symbol
13
+ if diagnostic.symbol.startswith(f"{diagnostic.library}.")
14
+ else f"{diagnostic.library}.{diagnostic.symbol}"
15
+ )
16
+ lines.append(
17
+ f"{diagnostic.path}:{diagnostic.line} {diagnostic.code} "
18
+ f"{diagnostic.severity} {qualified_symbol} {diagnostic.message}"
19
+ )
20
+ if diagnostic.version_assumption:
21
+ lines.append(f" version: {diagnostic.version_assumption}")
22
+ if diagnostic.replacement:
23
+ lines.append(f" fix: {diagnostic.replacement}")
24
+ if not result.diagnostics:
25
+ lines.append(f"OK: checked {result.checked_files} file(s), no diagnostics")
26
+ for warning in result.warnings:
27
+ lines.append(f"warning: {warning}")
28
+ return "\n".join(lines)
29
+
30
+
31
+ def format_json(result: CheckResult) -> str:
32
+ return json.dumps(result.to_dict(), indent=2, sort_keys=True)
33
+
34
+
35
+ def format_github(result: CheckResult) -> str:
36
+ lines: list[str] = []
37
+ for diagnostic in result.diagnostics:
38
+ message = diagnostic.message.replace("\n", " ")
39
+ lines.append(
40
+ f"::{diagnostic.severity} file={diagnostic.path},line={diagnostic.line},"
41
+ f"col={diagnostic.column},title={diagnostic.code}::{message}"
42
+ )
43
+ return "\n".join(lines)