You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在pre-commit-config.yaml中引用pyproject.toml的配置?

问题描述

我有一个包含pyproject.toml和pre-commit-config.yaml的Python仓库。其中pyproject.toml内容如下:

[tool.poetry]
name = "projectname"
description = "My project's description"
authors = ["My Name <my-name@example.com>"]
version = "0.1.0"

现在我希望在pre-commit的自定义hook中,用pyproject.toml里的name字段替换配置中的<PROJECT-NAME-COMES-HERE>,目标hook配置如下:

- repo: local
    hooks:
      - id: check-for-utility-imports
        name: check-for-utility-imports
        entry: ^from <PROJECT-NAME-COMES-HERE>.utility.* import
        files: ^<PROJECT-NAME-COMES-HERE>/contracts/.*.py$
        language: pygrep
        types: [ python ]

请问有没有实现这个需求的方法?

实现方法

方法1:自定义Python脚本实现动态检查

pre-commit的local hook支持执行自定义脚本,你可以写一个脚本读取pyproject.toml的项目名称,再执行匹配检查:

  1. 在仓库根目录创建check_utility_imports.py脚本:
import tomllib
import re
import sys

# 读取pyproject.toml获取项目名称
with open("pyproject.toml", "rb") as f:
    pyproject_data = tomllib.load(f)
project_name = pyproject_data["tool"]["poetry"]["name"]

# 定义检查规则
import_regex = re.compile(rf"^from {project_name}\.utility\..* import", re.MULTILINE)
target_files_regex = re.compile(rf"^{project_name}/contracts/.*\.py$")

# 遍历传入的文件进行检查
error_messages = []
for file_path in sys.argv[1:]:
    if not target_files_regex.match(file_path):
        continue
    with open(file_path, "r", encoding="utf-8") as f:
        file_content = f.read()
    if import_regex.search(file_content):
        error_messages.append(f"禁止导入utility模块:{file_path}")

if error_messages:
    print("\n".join(error_messages))
    sys.exit(1)
  1. 更新pre-commit-config.yaml的hook配置:
- repo: local
    hooks:
      - id: check-for-utility-imports
        name: check-for-utility-imports
        entry: python check_utility_imports.py
        files: ^.*\.py$
        language: system
        types: [ python ]

方法2:环境变量注入项目名称

通过脚本提取项目名称并设置为环境变量,让pre-commit hook读取该变量:

  1. 编写setup_hooks.sh(适用于Linux/macOS):
#!/bin/bash
# 从pyproject.toml提取项目名称
PROJECT_NAME=$(grep -E '^name = ".*"' pyproject.toml | sed 's/name = "\(.*\)"/\1/')
# 注入环境变量并安装pre-commit钩子
PROJECT_NAME=$PROJECT_NAME pre-commit install
  1. 修改pre-commit-config.yaml,引用环境变量:
- repo: local
    hooks:
      - id: check-for-utility-imports
        name: check-for-utility-imports
        entry: ^from ${PROJECT_NAME}.utility.* import
        files: ^${PROJECT_NAME}/contracts/.*.py$
        language: pygrep
        types: [ python ]
        env:
          - PROJECT_NAME=${PROJECT_NAME}

注意:团队成员需要通过这个脚本安装钩子,否则环境变量不会生效。

方法3:Jinja2模板生成配置文件

将pre-commit配置做成模板,通过脚本渲染生成最终配置:

  1. 创建模板文件pre-commit-config.yaml.j2:
- repo: local
    hooks:
      - id: check-for-utility-imports
        name: check-for-utility-imports
        entry: ^from {{ project_name }}.utility.* import
        files: ^{{ project_name }}/contracts/.*.py$
        language: pygrep
        types: [ python ]
  1. 编写生成脚本generate_pre_commit_config.py:
import tomllib
from jinja2 import Template

# 读取项目名称
with open("pyproject.toml", "rb") as f:
    pyproject_data = tomllib.load(f)
project_name = pyproject_data["tool"]["poetry"]["name"]

# 渲染模板并生成配置文件
with open("pre-commit-config.yaml.j2", "r", encoding="utf-8") as f:
    template_content = f.read()
rendered_config = Template(template_content).render(project_name=project_name)

with open("pre-commit-config.yaml", "w", encoding="utf-8") as f:
    f.write(rendered_config)

每次项目名称变更后,运行该脚本重新生成pre-commit-config.yaml即可。


内容的提问来源于stack exchange,提问作者Saroopashree Kumaraguru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:05:32