Files
playbook/test/templates/validate_python_templates.sh
T
cshandClaude Opus 4.6 8b93311cae 📝 docs(tsl): clarify syntax constraints and enhance test infrastructure
- Add TSF file naming constraint to syntax/02_core_model.md
- Clarify semicolon rules: syntax facts vs style preferences
- Separate control flow end semicolon rules (syntax allows both)
- Add function body semicolon requirements to syntax/05_functions_and_calls.md
- Move style preferences to code_style.md (control flow end semicolons)
- Remove cross-references from syntax docs to maintain independence
- Enhance Gitea workflow emoji for better CI output readability
- Fix CI test path from tests/ to test/
- Organize agent test results under test/agent/result/ directory
- Add complete Chinese translation of test cases (test_cases_zh.md)
- Clean up .gitignore to use unified test/agent/result/ directory
- Remove obsolete agent test artifacts (REPORTS_LOCATION.md, old results)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-21 17:04:50 +08:00

340 lines
9.7 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env sh
# Python 模板验证脚本
set -eu
echo "========================================"
echo "🐍 Python 模板验证"
echo "========================================"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PLAYBOOK_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
TEMPLATES_DIR="$PLAYBOOK_ROOT/templates/python"
VALIDATION_PASSED=0
VALIDATION_FAILED=0
ERRORS_FILE="/tmp/python_template_validation_errors.txt"
REPORT_FILE="$SCRIPT_DIR/python_validation_report.txt"
> "$ERRORS_FILE"
> "$REPORT_FILE"
echo "📁 模板目录: $TEMPLATES_DIR"
echo ""
# ============================================
# 辅助函数
# ============================================
validate_file_exists() {
local file="$1"
local description="$2"
if [ -f "$file" ]; then
echo " ✅ $description: $(basename "$file")"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
return 0
else
echo " ❌ $description: $(basename "$file") - 文件不存在"
echo "文件不存在: $file" >> "$ERRORS_FILE"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
return 1
fi
}
validate_toml_syntax() {
local file="$1"
local description="$2"
if ! command -v python3 >/dev/null 2>&1; then
echo " ⚠️ $description: 跳过(Python3 未安装)"
return 0
fi
if python3 << EOF
import sys
parser = None
for module_name in ("tomli", "tomllib", "toml"):
try:
parser = __import__(module_name)
break
except ImportError:
continue
if parser is None:
print("缺少 TOML 解析器(需要 tomli、tomllib 或 toml", file=sys.stderr)
sys.exit(2)
try:
with open("$file", "rb") as f:
parser.load(f)
sys.exit(0)
except Exception as e:
print(f"TOML 语法错误: {e}", file=sys.stderr)
sys.exit(1)
EOF
then
echo " ✅ $description: TOML 语法正确"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
return 0
else
status=$?
if [ "$status" -eq 2 ]; then
echo " ❌ $description: 缺少 TOML 解析器"
echo "缺少 TOML 解析器: $file" >> "$ERRORS_FILE"
else
echo " ❌ $description: TOML 语法错误"
echo "TOML 语法错误: $file" >> "$ERRORS_FILE"
fi
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
return 1
fi
}
validate_required_sections() {
local file="$1"
local sections="$2"
for section in $sections; do
if grep -q "^\[$section\]" "$file"; then
echo " ✓ 包含 [$section] 配置"
else
echo " ✗ 缺少 [$section] 配置"
echo "缺少配置节: $section in $file" >> "$ERRORS_FILE"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
done
}
# ============================================
# 验证 pyproject.toml
# ============================================
echo "🔍 验证 pyproject.toml"
PYPROJECT="$TEMPLATES_DIR/pyproject.toml"
if validate_file_exists "$PYPROJECT" "pyproject.toml"; then
# 验证 TOML 语法
validate_toml_syntax "$PYPROJECT" "pyproject.toml"
# 验证必要的配置节
echo " 📋 检查必要配置节:"
validate_required_sections "$PYPROJECT" "tool.black tool.isort tool.pytest.ini_options"
# 验证 black 配置
if grep -q "line-length = 80" "$PYPROJECT"; then
echo " ✓ black line-length 配置正确"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ black line-length 配置缺失或不正确"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
# 验证 isort 配置
if grep -q "profile = \"google\"" "$PYPROJECT"; then
echo " ✓ isort profile 配置正确"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ isort profile 配置缺失或不正确"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
fi
echo ""
# ============================================
# 验证 .flake8
# ============================================
echo "🔍 验证 .flake8"
FLAKE8="$TEMPLATES_DIR/.flake8"
if validate_file_exists "$FLAKE8" ".flake8"; then
# 验证 [flake8] 节
if grep -q "^\[flake8\]" "$FLAKE8"; then
echo " ✓ 包含 [flake8] 配置"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
# 验证 max-line-length
if grep -q "^max-line-length" "$FLAKE8"; then
echo " ✓ 配置了 max-line-length"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ 缺少 max-line-length 配置"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
# 验证 extend-ignore
if grep -q "^extend-ignore" "$FLAKE8" || grep -q "^ignore" "$FLAKE8"; then
echo " ✓ 配置了错误忽略规则"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
else
echo " ✗ 缺少 [flake8] 配置节"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
fi
echo ""
# ============================================
# 验证 .pylintrc
# ============================================
echo "🔍 验证 .pylintrc"
PYLINTRC="$TEMPLATES_DIR/.pylintrc"
if validate_file_exists "$PYLINTRC" ".pylintrc"; then
# 验证关键配置节
for section in "MASTER" "MESSAGES CONTROL" "FORMAT"; do
if grep -qi "^\[$section\]" "$PYLINTRC"; then
echo " ✓ 包含 [$section] 配置"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ 缺少 [$section] 配置"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
done
# 验证 max-line-length
if grep -q "^max-line-length" "$PYLINTRC"; then
echo " ✓ 配置了 max-line-length"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
fi
echo ""
# ============================================
# 验证 .pre-commit-config.yaml
# ============================================
echo "🔍 验证 .pre-commit-config.yaml"
PRECOMMIT="$TEMPLATES_DIR/.pre-commit-config.yaml"
if validate_file_exists "$PRECOMMIT" ".pre-commit-config.yaml"; then
# 验证 YAML 语法
if command -v yamllint >/dev/null 2>&1; then
if yamllint -d relaxed "$PRECOMMIT" >/dev/null 2>&1; then
echo " ✓ YAML 语法正确"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ YAML 语法错误"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
fi
# 验证包含 pre-commit hooks
if grep -q "^repos:" "$PRECOMMIT"; then
echo " ✓ 包含 repos 配置"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
# 检查常用 hooks
for hook in "black" "isort" "flake8"; do
if grep -q "$hook" "$PRECOMMIT"; then
echo " ✓ 配置了 $hook hook"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
done
fi
fi
echo ""
# ============================================
# 验证 .editorconfig
# ============================================
echo "🔍 验证 .editorconfig"
EDITORCONFIG="$TEMPLATES_DIR/.editorconfig"
if validate_file_exists "$EDITORCONFIG" ".editorconfig"; then
# 验证包含 root 标记
if grep -q "^root = true" "$EDITORCONFIG"; then
echo " ✓ 包含 root = true"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
# 验证 Python 配置节
if grep -q "^\[\*.py\]" "$EDITORCONFIG" || grep -q "^\[*.py\]" "$EDITORCONFIG"; then
echo " ✓ 包含 Python 文件配置"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
fi
echo ""
# ============================================
# 验证 VSCode 配置
# ============================================
echo "🔍 验证 .vscode/settings.json"
VSCODE_SETTINGS="$TEMPLATES_DIR/.vscode/settings.json"
if validate_file_exists "$VSCODE_SETTINGS" "settings.json"; then
# 验证 JSON 语法
if command -v python3 >/dev/null 2>&1; then
if python3 -m json.tool "$VSCODE_SETTINGS" >/dev/null 2>&1; then
echo " ✓ JSON 语法正确"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
else
echo " ✗ JSON 语法错误"
VALIDATION_FAILED=$((VALIDATION_FAILED + 1))
fi
fi
# 验证 Python 相关配置
if grep -q "python" "$VSCODE_SETTINGS"; then
echo " ✓ 包含 Python 配置"
VALIDATION_PASSED=$((VALIDATION_PASSED + 1))
fi
fi
echo ""
# ============================================
# 生成验证报告
# ============================================
echo "========================================"
echo "📊 验证结果统计"
echo "========================================"
echo "✅ 通过: $VALIDATION_PASSED"
echo "❌ 失败: $VALIDATION_FAILED"
echo "📈 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%"
echo ""
# 写入报告文件
{
echo "Python 模板验证报告"
echo "===================="
echo ""
echo "验证时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "模板目录: $TEMPLATES_DIR"
echo ""
echo "统计结果:"
echo " 通过: $VALIDATION_PASSED"
echo " 失败: $VALIDATION_FAILED"
echo " 通过率: $(awk "BEGIN {printf \"%.1f\", ($VALIDATION_PASSED * 100.0) / ($VALIDATION_PASSED + $VALIDATION_FAILED)}")%"
echo ""
if [ -s "$ERRORS_FILE" ]; then
echo "错误详情:"
cat "$ERRORS_FILE"
fi
} > "$REPORT_FILE"
echo "📄 详细报告: $REPORT_FILE"
echo "========================================"
# 清理临时文件
rm -f "$ERRORS_FILE"
# 返回结果
if [ "$VALIDATION_FAILED" -eq 0 ]; then
echo "✅ 所有 Python 模板验证通过"
exit 0
else
echo "❌ Python 模板验证失败 ($VALIDATION_FAILED 个错误)"
exit 1
fi