modern-python

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Modern Python Skill

现代Python工具链实践

<!-- Agent: evolution-orchestrator | Task: #2 | Session: 2026-02-21 --> <!-- License: CC-BY-SA-4.0 | Source: Trail of Bits (github.com/trailofbits/skills) --> <!-- Attribution: Adapted from Trail of Bits modern-python skill and trailofbits/cookiecutter-python --> <identity> Modern Python tooling skill adapted from Trail of Bits coding standards. Mandates the use of uv (package management), ruff (linting and formatting), ty (type checking), and pytest (testing) as the standard Python toolchain. Based on patterns from trailofbits/cookiecutter-python for consistent, high-quality Python projects. </identity> <capabilities> - Project initialization with modern Python toolchain (uv + ruff + ty + pytest) - Migration from legacy tools (pip/Poetry/pipenv to uv, black/flake8/isort to ruff, mypy to ty) - pyproject.toml configuration for all tools (single source of truth) - Dependency management with uv (lock files, dependency groups, virtual environments) - Linting and formatting with ruff (replaces flake8, isort, black, pyflakes, pycodestyle) - Type checking with ty (Rust-based, faster than mypy) - Testing with pytest, pytest-cov, and hypothesis - CI/CD configuration with GitHub Actions - Dependabot setup for automated dependency updates - Pre-commit hook configuration </capabilities>
<!-- Agent: evolution-orchestrator | Task: #2 | Session: 2026-02-21 --> <!-- License: CC-BY-SA-4.0 | Source: Trail of Bits (github.com/trailofbits/skills) --> <!-- Attribution: Adapted from Trail of Bits modern-python skill and trailofbits/cookiecutter-python --> <identity> 基于Trail of Bits编码标准适配的现代Python工具链实践。强制使用uv(包管理)、ruff(代码检查与格式化)、ty(类型校验)和pytest(测试)作为标准Python工具链。基于trailofbits/cookiecutter-python的模式,用于构建一致、高质量的Python项目。 </identity> <capabilities> - 基于现代Python工具链(uv + ruff + ty + pytest)初始化项目 - 从传统工具链迁移(pip/Poetry/pipenv 迁移至 uv,black/flake8/isort 迁移至 ruff,mypy 迁移至 ty) - 为所有工具配置pyproject.toml(单一可信源) - 使用uv进行依赖管理(锁文件、依赖组、虚拟环境) - 使用ruff进行代码检查与格式化(替代flake8、isort、black、pyflakes、pycodestyle) - 使用ty进行类型校验(基于Rust,比mypy更快) - 使用pytest、pytest-cov和hypothesis进行测试 - 配置GitHub Actions实现CI/CD - 配置Dependabot实现依赖自动更新 - 配置预提交钩子 </capabilities>

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
本实践为agent-studio框架实现了Trail of Bits的现代Python编码标准。核心理念是:使用基于Rust的工具以实现更快的反馈循环,尤其是在与AI Agent协作时。该工具栈中的每一个工具(uv、ruff、ty)均基于Rust开发,执行时间可达亚秒级,支持高效的迭代周期。
源码仓库
https://github.com/trailofbits/skills
模板
https://github.com/trailofbits/cookiecutter-python
许可证: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
  • 从零开始创建新Python项目时
  • 将Python项目从传统工具链迁移时
  • 为Python项目搭建CI/CD流水线时
  • 在团队内标准化Python工具链时
  • 编写需要规范结构的独立Python脚本时
  • AI Agent需要从Python工具链获取快速反馈时

Iron Law

铁律

ALL PYTHON TOOLING CONFIGURED IN pyproject.toml — NO SEPARATE CONFIG FILES
pyproject.toml
is the single source of truth for all tool configuration. No
setup.cfg
, no
.flake8
, no
mypy.ini
, no
black.toml
.
所有Python工具配置均需写入pyproject.toml — 禁止使用单独的配置文件
pyproject.toml
是所有工具配置的单一可信源。禁止使用
setup.cfg
.flake8
mypy.ini
black.toml

The Modern Python Stack

现代Python工具栈

ToolReplacesPurposeSpeed
uvpip, Poetry, pipenv, pip-toolsPackage & project management10-100x faster
ruffflake8, isort, black, pyflakes, pycodestyle, pydocstyleLinting + formatting10-100x faster
tymypy, pyright, pytypeType checking5-10x faster
pytestunittestTesting--
hypothesis(manual property tests)Property-based testing--
工具替代工具用途速度
uvpip、Poetry、pipenv、pip-tools包与项目管理快10-100倍
ruffflake8、isort、black、pyflakes、pycodestyle、pydocstyle代码检查 + 格式化快10-100倍
tymypy、pyright、pytype类型校验快5-10倍
pytestunittest测试--
hypothesis(手动属性测试)基于属性的测试--

