如何在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的项目名称,再执行匹配检查:
- 在仓库根目录创建
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)
- 更新
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读取该变量:
- 编写
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
- 修改
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配置做成模板,通过脚本渲染生成最终配置:
- 创建模板文件
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 ]
- 编写生成脚本
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
相关产品推荐
相关产品推荐

