"""Tests for Python syntax validation in execute_code.""" import json import sys import os from pathlib import Path import pytest # Import the validation function directly sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from tools.code_execution_tool import _validate_python_syntax class TestValidatePythonSyntax: """Test _validate_python_syntax catches errors before subprocess spawn.""" def test_valid_code_returns_none(self): assert _validate_python_syntax("print('hello')") is None def test_valid_multiline_returns_none(self): code = """ import os def foo(): return 42 result = foo() """ assert _validate_python_syntax(code) is None def test_syntax_error_detected(self): result = _validate_python_syntax("def foo( ") assert result is not None data = json.loads(result) assert data["syntax_error"] is True assert "line" in data assert "message" in data def test_missing_colon(self): result = _validate_python_syntax("def foo() pass") data = json.loads(result) assert data["syntax_error"] is True assert data["line"] == 1 def test_unmatched_paren(self): result = _validate_python_syntax("print('hello'") data = json.loads(result) assert data["syntax_error"] is True def test_indentation_error(self): result = _validate_python_syntax("def foo(): pass") data = json.loads(result) assert data["syntax_error"] is True assert data["line"] == 2 def test_invalid_character(self): result = _validate_python_syntax("x = 5 √ 2") data = json.loads(result) assert data["syntax_error"] is True def test_error_format_has_required_fields(self): result = _validate_python_syntax("def( ") data = json.loads(result) assert "error" in data assert "syntax_error" in data assert "line" in data assert "offset" in data assert "message" in data def test_empty_string_returns_none(self): # Empty code is caught by the guard before validation # But if called directly, ast.parse("") is valid assert _validate_python_syntax("") is None def test_comment_only_returns_none(self): assert _validate_python_syntax("# just a comment") is None def test_complex_valid_code(self): code =