Files
gh-fcakyon-claude-codex-set…/hooks/scripts/python_code_quality.py
2025-11-29 18:26:40 +08:00

87 lines
2.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
PostToolUse hook: Auto-format Python files with ruff and block on errors
Inspired by onuralpszr's pre-commit hook: https://github.com/onuralpszr/onuralpszr/blob/main/configs/git-hooks/pre-commit-line-120
"""
import json
import shutil
import subprocess
import sys
from pathlib import Path
def main():
try:
data = json.load(sys.stdin)
# Get file path from tool input
file_path = data.get("tool_input", {}).get("file_path", "")
# Only process Python files
if not file_path.endswith('.py'):
sys.exit(0)
# Check if ruff is available - silent exit if not (no blocking)
if not shutil.which('ruff'):
sys.exit(0)
# Get directory containing the Python file
py_file = Path(file_path)
if not py_file.exists():
sys.exit(0)
work_dir = py_file.parent
# Run ruff check with fixes - capture output to check for errors
check_result = subprocess.run([
'ruff', 'check',
'--fix',
'--extend-select', 'F,I,D,UP,RUF,FA',
'--target-version', 'py39',
'--ignore', 'D100,D104,D203,D205,D212,D213,D401,D406,D407,D413,RUF001,RUF002,RUF012',
str(py_file)
], capture_output=True, text=True, cwd=work_dir)
# Block only if ruff check finds unfixable errors
if check_result.returncode != 0:
error_output = check_result.stdout.strip() or check_result.stderr.strip()
error_msg = f'ERROR running ruff check ❌ {error_output}'
print(error_msg, file=sys.stderr)
output = {
'systemMessage': f'Ruff errors detected in {py_file.name}',
'hookSpecificOutput': {'hookEventName': 'PostToolUse', 'decision': 'block', 'reason': error_msg},
}
print(json.dumps(output))
sys.exit(2)
# Run ruff format
format_result = subprocess.run([
'ruff', 'format',
'--line-length', '120',
str(py_file)
], capture_output=True, text=True, cwd=work_dir)
# Block only if ruff format fails (unlikely but possible)
if format_result.returncode != 0:
error_msg = f'ERROR running ruff format ❌ {format_result.stderr.strip()}'
print(error_msg, file=sys.stderr)
output = {
'systemMessage': f'Ruff format failed for {py_file.name}',
'hookSpecificOutput': {'hookEventName': 'PostToolUse', 'decision': 'block', 'reason': error_msg},
}
print(json.dumps(output))
sys.exit(2)
except Exception as e:
# Block on unexpected errors
error_msg = f'Python code quality hook error: {e}'
print(error_msg, file=sys.stderr)
sys.exit(2)
# Success - no errors
sys.exit(0)
if __name__ == '__main__':
main()