Skip to content

Commit 497df5c

Browse files
committed
Fix agent JSON severity filtering and console output
1 parent ac01cc0 commit 497df5c

3 files changed

Lines changed: 49 additions & 8 deletions

File tree

src/pinescript_validator/agent_report.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,13 @@ def build_agent_report(
121121
"diagnostics": items,
122122
"next_steps": next_steps,
123123
}
124+
125+
126+
def clone_agent_report_with_diagnostics(
127+
report: dict[str, object],
128+
diagnostics: list[Diagnostic],
129+
text: str,
130+
*,
131+
file_path: str | Path | None = None,
132+
) -> dict[str, object]:
133+
return build_agent_report(diagnostics, text, file_path=file_path)

src/pinescript_validator/cli.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from pathlib import Path
88

99
from .diagnostics import Diagnostic, Severity
10+
from .agent_report import build_agent_report
1011
from .sarif import build_sarif_run
1112
from .validator import PineScriptValidator
1213

@@ -127,6 +128,26 @@ def _summary(results: list[dict[str, object]]) -> dict[str, int]:
127128
}
128129

129130

131+
def _write_output(value: str) -> None:
132+
if hasattr(sys.stdout, "reconfigure"):
133+
try:
134+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
135+
except (ValueError, OSError):
136+
pass
137+
try:
138+
sys.stdout.write(value)
139+
if not value.endswith("\n"):
140+
sys.stdout.write("\n")
141+
except UnicodeEncodeError:
142+
safe_value = value.encode(sys.stdout.encoding or "utf-8", errors="replace").decode(
143+
sys.stdout.encoding or "utf-8",
144+
errors="replace",
145+
)
146+
sys.stdout.write(safe_value)
147+
if not safe_value.endswith("\n"):
148+
sys.stdout.write("\n")
149+
150+
130151
def main(argv: list[str] | None = None) -> int:
131152
args = build_parser().parse_args(argv)
132153
validator = PineScriptValidator()
@@ -154,13 +175,13 @@ def main(argv: list[str] | None = None) -> int:
154175
diagnostics = results[0]["diagnostics"] if len(results) == 1 else []
155176

156177
if args.sarif:
157-
print(json.dumps(build_sarif_run(results), ensure_ascii=False, indent=2))
178+
_write_output(json.dumps(build_sarif_run(results), ensure_ascii=False, indent=2))
158179
elif args.agent_json and len(results) > 1:
159180
file_reports = [
160-
validator.build_agent_report_for_text(item["text"], file_path=item["path"])
181+
build_agent_report(item["diagnostics"], item["text"], file_path=item["path"])
161182
for item in results
162183
]
163-
print(
184+
_write_output(
164185
json.dumps(
165186
{
166187
"tool": "pine-script-validator",
@@ -174,9 +195,9 @@ def main(argv: list[str] | None = None) -> int:
174195
)
175196
)
176197
elif args.agent_json:
177-
print(json.dumps(validator.build_agent_report_for_text(text, file_path=file_path), ensure_ascii=False, indent=2))
198+
_write_output(json.dumps(build_agent_report(diagnostics, text, file_path=file_path), ensure_ascii=False, indent=2))
178199
elif args.json and len(results) > 1:
179-
print(
200+
_write_output(
180201
json.dumps(
181202
{
182203
"tool": "pine-script-validator",
@@ -195,7 +216,7 @@ def main(argv: list[str] | None = None) -> int:
195216
)
196217
)
197218
elif args.json:
198-
print(json.dumps([diagnostic.to_dict() for diagnostic in diagnostics], ensure_ascii=False, indent=2))
219+
_write_output(json.dumps([diagnostic.to_dict() for diagnostic in diagnostics], ensure_ascii=False, indent=2))
199220
else:
200221
any_output = False
201222
for item in results:
@@ -204,9 +225,9 @@ def main(argv: list[str] | None = None) -> int:
204225
if file_diagnostics:
205226
any_output = True
206227
for diagnostic in file_diagnostics:
207-
print(diagnostic.format(path))
228+
_write_output(diagnostic.format(path))
208229
if not any_output:
209-
print("No diagnostics.")
230+
_write_output("No diagnostics.")
210231

211232
return 1 if any(diagnostic.severity == Severity.ERROR for item in results for diagnostic in item["diagnostics"]) else 0
212233

tests/test_validator.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pathlib import Path
66
from tempfile import TemporaryDirectory
77

8+
from pinescript_validator.agent_report import build_agent_report
89
from pinescript_validator.cli import _expand_paths, _filter_results, _selected_severities
910
from pinescript_validator.diagnostics import Severity
1011
from pinescript_validator.sarif import build_sarif_run
@@ -503,6 +504,15 @@ def test_filter_results_removes_disabled_severities(self) -> None:
503504
self.assertTrue(filtered[0]["diagnostics"])
504505
self.assertTrue(all(item.severity == Severity.ERROR for item in filtered[0]["diagnostics"]))
505506

507+
def test_agent_report_can_be_built_from_filtered_diagnostics(self) -> None:
508+
diagnostics = self.validator.validate_text('indicator("X")\nvalue = close\nplot(close, invalid_param=true)')
509+
filtered = [item for item in diagnostics if item.severity == Severity.ERROR]
510+
report = build_agent_report(filtered, 'indicator("X")\nvalue = close\nplot(close, invalid_param=true)')
511+
512+
self.assertEqual(report["summary"]["error"], 1)
513+
self.assertEqual(report["summary"]["hint"], 0)
514+
self.assertEqual(len(report["diagnostics"]), 1)
515+
506516

507517
if __name__ == "__main__":
508518
unittest.main()

0 commit comments

Comments
 (0)