playbook/antigravity-awesome-skills/skills/ecl-harness-engineer/references/adapters/python.md

226 lines
7.3 KiB
Markdown

---
adapter:
language: python
display_name: "Python"
version: "1.0"
detection:
files: [pyproject.toml, setup.py, requirements.txt, Pipfile]
content_patterns:
- file: "pyproject.toml"
pattern: '\\[project\\]|\\[tool\\.poetry\\]'
confidence: 0.90
commands:
build: null # Python typically doesn't need a build step
test: "pytest"
lint: "ruff check ."
lint_arch: "python scripts/lint_deps.py src/"
format: "ruff format ."
start: null # Inferred from framework
dev: null
package_manager:
detection:
- lockfile: "poetry.lock"
manager: "poetry"
- lockfile: "uv.lock"
manager: "uv"
- lockfile: "Pipfile.lock"
manager: "pipenv"
- lockfile: "pdm.lock"
manager: "pdm"
default: "pip"
install_command: "{manager} install"
route_detection:
server_indicators:
- pattern: 'from fastapi|import fastapi|FastAPI\(\)'
description: "FastAPI ASGI framework"
frameworks: ["fastapi"]
- pattern: 'from flask|import flask|Flask\(__name__\)'
description: "Flask WSGI framework"
frameworks: ["flask"]
- pattern: 'from django|import django'
description: "Django web framework"
frameworks: ["django"]
- pattern: 'from aiohttp|import aiohttp\.web'
description: "aiohttp async web framework"
frameworks: ["aiohttp"]
- pattern: 'from starlette|import starlette'
description: "Starlette ASGI framework"
frameworks: ["starlette"]
- pattern: 'from litestar|import litestar'
description: "Litestar ASGI framework"
frameworks: ["litestar"]
cli_indicators:
- pattern: 'import click|from click'
description: "Click CLI framework"
frameworks: ["click"]
- pattern: 'import typer|from typer'
description: "Typer CLI framework"
frameworks: ["typer"]
- pattern: 'import argparse|from argparse'
description: "Standard library argparse"
frameworks: ["argparse"]
- pattern: 'import fire|from fire'
description: "Google Python Fire"
frameworks: ["fire"]
frontend_indicators: [] # Python is not typically used for frontend
patterns:
# FastAPI
- type: route
regex: '@(?:app|router)\.(get|post|put|delete|patch)\s*\(\s*["\x27]([^"\x27]+)["\x27]'
groups: [method, path]
frameworks: ["fastapi", "starlette", "litestar"]
# Flask
- type: route
regex: '@(?:app|bp|blueprint)\.(route)\s*\(\s*["\x27]([^"\x27]+)["\x27](?:.*methods\s*=\s*\[([^\]]+)\])?'
groups: [_, path, method]
frameworks: ["flask"]
# Django URLs
- type: route
regex: 'path\s*\(\s*["\x27]([^"\x27]+)["\x27]'
groups: [path]
frameworks: ["django"]
# Click
- type: command
regex: '@\w+\.command\s*\(\s*(?:name\s*=\s*)?["\x27]?([^"\x27\)]+)'
groups: [command_name]
frameworks: ["click"]
# Typer
- type: command
regex: '@app\.command\s*\(\s*(?:name\s*=\s*)?["\x27]?([^"\x27\)]*)'
groups: [command_name]
frameworks: ["typer"]
import_analysis:
list_packages: null
import_pattern: "^(?:from|import)\\s+([\\w.]+)"
source_extensions: [".py"]
module_root_file: "pyproject.toml"
layer_conventions:
patterns:
- layer: 0
paths: ["src/models", "src/schemas", "src/types", "models", "schemas"]
description: "Data models, Pydantic schemas, type definitions"
- layer: 1
paths: ["src/utils", "src/lib", "src/common", "utils", "lib"]
description: "Shared utilities"
- layer: 2
paths: ["src/services", "src/core", "src/domain", "services", "core"]
description: "Business logic, service layer"
- layer: 3
paths: ["src/api", "src/routes", "src/views", "src/handlers", "api", "routes"]
description: "API endpoints, request handlers"
- layer: 4
paths: ["src/main.py", "src/app.py", "src/cli.py", "main.py", "app.py"]
description: "Application entry points"
dependency_detection:
manifest_file: "pyproject.toml"
databases:
- pattern: "psycopg|asyncpg|sqlalchemy.*postgres|databases.*postgres"
type: "postgres"
default_port: 5432
- pattern: "pymysql|aiomysql|mysqlclient"
type: "mysql"
default_port: 3306
- pattern: "pymongo|motor"
type: "mongodb"
default_port: 27017
- pattern: "redis|aioredis"
type: "redis"
default_port: 6379
- pattern: "aiosqlite|sqlite3"
type: "sqlite"
default_port: 0
services:
- pattern: "confluent-kafka|aiokafka"
type: "kafka"
default_port: 9092
- pattern: "pika|aio-pika"
type: "rabbitmq"
default_port: 5672
- pattern: "elasticsearch|elastic-transport"
type: "elasticsearch"
default_port: 9200
env_var_patterns:
- pattern: 'os\.environ\.get\(\s*["\x27]([^"\x27]+)["\x27]'
- pattern: 'os\.environ\[["\x27]([^"\x27]+)["\x27]\]'
- pattern: 'os\.getenv\(\s*["\x27]([^"\x27]+)["\x27]'
linter:
template_section: "python-linter"
script_extension: ".py"
run_command: "python scripts/lint_deps.py src/"
naming:
file_pattern: "^[a-z][a-z0-9_]*\\.py$"
test_pattern: "^test_[a-z][a-z0-9_]*\\.py$"
directory_style: "snake_case"
ci:
github_actions:
image: "python:3.12"
setup_steps:
- "uses: actions/setup-python@v5\n with:\n python-version: '3.12'"
cache_paths: ["~/.cache/pip", ".venv"]
---
# Python Adapter
## Server Start Command Inference
1. Existing `harness/config/environment.json` startup command, if present
2. FastAPI detected → `python -m uvicorn {module}:app --port 8080`
- Module inferred from main app file location
3. Flask detected → `python -m flask run --port 8080`
4. Django detected → `python manage.py runserver 8080`
5. `main.py` exists → `python main.py`
## Virtual Environment Detection
The adapter checks for virtual environments in this order:
1. `.venv/` directory → `source .venv/bin/activate`
2. `venv/` directory → `source venv/bin/activate`
3. `poetry.lock``poetry shell` or prefix with `poetry run`
4. `uv.lock` → prefix with `uv run`
5. `Pipfile.lock` → prefix with `pipenv run`
## Framework-Specific Notes
### FastAPI
- Routes via decorators: `@app.get("/path")`, `@router.post("/path")`
- Dependency injection via `Depends()`
- Auto-generated OpenAPI docs at `/docs` and `/redoc`
- Start with uvicorn: `uvicorn app.main:app --reload`
### Flask
- Routes via decorators: `@app.route("/path", methods=["GET"])`
- Blueprints for modular routing
- Start with: `flask run` or `python -m flask run`
### Django
- URL configuration in `urls.py`: `path("api/", include("app.urls"))`
- Class-based views and function-based views
- Start with: `python manage.py runserver`
- Migrations: `python manage.py migrate`
### Click / Typer (CLI)
- Click: `@cli.command()` decorator pattern
- Typer: `@app.command()` decorator pattern, with auto-generated help
## Type Checking
Python projects may use type checkers:
- `mypy` — most common, configured in `pyproject.toml` or `mypy.ini`
- `pyright` — Microsoft's type checker, often via Pylance
- `pytype` — Google's type checker
Detection: check `pyproject.toml` `[tool.mypy]` or `mypy.ini` existence.