Source Code:
src/gaia/agents/code/tools/code_formatting.pyComponent: CodeFormattingMixin
Module:
gaia.agents.code.tools.code_formatting
Import: from gaia.agents.code.tools.code_formatting import CodeFormattingMixinOverview
CodeFormattingMixin provides Python code formatting and combined linting tools for the Code Agent, integrating Black formatter with pylint analysis for comprehensive code quality checks. Key Features:- Black formatting with configurable line length
- Check-only mode for validation without modification
- Combined lint + format analysis
- Auto-fix capability with re-validation
- Unified diff generation for changes
API Specification
Copy
class CodeFormattingMixin:
"""
Mixin providing code formatting and linting tools.
Tools provided:
- format_with_black: Format code using Black
- lint_and_format: Combined pylint + Black analysis
"""
@tool
def format_with_black(
file_path: str = None,
code: str = None,
line_length: int = 88,
check_only: bool = False
) -> Dict[str, Any]:
"""
Format Python code with Black.
Args:
file_path: Path to Python file (optional)
code: Python code string (optional)
line_length: Max line length (default: 88)
check_only: Only check, don't modify (default: False)
Returns:
{
"status": "success" | "error",
"formatted": bool, # Whether formatting was applied
"needs_formatting": bool,
"formatted_code": str | None, # If formatted
"diff": str | None, # Unified diff
"command": str,
"stdout": str,
"stderr": str,
"return_code": int,
"message": str
}
"""
pass
@tool
def lint_and_format(
file_path: str = None,
code: str = None,
fix: bool = False,
line_length: int = 88
) -> Dict[str, Any]:
"""
Combined linting and formatting analysis.
Workflow:
1. Validate syntax
2. Run pylint analysis
3. Check/apply Black formatting
4. If fix=True, apply lint fixes and re-validate
Args:
file_path: Path to Python file (optional)
code: Python code string (optional)
fix: Apply fixes (default: False)
line_length: Max line length (default: 88)
Returns:
{
"status": "success" | "error",
"file_path": str,
"syntax_valid": bool,
"syntax_errors": List[str],
"pylint": {
"total_issues": int,
"errors": int,
"warnings": int,
"conventions": int,
"issues": List[dict] # First 10
},
"formatting": {
"needs_formatting": bool,
"formatted": bool
},
"formatted_code": str, # If fix=True
"file_updated": bool,
"lint_fixes_applied": List[str],
"pylint_after_fixes": {...}, # If fix=True
"formatting_diff": str,
"clean": bool,
"message": str
}
"""
pass
def _generate_unified_diff(
self,
original: str,
modified: str,
original_name: str = "original",
modified_name: str = "modified",
context_lines: int = 3
) -> str:
"""Generate unified diff between two strings."""
pass
Implementation Details
Black Integration
Copy
def format_with_black(file_path=None, code=None, line_length=88, check_only=False):
# Determine source (file or code string)
if file_path:
target_file = str(Path(file_path))
original_content = Path(file_path).read_text()
elif code:
with tempfile.NamedTemporaryFile(mode="w", suffix=".py", delete=False) as f:
f.write(code)
target_file = f.name
original_content = code
# Run black
cmd = ["python", "-m", "black", f"--line-length={line_length}", "--quiet"]
if check_only:
cmd.extend(["--check", "--diff"])
cmd.append(target_file)
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
# Read formatted content
formatted_content = original_content
if not check_only and result.returncode == 0:
formatted_content = Path(target_file).read_text()
# Generate diff
needs_formatting = (result.returncode != 0 if check_only
else original_content != formatted_content)
diff = _generate_unified_diff(original_content, formatted_content) if needs_formatting else None
return {
"formatted": not check_only and needs_formatting,
"needs_formatting": needs_formatting,
"formatted_code": formatted_content if not check_only else None,
"diff": diff
}
Combined Analysis
Copy
def lint_and_format(file_path=None, code=None, fix=False, line_length=88):
# 1. Syntax check
syntax_check = self._validate_python_syntax(code or Path(file_path).read_text())
if not syntax_check["is_valid"]:
return {"syntax_valid": False, "syntax_errors": syntax_check["errors"]}
# 2. Pylint analysis
pylint_result = self._execute_tool("analyze_with_pylint", {...})
results["pylint"] = {
"total_issues": pylint_result["total_issues"],
"errors": pylint_result["errors"],
"issues": pylint_result["issues"][:10]
}
# 3. Black formatting
black_result = format_with_black(file_path, code, line_length, check_only=not fix)
results["formatting"] = {
"needs_formatting": black_result["needs_formatting"],
"formatted": black_result["formatted"]
}
# 4. Apply fixes if requested
if fix and black_result["formatted_code"]:
Path(file_path).write_text(black_result["formatted_code"])
results["file_updated"] = True
# Fix linting errors
if pylint_result["total_issues"] > 0:
fix_lint_result = self._execute_tool("fix_linting_errors", {...})
results["lint_fixes_applied"] = fix_lint_result["fixes_applied"]
results["clean"] = results["pylint"]["total_issues"] == 0 and not results["formatting"]["needs_formatting"]
return results
Testing Requirements
File:tests/agents/code/test_code_formatting_mixin.py
Copy
def test_format_with_black_formats_code():
"""Test Black formatting is applied."""
code = "x=1;y=2" # Poorly formatted
result = agent.format_with_black(code=code)
assert result["formatted"] is True
assert result["formatted_code"] == "x = 1\ny = 2\n"
def test_format_with_black_check_only():
"""Test check-only mode doesn't modify."""
code = "x=1"
result = agent.format_with_black(code=code, check_only=True)
assert result["needs_formatting"] is True
assert result["formatted_code"] is None
def test_lint_and_format_combined():
"""Test combined linting and formatting."""
code = "import os\nx=1" # Unused import + bad formatting
result = agent.lint_and_format(code=code)
assert result["syntax_valid"] is True
assert result["pylint"]["total_issues"] > 0
assert result["formatting"]["needs_formatting"] is True
def test_lint_and_format_with_fix(tmp_path):
"""Test auto-fix capability."""
file = tmp_path / "test.py"
file.write_text("x=1")
result = agent.lint_and_format(file_path=str(file), fix=True)
assert result["file_updated"] is True
assert result["formatting"]["formatted"] is True
Usage Examples
Copy
# Format code
result = agent.format_with_black(file_path="src/main.py")
if result["formatted"]:
print("Code formatted successfully")
print(f"Diff:\n{result['diff']}")
# Check formatting without modifying
result = agent.format_with_black(code=code_string, check_only=True)
if result["needs_formatting"]:
print("Code needs formatting")
# Combined analysis
result = agent.lint_and_format(file_path="src/main.py", fix=True)
print(f"Clean: {result['clean']}")
print(f"Pylint issues: {result['pylint']['total_issues']}")
print(f"Formatted: {result['formatting']['formatted']}")
Acceptance Criteria
- Black formatting integration
- Check-only mode
- Combined lint + format analysis
- Auto-fix with re-validation
- Unified diff generation
- Temp file handling for code strings
- Line length configuration
- Error handling for missing Black
CodeFormattingMixin Technical Specification