Project Setup

项目搭建

New Project

新项目

bash
undefined
bash
undefined

Create new project with uv

使用uv创建新项目

uv init my-project cd my-project
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
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
undefined
uv sync --all-groups
undefined

pyproject.toml Configuration

pyproject.toml配置

toml
[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"]
toml
[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 ===

=== Ruff配置 ===

[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"
[tool.ruff] target-version = "py312" line-length = 100
[tool.ruff.lint] select = [ "E", # pycodestyle错误 "W", # pycodestyle警告 "F", # pyflakes "I", # isort "N", # pep8-naming "UP", # pyupgrade "B", # flake8-bugbear "A", # flake8-builtins "C4", # flake8-comprehensions "SIM", # flake8-simplify "S", # flake8-bandit(安全) "TCH", # flake8-type-checking "RUF", # ruff专属规则 ]
[tool.ruff.lint.per-file-ignores] "tests/**/*.py" = ["S101"] # 允许在测试中使用assert
[tool.ruff.format] quote-style = "double" indent-style = "space"

=== Pytest Configuration ===

=== Pytest配置 ===

[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.:", ]
undefined
[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":", ]
undefined

Daily Workflow Commands

日常工作流命令

Package Management (uv)

包管理(uv)

bash
undefined
bash
undefined

Add a dependency

添加依赖

uv add requests
uv add requests

Add a dev dependency

添加开发依赖

uv add --group dev ipdb
uv add --group dev ipdb

Remove a dependency

移除依赖

uv remove requests
uv remove requests

Update all dependencies

更新所有依赖

uv lock --upgrade
uv lock --upgrade

Update a specific dependency

更新特定依赖

uv lock --upgrade-package requests
uv lock --upgrade-package requests

Run a script in the project environment

在项目环境中运行脚本

uv run python script.py
uv run python script.py

Run a tool (without installing globally)

运行工具(无需全局安装)

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

Linting and Formatting (ruff)

代码检查与格式化(ruff)

bash
undefined
bash
undefined

Check for lint errors

检查代码错误

uv run ruff check .
uv run ruff check .

Auto-fix lint errors

自动修复代码错误

uv run ruff check --fix .
uv run ruff check --fix .

Format code

格式化代码

uv run ruff format .
uv run ruff format .

Check formatting (dry run)

检查代码格式(试运行)

uv run ruff format --check .
uv run ruff format --check .

Check specific rules

检查特定规则

uv run ruff check --select S . # Security rules only
undefined
uv run ruff check --select S . # 仅检查安全规则
undefined

Type Checking (ty)

类型校验(ty)

bash
undefined
bash
undefined

Run type checker

运行类型校验

uv run ty check
uv run ty check

Check specific file

检查特定文件

uv run ty check src/main.py
undefined
uv run ty check src/main.py
undefined

Testing (pytest)

测试(pytest)

bash
undefined
bash
undefined

Run all tests

运行所有测试

uv run pytest
uv run pytest

Run with coverage

运行测试并生成覆盖率报告

uv run pytest --cov
uv run pytest --cov

Run specific test file

运行特定测试文件

uv run pytest tests/test_auth.py
uv run pytest tests/test_auth.py

Run with verbose output

详细输出测试结果

uv run pytest -v
uv run pytest -v

Run and stop at first failure

遇到第一个测试失败时停止

uv run pytest -x
undefined
uv run pytest -x
undefined

Migration Guide

迁移指南

From pip/requirements.txt

从pip/requirements.txt迁移

bash
undefined
bash
undefined

Install uv

安装uv

Initialize project from existing requirements

从现有requirements初始化项目

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

Remove old files

删除旧文件

rm requirements.txt requirements-dev.txt
undefined
rm requirements.txt requirements-dev.txt
undefined

From Poetry

从Poetry迁移

bash
undefined
bash
undefined

uv can read pyproject.toml with Poetry sections

uv可以读取包含Poetry配置段的pyproject.toml

uv init
uv init

Move Poetry dependencies to [project.dependencies]

将Poetry依赖移至[project.dependencies]

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

将[tool.poetry.group.dev.dependencies]移至[dependency-groups]

Remove [tool.poetry] section

移除[tool.poetry]配置段

uv sync
undefined
uv sync
undefined

From flake8/black/isort to ruff

从flake8/black/isort迁移至ruff

bash
undefined
bash
undefined

Remove old tools

移除旧工具

uv remove flake8 black isort pyflakes pycodestyle
uv remove flake8 black isort pyflakes pycodestyle

Add ruff

添加ruff

uv add --group dev ruff
uv add --group dev ruff

Convert .flake8 config to ruff (manual)

手动将.flake8配置转换为ruff配置

ruff supports most flake8 rules with same codes

ruff支持大多数flake8规则,且规则代码一致

Remove old config files

删除旧配置文件

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

From mypy to ty

从mypy迁移至ty

bash
undefined
bash
undefined

Remove mypy

移除mypy

uv remove mypy
uv remove mypy

Add ty

添加ty

uv add --group dev ty
uv add --group dev ty

ty uses the same type annotation syntax as mypy

ty使用与mypy相同的类型注解语法

Most code requires no changes

大多数代码无需修改

undefined
undefined

CI/CD Configuration

CI/CD配置

GitHub Actions

GitHub Actions

yaml
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
yaml
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

Dependabot配置

yaml
undefined
yaml
undefined

.github/dependabot.yml

.github/dependabot.yml

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

Pre-commit Hooks

预提交钩子

yaml
undefined
yaml
undefined

.pre-commit-config.yaml

.pre-commit-config.yaml

repos:
undefined
repos:
undefined

Code Patterns

代码模式

Type Annotations

类型注解

python
from __future__ import annotations

from collections.abc import Sequence
from typing import TypeAlias
python
from __future__ import annotations

from collections.abc import Sequence
from typing import TypeAlias

Use modern syntax (Python 3.12+)

使用现代语法(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]]
type Vector = list[float] # 类型别名(PEP 695)
def process_items(items: Sequence[str], *, limit: int = 10) -> list[str]: """按限制条件处理条目。""" return [item.strip() for item in items[:limit]]

Use | instead of Union

使用|替代Union

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

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
my-project/
  pyproject.toml          # 所有工具的统一配置文件
  uv.lock                 # 锁定的依赖(需提交至仓库)
  src/
    my_project/
      __init__.py
      main.py
      models.py
      utils.py
  tests/
    __init__.py
    test_main.py
    test_models.py
    conftest.py           # 共享夹具
  .github/
    workflows/
      ci.yml
    dependabot.yml
  .pre-commit-config.yaml

Common Pitfalls

常见陷阱

  1. Using pip directly: Always use
    uv add
    /
    uv remove
    /
    uv run
    . Never
    pip install
    .
  2. Separate config files: All configuration goes in
    pyproject.toml
    . Delete
    .flake8
    ,
    mypy.ini
    ,
    black.toml
    .
  3. Global installs: Use
    uv run
    or
    uv tool run
    instead of globally installing CLI tools.
  4. Missing lock file: Always commit
    uv.lock
    for reproducible builds.
  5. Old Python syntax: Use
    ruff --select UP
    to auto-upgrade to modern syntax (match statements,
    |
    unions, etc.).
  6. Ignoring security rules: Enable
    S
    (bandit) rules in ruff to catch security issues.
  1. 直接使用pip:始终使用
    uv add
    /
    uv remove
    /
    uv run
    。禁止使用
    pip install
  2. 使用单独配置文件:所有配置必须写入
    pyproject.toml
    。删除
    .flake8
    mypy.ini
    black.toml
  3. 全局安装工具:使用
    uv run
    uv tool run
    替代全局安装CLI工具
  4. 缺失锁文件:必须提交
    uv.lock
    以实现可复现的构建
  5. 使用旧Python语法:使用
    ruff --select UP
    自动升级至现代语法(match语句、
    |
    联合类型等)
  6. 忽略安全规则:在ruff中启用
    S
    (bandit)规则以捕获安全问题

Integration with Agent-Studio

与Agent-Studio的集成

Recommended Workflow

推荐工作流

  1. Use
    modern-python
    to set up or migrate Python projects
  2. Use
    python-backend-expert
    for framework-specific patterns (Django, FastAPI)
  3. Use
    tdd
    skill for test-driven development workflow
  4. Use
    comprehensive-unit-testing-with-pytest
    for test strategy
  1. 使用
    modern-python
    搭建或迁移Python项目
  2. 使用
    python-backend-expert
    获取框架特定模式(Django、FastAPI)
  3. 使用
    tdd
    技能遵循测试驱动开发工作流
  4. 使用
    comprehensive-unit-testing-with-pytest
    制定测试策略

Complementary Skills

互补技能

SkillRelationship
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
技能关系
python-backend-expert
框架特定模式(Django、FastAPI、Flask)
comprehensive-unit-testing-with-pytest
测试策略与模式
comprehensive-type-annotations
类型注解最佳实践
prioritize-python-3-10-features
现代Python语言特性
tdd
测试驱动开发方法论
property-based-testing
基于Hypothesis的属性测试模式

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.
开始前:检查项目是否已配置Python工具链。识别需要迁移的传统工具。
搭建过程中:逐步编写配置,在进行下一步前验证每个工具是否正常工作。每一步都要运行
ruff check
ruff format --check
uv run pytest
完成后:记录工具链版本和迁移过程中遇到的问题至
.claude/context/memory/learnings.md
,以备未来参考。