modern-python

This skill implements Trail of Bits' modern Python coding standards for the agent-studio framework. The core philosophy is: use Rust-based tools for faster feedback loops, especially when working with AI agents. Every tool in this stack (uv, ruff, ty) is written in Rust and provides sub-second execution times, enabling tight iteration cycles.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "modern-python" with this command: npx skills add oimiragieo/agent-studio/oimiragieo-agent-studio-modern-python

Modern Python Skill

Overview

This skill implements Trail of Bits' modern Python coding standards for the agent-studio framework. The core philosophy is: use Rust-based tools for faster feedback loops, especially when working with AI agents. Every tool in this stack (uv, ruff, ty) is written in Rust and provides sub-second execution times, enabling tight iteration cycles.

Source repository: https://github.com/trailofbits/skills

Template: https://github.com/trailofbits/cookiecutter-python

License: CC-BY-SA-4.0

When to Use

  • When creating new Python projects from scratch

  • When migrating Python projects from legacy tooling

  • When setting up CI/CD pipelines for Python projects

  • When standardizing Python tooling across a team

  • When writing standalone Python scripts that need proper structure

  • When an AI agent needs fast feedback from Python tooling

Iron Laws

  • ALWAYS configure all Python tooling in pyproject.toml -- no separate config files (setup.cfg , .flake8 , mypy.ini , black.toml ) are permitted.

  • ALWAYS use uv add /uv remove for dependency management -- never use bare pip install in projects managed by uv.

  • NEVER commit venv/ , .venv/ , or pip-generated requirements.txt -- commit uv.lock for reproducible builds.

  • ALWAYS use uv run to execute tools and scripts -- this ensures the correct virtual environment and dependency resolution.

  • NEVER use legacy linting/formatting tools (flake8, black, isort, mypy) when ruff and ty are available -- consolidate to the Rust-based stack for speed and consistency.

Anti-Patterns

Anti-Pattern Why It Fails Correct Approach

Using pip install directly in a uv-managed project Bypasses lockfile and dependency resolution; creates reproducibility drift Use uv add <pkg> to add dependencies and uv sync to install

Maintaining .flake8 , mypy.ini , or black.toml config files Fragments configuration across multiple files; hard to maintain and audit Consolidate all tool config into pyproject.toml under [tool.ruff] and [tool.ty]

Running python script.py instead of uv run python script.py

Uses system Python instead of project venv; dependency mismatches Always use uv run to execute within the managed environment

Globally installing CLI tools with pip install --user

Pollutes global environment; version conflicts across projects Use uv tool run <tool> or uvx <tool> for one-off tool execution

Ignoring ruff security rules (S select) Misses bandit-equivalent security checks like hardcoded passwords and SQL injection Enable select = ["S"] in [tool.ruff.lint] for security linting

The Modern Python Stack

Tool Replaces Purpose Speed

uv pip, Poetry, pipenv, pip-tools Package & project management 10-100x faster

ruff flake8, isort, black, pyflakes, pycodestyle, pydocstyle Linting + formatting 10-100x faster

ty mypy, pyright, pytype Type checking 5-10x faster

pytest unittest Testing

hypothesis (manual property tests) Property-based testing

Project Setup

New Project

Create new project with uv

uv init my-project cd my-project

Add dependency groups

uv add --group dev ruff ty uv add --group test pytest pytest-cov hypothesis uv add --group docs sphinx myst-parser

Install all dependencies

uv sync --all-groups

pyproject.toml Configuration

[project] name = "my-project" version = "0.1.0" requires-python = ">=3.12" dependencies = []

[dependency-groups] dev = ["ruff", "ty"] test = ["pytest", "pytest-cov", "hypothesis"] docs = ["sphinx", "myst-parser"]

=== Ruff Configuration ===

[tool.ruff] target-version = "py312" line-length = 100

[tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "N", # pep8-naming "UP", # pyupgrade "B", # flake8-bugbear "A", # flake8-builtins "C4", # flake8-comprehensions "SIM", # flake8-simplify "S", # flake8-bandit (security) "TCH", # flake8-type-checking "RUF", # ruff-specific rules ]

[tool.ruff.lint.per-file-ignores] "tests/**/*.py" = ["S101"] # Allow assert in tests

[tool.ruff.format] quote-style = "double" indent-style = "space"

=== Pytest Configuration ===

[tool.pytest.ini_options] testpaths = ["tests"] addopts = [ "--strict-markers", "--strict-config", "-ra", ]

[tool.coverage.run] source = ["src"] branch = true

[tool.coverage.report] fail_under = 80 show_missing = true exclude_lines = [ "if TYPE_CHECKING:", "if name == .main.:", ]

Daily Workflow Commands

Package Management (uv)

Add a dependency

uv add requests

Add a dev dependency

uv add --group dev ipdb

Remove a dependency

uv remove requests

Update all dependencies

uv lock --upgrade

Update a specific dependency

uv lock --upgrade-package requests

Run a script in the project environment

uv run python script.py

Run a tool (without installing globally)

uv run --with httpie http GET https://api.example.com

Linting and Formatting (ruff)

Check for lint errors

uv run ruff check .

Auto-fix lint errors

uv run ruff check --fix .

Format code

uv run ruff format .

Check formatting (dry run)

uv run ruff format --check .

Check specific rules

uv run ruff check --select S . # Security rules only

Type Checking (ty)

Run type checker

uv run ty check

Check specific file

uv run ty check src/main.py

Testing (pytest)

Run all tests

uv run pytest

Run with coverage

uv run pytest --cov

Run specific test file

uv run pytest tests/test_auth.py

Run with verbose output

uv run pytest -v

Run and stop at first failure

uv run pytest -x

Migration Guide

From pip/requirements.txt

Install uv

curl -LsSf https://astral.sh/uv/install.sh | sh

Initialize project from existing requirements

uv init uv add $(cat requirements.txt | grep -v '^#' | grep -v '^$')

Remove old files

rm requirements.txt requirements-dev.txt

From Poetry

uv can read pyproject.toml with Poetry sections

uv init

Move Poetry dependencies to [project.dependencies]

Move [tool.poetry.group.dev.dependencies] to [dependency-groups]

Remove [tool.poetry] section

uv sync

From flake8/black/isort to ruff

Remove old tools

uv remove flake8 black isort pyflakes pycodestyle

Add ruff

uv add --group dev ruff

Convert .flake8 config to ruff (manual)

ruff supports most flake8 rules with same codes

Remove old config files

rm .flake8 .isort.cfg pyproject.toml.bak

From mypy to ty

Remove mypy

uv remove mypy

Add ty

uv add --group dev ty

ty uses the same type annotation syntax as mypy

Most code requires no changes

CI/CD Configuration

GitHub Actions

name: CI

on: push: branches: [main] pull_request: branches: [main]

jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: astral-sh/setup-uv@v4 with: enable-cache: true

  - name: Install dependencies
    run: uv sync --all-groups

  - name: Lint
    run: uv run ruff check .

  - name: Format check
    run: uv run ruff format --check .

  - name: Type check
    run: uv run ty check

  - name: Test
    run: uv run pytest --cov --cov-report=xml

  - name: Upload coverage
    uses: codecov/codecov-action@v4
    with:
      file: coverage.xml

Dependabot Configuration

.github/dependabot.yml

version: 2 updates:

  • package-ecosystem: 'uv' directory: '/' schedule: interval: 'weekly' groups: all: patterns: - '*'

Pre-commit Hooks

.pre-commit-config.yaml

repos:

Code Patterns

Type Annotations

from future import annotations

from collections.abc import Sequence from typing import TypeAlias

Use modern syntax (Python 3.12+)

type Vector = list[float] # Type alias (PEP 695)

def process_items(items: Sequence[str], *, limit: int = 10) -> list[str]: """Process items with a limit.""" return [item.strip() for item in items[:limit]]

Use | instead of Union

def maybe_int(value: str) -> int | None: try: return int(value) except ValueError: return None

Project Structure

my-project/ pyproject.toml # Single config file for all tools uv.lock # Locked dependencies (commit this) src/ my_project/ init.py main.py models.py utils.py tests/ init.py test_main.py test_models.py conftest.py # Shared fixtures .github/ workflows/ ci.yml dependabot.yml .pre-commit-config.yaml

Common Pitfalls

  • Using pip directly: Always use uv add / uv remove / uv run . Never pip install .

  • Separate config files: All configuration goes in pyproject.toml . Delete .flake8 , mypy.ini , black.toml .

  • Global installs: Use uv run or uv tool run instead of globally installing CLI tools.

  • Missing lock file: Always commit uv.lock for reproducible builds.

  • Old Python syntax: Use ruff --select UP to auto-upgrade to modern syntax (match statements, | unions, etc.).

  • Ignoring security rules: Enable S (bandit) rules in ruff to catch security issues.

Integration with Agent-Studio

Recommended Workflow

  • Use modern-python to set up or migrate Python projects

  • Use python-backend-expert for framework-specific patterns (Django, FastAPI)

  • Use tdd skill for test-driven development workflow

  • Use comprehensive-unit-testing-with-pytest for test strategy

Complementary Skills

Skill Relationship

python-backend-expert

Framework-specific patterns (Django, FastAPI, Flask)

comprehensive-unit-testing-with-pytest

Testing strategies and patterns

comprehensive-type-annotations

Type annotation best practices

prioritize-python-3-10-features

Modern Python language features

tdd

Test-driven development methodology

property-based-testing

Hypothesis-based testing patterns

Memory Protocol

Before starting: Check if the project already has Python tooling configured. Identify which legacy tools need migration.

During setup: Write configuration incrementally, verifying each tool works before moving to the next. Run ruff check , ruff format --check , and uv run pytest at each step.

After completion: Record the toolchain versions and any migration issues to .claude/context/memory/learnings.md for future reference.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

pyqt6-ui-development-rules

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-analyzer

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

gcloud-cli

No summary provided by upstream source.

Repository SourceNeeds Review