diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..149cdb4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,36 @@ +# Pre-commit hooks for Agent Arena +# Install: pip install pre-commit && pre-commit install +# Run manually: pre-commit run --all-files + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + args: ['--maxkb=1000'] + - id: check-merge-conflict + + - repo: https://github.com/psf/black + rev: 24.2.0 + hooks: + - id: black + args: ['--config=pyproject.toml'] + files: ^python/ + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.15 + hooks: + - id: ruff + args: ['--fix', '--exit-non-zero-on-fix'] + files: ^python/ + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.8.0 + hooks: + - id: mypy + args: ['--ignore-missing-imports'] + files: ^python/(agent_runtime|backends|tools)/ + additional_dependencies: [] diff --git a/docs/linting_guide.md b/docs/linting_guide.md new file mode 100644 index 0000000..15c503a --- /dev/null +++ b/docs/linting_guide.md @@ -0,0 +1,173 @@ +# Linting Guide for Agent Arena + +## Overview +This project uses automated linting tools to maintain code quality and consistency. All Python code must pass linting checks before being merged. + +## Tools Used + +### 1. **Black** - Code Formatter +- Automatically formats Python code to maintain consistent style +- Configuration: `pyproject.toml` ([tool.black]) +- Line length: 100 characters + +### 2. **Ruff** - Fast Python Linter +- Catches common errors and enforces code quality rules +- Configuration: `pyproject.toml` ([tool.ruff.lint]) +- Checks for: unused imports, import sorting, naming conventions, and more + +### 3. **MyPy** - Static Type Checker +- Verifies type hints and catches type-related bugs +- Configuration: `pyproject.toml` ([tool.mypy]) +- Currently set to not fail builds (continue-on-error: true) + +## Running Linters Locally + +### Check for issues: +```bash +# Check formatting +python -m black --check python + +# Check linting +python -m ruff check python + +# Check types +mypy --ignore-missing-imports python/agent_runtime python/backends python/tools +``` + +### Auto-fix issues: +```bash +# Auto-format code +python -m black python + +# Auto-fix linting issues +python -m ruff check python --fix +``` + +## Pre-commit Hooks (Automatic Prevention) + +Pre-commit hooks automatically run linters before each commit, catching issues before they reach CI/CD. + +### Installation: +```bash +pip install pre-commit +pre-commit install +``` + +### Manual run on all files: +```bash +pre-commit run --all-files +``` + +### What happens on commit: +1. **Black** formats your Python files +2. **Ruff** checks and auto-fixes linting issues +3. **MyPy** checks types (optional) +4. If any issues can't be auto-fixed, the commit is blocked + +## Common Issues and Fixes + +### 1. Unused Imports +**Error:** `F401: 'module.Class' imported but unused` + +**Fix:** Remove the unused import +```python +# Before +from fastapi.responses import JSONResponse # Unused! +from fastapi import FastAPI + +# After +from fastapi import FastAPI +``` + +### 2. Import Sorting +**Error:** `I001: Import block is un-sorted or un-formatted` + +**Fix:** Run `python -m ruff check python --fix` to auto-sort imports + +Ruff follows this order: +1. Standard library imports +2. Third-party imports +3. Local imports (separated by blank lines) + +### 3. Line Too Long +**Error:** Lines longer than 100 characters + +**Fix:** Run `python -m black python` to auto-format + +## CI/CD Pipeline + +The GitHub Actions workflow (`.github/workflows/python-tests.yml`) runs: +1. **Black** check (fails if code isn't formatted) +2. **Ruff** check (fails on linting errors) +3. **MyPy** check (warnings only, doesn't fail build) + +### Viewing CI Results: +```bash +# List recent workflow runs +gh run list --workflow="Python Tests" + +# View specific run details +gh run view +``` + +## Best Practices + +1. **Run linters before committing:** + ```bash + python -m black python && python -m ruff check python --fix + ``` + +2. **Use pre-commit hooks** - They catch issues automatically + +3. **Don't disable linting rules** without team discussion + +4. **Keep imports clean** - Remove unused imports immediately + +5. **Format on save** - Configure your IDE to run Black on save: + - VSCode: Install "Black Formatter" extension + - PyCharm: Enable Black under Tools → Black + +## IDE Integration + +### VSCode Settings +Add to `.vscode/settings.json`: +```json +{ + "python.formatting.provider": "black", + "python.linting.enabled": true, + "python.linting.ruffEnabled": true, + "editor.formatOnSave": true +} +``` + +### PyCharm +1. Go to Preferences → Tools → Black +2. Enable "On code reformat" +3. Install Ruff plugin from marketplace + +## Troubleshooting + +### Pre-commit hooks not running? +```bash +# Reinstall hooks +pre-commit uninstall +pre-commit install +``` + +### Linter version conflicts? +```bash +# Update all linters +pip install --upgrade black ruff mypy pre-commit +``` + +### Can't fix an issue? +- Check the specific error code in [Ruff documentation](https://docs.astral.sh/ruff/rules/) +- Ask the team for help +- Comment the line with `# noqa: ` only as last resort + +## Summary + +✅ All Python code must pass Black, Ruff, and MyPy checks +✅ Pre-commit hooks prevent issues before they reach CI/CD +✅ Use `--fix` flags to auto-resolve most issues +✅ Configure your IDE for automatic formatting diff --git a/pyproject.toml b/pyproject.toml index d94fc4a..a3c6c40 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,8 @@ include = '\.pyi?$' [tool.ruff] line-length = 100 target-version = "py311" + +[tool.ruff.lint] select = ["E", "F", "I", "N", "W", "UP"] ignore = ["E501"] # Line too long (handled by black) diff --git a/python/ipc/__init__.py b/python/ipc/__init__.py index 8f37582..9432a61 100644 --- a/python/ipc/__init__.py +++ b/python/ipc/__init__.py @@ -2,7 +2,7 @@ IPC module for communication between Godot and Python. """ +from .messages import ActionMessage, PerceptionMessage, TickRequest, TickResponse from .server import IPCServer -from .messages import PerceptionMessage, ActionMessage, TickRequest, TickResponse __all__ = ["IPCServer", "PerceptionMessage", "ActionMessage", "TickRequest", "TickResponse"] diff --git a/python/ipc/server.py b/python/ipc/server.py index 2f59ece..4c6b9c6 100644 --- a/python/ipc/server.py +++ b/python/ipc/server.py @@ -5,16 +5,15 @@ and returns actions to execute in the simulation. """ -import asyncio import logging import time from contextlib import asynccontextmanager from typing import Any from fastapi import FastAPI, HTTPException -from fastapi.responses import JSONResponse from agent_runtime.runtime import AgentRuntime + from .messages import ActionMessage, TickRequest, TickResponse logger = logging.getLogger(__name__) diff --git a/python/pyproject.toml b/python/pyproject.toml index d052bf9..b4f6e44 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -76,6 +76,8 @@ include = '\.pyi?$' [tool.ruff] line-length = 100 target-version = "py311" + +[tool.ruff.lint] select = ["E", "F", "I", "N", "W", "UP"] ignore = ["E501"]