From python-toolkit
Set up Python project with pyproject.toml, ruff, mypy, pre-commit, and uv
npx claudepluginhub infiquetra/infiquetra-claude-plugins --plugin python-toolkitThis skill uses the workspace's default tool permissions.
You are helping the user set up a Python project with modern tooling and Infiquetra standards.
Provides Ktor server patterns for routing DSL, plugins (auth, CORS, serialization), Koin DI, WebSockets, services, and testApplication testing.
Conducts multi-source web research with firecrawl and exa MCPs: searches, scrapes pages, synthesizes cited reports. For deep dives, competitive analysis, tech evaluations, or due diligence.
Provides demand forecasting, safety stock optimization, replenishment planning, and promotional lift estimation for multi-location retailers managing 300-800 SKUs.
You are helping the user set up a Python project with modern tooling and Infiquetra standards.
For a new Infiquetra Python project, create this structure:
project-name/
├── src/
│ └── service/
│ ├── __init__.py
│ └── handler.py
├── tests/
│ ├── __init__.py
│ ├── conftest.py
│ └── unit/
│ └── __init__.py
├── pyproject.toml
├── .pre-commit-config.yaml
├── .gitignore
├── README.md
└── .python-version (optional)
Start with the minimal template from references/pyproject-template.md:
[project]
name = "your-service-name"
version = "0.1.0"
description = "Your service description"
requires-python = ">=3.12"
dependencies = [
"boto3>=1.34.0",
"aws-lambda-powertools>=2.30.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"pytest-cov>=4.1.0",
"ruff>=0.2.0",
"mypy>=1.8.0",
"moto[all]>=5.0.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "B", "C4", "UP"]
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=src --cov-report=html --cov-fail-under=80"
[tool.mypy]
python_version = "3.12"
disallow_untyped_defs = true
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Or with homebrew
brew install uv
# Verify installation
uv --version
# Create virtual environment and install dependencies
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install project with dev dependencies
uv pip install -e ".[dev]"
# Or with standard pip
pip install -e ".[dev]"
Create .pre-commit-config.yaml (see references/pre-commit-config.md):
default_language_version:
python: python3.12
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy
additional_dependencies: [boto3-stubs]
- repo: https://github.com/PyCQA/bandit
rev: 1.7.6
hooks:
- id: bandit
args: [-r, src/]
Install hooks:
pip install pre-commit
pre-commit install
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual environments
venv/
.venv/
ENV/
env/
# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/
# IDEs
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# AWS
.aws-sam/
samconfig.toml
# Type checking
.mypy_cache/
.dmypy.json
dmypy.json
# src/service/__init__.py
"""Infiquetra Service."""
__version__ = "0.1.0"
# src/service/handler.py
from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.utilities.typing import LambdaContext
logger = Logger()
tracer = Tracer()
@logger.inject_lambda_context
@tracer.capture_lambda_handler
def handler(event: dict, context: LambdaContext) -> dict:
"""Lambda handler."""
logger.info("Processing request")
return {
"statusCode": 200,
"body": {"message": "Hello from Infiquetra!"},
}
# tests/conftest.py
import os
import pytest
# Set AWS credentials for moto
os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
os.environ["AWS_ACCESS_KEY_ID"] = "testing"
os.environ["AWS_SECRET_ACCESS_KEY"] = "testing"
@pytest.fixture
def lambda_context():
"""Mock Lambda context."""
class MockContext:
function_name = "test-function"
aws_request_id = "test-request-id"
def get_remaining_time_in_millis(self) -> int:
return 300000
return MockContext()
# tests/unit/test_handler.py
from src.service.handler import handler
def test_handler_success(lambda_context):
"""Test handler returns 200."""
event = {}
response = handler(event, lambda_context)
assert response["statusCode"] == 200
assert "message" in response["body"]
Ruff replaces flake8, isort, black, and more. Essential rules:
[tool.ruff]
line-length = 100
target-version = "py312"
src = ["src", "tests"]
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"W", # pycodestyle warnings
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"UP", # pyupgrade
]
ignore = [
"E501", # Line too long (handled by formatter)
]
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101"] # Allow assert in tests
Run ruff:
# Check for issues
ruff check .
# Auto-fix issues
ruff check . --fix
# Format code
ruff format .
Type checking configuration:
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
show_error_codes = true
pretty = true
# Allow third-party packages without stubs
[[tool.mypy.overrides]]
module = ["moto.*"]
ignore_missing_imports = true
Run mypy:
# Type check entire project
mypy src/
# Check specific file
mypy src/service/handler.py
Testing configuration:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = [
"--cov=src",
"--cov-report=html",
"--cov-report=term-missing",
"--cov-fail-under=80",
"-ra",
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow tests",
]
Run tests:
# Run all tests with coverage
pytest
# Run only unit tests
pytest -m unit
# Run with verbose output
pytest -v
# Run specific test file
pytest tests/unit/test_handler.py
uv is a fast Python package installer (10-100x faster than pip):
# Install dependencies
uv pip install -e ".[dev]"
# Add new dependency
uv pip install requests
# Update pyproject.toml manually, then:
uv pip install -e ".[dev]"
# Install from requirements.txt
uv pip install -r requirements.txt
# Compile requirements
uv pip compile pyproject.toml -o requirements.txt
[project]
dependencies = [
"boto3>=1.34.0",
"aws-lambda-powertools>=2.30.0",
]
[project]
dependencies = [
"fastapi>=0.109.0",
"uvicorn>=0.27.0",
"pydantic>=2.5.0",
]
[project]
dependencies = [
"aws-cdk-lib>=2.120.0",
"constructs>=10.3.0",
]
After setup, verify everything works:
# 1. Check ruff
ruff check .
# 2. Check mypy
mypy src/
# 3. Run tests
pytest
# 4. Test pre-commit
pre-commit run --all-files
# 5. Verify coverage
coverage report
All checks should pass with 0 errors and 80%+ coverage.
Install project in editable mode:
pip install -e .
Install type stubs:
pip install boto3-stubs[essential] types-requests
Run hooks manually to see detailed errors:
pre-commit run ruff --all-files
pre-commit run mypy --all-files
View coverage report:
coverage html
open htmlcov/index.html
Add tests for uncovered lines.
After project setup: