AgentSkillsCN

python-standards

为放大器模块制定Python编码标准,涵盖类型提示、异步模式、错误处理与代码格式化。适用于为放大器模块编写Python代码时使用。

SKILL.md
--- frontmatter
name: python-standards
description: Python coding standards for Amplifier including type hints, async patterns, error handling, and formatting. Use when writing Python code for Amplifier modules.
version: 1.0.0
license: MIT
metadata:
  category: development
  complexity: low

Python Coding Standards

Type Hints

ALL functions must have complete type hints:

python
from typing import Any

async def process_data(items: list[str], config: dict[str, Any]) -> dict[str, Any]:
    """Process data items with configuration."""
    results = {}
    for item in items:
        results[item] = await transform(item, config)
    return results

Include type hints for self:

python
class MyClass:
    def __init__(self: "MyClass", name: str) -> None:
        self.name = name

    async def process(self: "MyClass") -> str:
        return f"Processing {self.name}"

Async Patterns

All I/O operations must be async:

python
# Good
async def read_file(path: Path) -> str:
    content = path.read_text()  # For now, sync is OK
    return content

# Better (when using async libraries)
async def read_file(path: Path) -> str:
    async with aiofiles.open(path) as f:
        return await f.read()

Use asyncio.gather for parallel operations:

python
async def process_files(files: list[Path]) -> list[dict]:
    tasks = [process_file(f) for f in files]
    return await asyncio.gather(*tasks)

Error Handling

Return errors, don't raise:

python
from amplifier_core import ToolResult

async def execute(self: "MyTool", input: dict[str, Any]) -> ToolResult:
    """Execute tool operation."""
    try:
        result = await self._process(input)
        return ToolResult(success=True, output=result)
    except ValueError as e:
        logger.error(f"Validation error: {e}")
        return ToolResult(success=False, error={"message": str(e)})

Provide clear error messages:

python
# Good
return ToolResult(
    success=False,
    error={"message": f"File not found: {path}"}
)

# Bad
return ToolResult(
    success=False,
    error={"message": "Error"}
)

Formatting

Line length: 120 characters

Import organization:

python
# Standard library
import asyncio
import logging
from pathlib import Path
from typing import Any

# Third-party
import yaml
from pydantic import BaseModel

# Local/Amplifier
from amplifier_core import ModuleCoordinator, ToolResult

Files must end with newline - Add blank line at EOF

Use ruff for formatting:

bash
uv run ruff format .
uv run ruff check . --fix

Dependencies

Use uv for dependency management:

bash
# Add dependency
cd amplifier-module-tool-mytool
uv add package-name

# Add dev dependency
uv add --dev pytest ruff pyright

Never manually edit pyproject.toml dependencies - Use uv add

Testing

Test behavior at protocol level:

python
import pytest
from amplifier_core.testing import TestCoordinator

@pytest.mark.asyncio
async def test_tool_basic():
    """Test basic tool functionality."""
    coordinator = TestCoordinator()

    # Mount module
    await mount(coordinator, {"timeout": 10})

    # Get and test
    tool = coordinator.get("tools", "my-tool")
    result = await tool.execute({"param": "value"})

    assert result.success
    assert "expected" in result.output

Test pyramid: 60% unit, 30% integration, 10% end-to-end

Common Pitfalls

Don't use blocking I/O

python
# Bad
content = requests.get(url).text

# Good
async with aiohttp.ClientSession() as session:
    async with session.get(url) as response:
        content = await response.text()

Don't modify module internals from outside

python
# Bad
tool._internal_state = new_value

# Good
await tool.execute({"operation": "update", "value": new_value})

Don't put logic in mount()

python
# Bad
async def mount(coordinator, config):
    tool = MyTool()
    await tool.initialize_database()  # Heavy logic
    await coordinator.mount("tools", tool)

# Good
async def mount(coordinator, config):
    tool = MyTool(config)  # Light initialization only
    await coordinator.mount("tools", tool)
    # Heavy logic happens in execute(), not mount()

Remember

  • Run make check before committing
  • Keep modules focused and simple
  • Document public interfaces
  • Test at the protocol level