ruff

一、配置

pyproject.yaml

[build-system]
requires = ["hatchling>=1.27.0"]
build-backend = "hatchling.build"

[project]
name = "aaa"
version = "1.0.0"
description = "project"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "mcp>=1.13.1",
]

[dependency-groups]
dev = [
  "black>=25.11.0",
  "ruff>=0.8.0",
  "pre-commit>=4.5.0",
  "hatchling>=1.27.0",
  "pytest",
  "pytest-cov",
  "pytest-asyncio"
]

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
addopts = "-v --cov=src --cov-report=term-missing"
filterwarnings = ["ignore::DeprecationWarning", "ignore::UserWarning"]

[tool.coverage.report]
fail_under = 25

[tool.hatch.build.targets.wheel]
packages = ["src"]

# === 代码质量工具配置 ===

[tool.black]
line-length = 88
target-version = ["py312"]
include = '\.pyi?$'
extend-exclude = '''
^/build/
^/dist/
^/.venv/
^/venv/
'''

[[tool.uv.index]]
name = "tsinghua"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
default = true

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

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors (代码错误)
    "W",    # pycodestyle warnings (代码警告)
    "F",    # pyflakes (未使用导入、未定义变量等)
    "I",    # isort (导入排序)
    "B",    # flake8-bugbear (潜在bug)
    "C4",   # flake8-comprehensions (列表推导式优化)
    "UP",   # pyupgrade (Python升级建议)
    "SIM",  # flake8-simplify (代码简化)
    # "T20",  # flake8-print (print语句检查)
    "RET",  # flake8-return (返回语句优化)
    # "PTH",  # flake8-use-pathlib (pathlib使用建议)
]
ignore = [
    "E501",  # 行长度由Black处理
    "B008",  # 函数默认参数中不允许函数调用
    "C901",  # 函数复杂度过高
    "RET504", # 不必要的赋值后再返回
    "SIM108",   
    "SIM112",   
    "SIM115",
    "E741",  # 避免使用l、O、I作为变量名
    "B006",
    "F811",
]
fixable = [
    "E", "W", "F", "I", "UP", "SIM", "C4", "RET", "F841"
]

# 文件级忽略规则
per-file-ignores = { "__init__.py" = ["F401"], "agent_manager.py" = ["F401"] }

# 导入排序配置
[tool.ruff.lint.isort]
known-first-party = ["src"]
known-third-party = ["langchain", "langgraph", "pydantic", "fastapi"]
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]

# 规则特定配置
[tool.ruff.lint.flake8-bugbear]
extend-immutable-calls = ["fastapi.Depends", "fastapi.Query"]

[tool.ruff.lint.pyupgrade]
keep-runtime-typing = true

setup-precommit.py

#!/usr/bin/env python3
"""
Pre-commit钩子安装脚本
基于现代pre-commit框架
"""

import subprocess
import sys
from pathlib import Path


def install_precommit():
    """安装pre-commit钩子"""
    print("🚀 安装pre-commit钩子...")

    try:
        # 安装pre-commit
        subprocess.run([sys.executable, "-m", "pip", "install", "pre-commit"], check=True)

        # 安装钩子
        subprocess.run(["pre-commit", "install"], check=True)

        # 运行一次检查配置
        subprocess.run(["pre-commit", "run", "--all-files"], check=True)

        print("✅ pre-commit钩子安装完成!")
        print("💡 钩子将在每次git commit时自动运行")
        print("💡 手动运行: pre-commit run --all-files")

    except subprocess.CalledProcessError as e:
        print(f"❌ 安装失败: {e}")
        sys.exit(1)


def main():
    """主函数"""
    if not Path(".pre-commit-config.yaml").exists():
        print("❌ 未找到.pre-commit-config.yaml文件")
        sys.exit(1)

    install_precommit()


if __name__ == "__main__":
    main()

.pre-commit-config.yaml

# 现代pre-commit配置
# 基于Ruff的单一工具链
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.14.10
    hooks:
      # Ruff代码规范检查和自动修复
      - id: ruff
        args: [--fix, --unsafe-fixes, --exit-non-zero-on-fix]

      # 导入排序
      - id: ruff-format
        args: [--check]

  # Ruff-format 替代 Black,避免冲突
  - repo: local
    hooks:
      # 自定义检查:确保没有函数级导入
      - id: no-function-imports
        name: Check for function-level imports
        entry: bash -c 'ruff check --select=E402 src/ || (echo "❌ 发现函数级导入问题" && exit 1)'
        language: system
        pass_filenames: false
        always_run: true

二、使用

1、安装

# 安装Ruff和pre-commit
uv add ruff pre-commit

# 安装git hooks(首次使用)
mkdir -p .git/hooks
pre-commit install

# 更新
pre-commit autoupdate

2、使用

# 直接运行钩子脚本(如当前脚本)
./.git/hooks/pre-commit
# 对所有文件运行 pre-commit 检查
pre-commit run --all-files

# 对暂存区的文件运行 pre-commit 检查
pre-commit run
ruff format .
# 跳过检查(紧急情况)
git commit --no-verify -m "紧急提交"
git commit -n -m "紧急提交"

results matching ""

    No results matching ""