This commit is contained in:
zlwu committed 2026-06-21 09:19:07 +08:00
1 parent c3be9d1dce
commit 299609706c
328 files changed
+144899 -13873

No files matched your search

+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env python3
"""校验运输计划模块 Pydantic Schema 是否具备 camelCase alias(防 422)。
用法(在 backend 目录):
./venv/bin/python scripts/check_pl_json_aliases.py
"""
from __future__ import annotations
import ast
import re
import sys
from pathlib import Path
SCHEMA_FILES = [
"app/schemas/pl/base_data.py",
"app/schemas/pl/plan.py",
"app/schemas/pl/transport.py",
"app/schemas/pl/freight.py",
"app/schemas/pl/inventory.py",
]
# 单段 snake_case 公共字段可不加 alias(JSON 与 Python 同名)
SINGLE_WORD_OK = {
"id",
"q",
"page",
"status",
"remark",
"model",
"unit",
"action",
"comment",
"total",
"list",
"products",
"transports",
"period",
"qty",
"amount",
}
def snake_to_camel(name: str) -> str:
parts = name.split("_")
return parts[0] + "".join(p.capitalize() for p in parts[1:])
def iter_field_assignments(tree: ast.AST):
for node in ast.walk(tree):
if not isinstance(node, ast.ClassDef):
continue
for stmt in node.body:
if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name):
yield node.name, stmt.target.id, stmt.value
elif isinstance(stmt, ast.Assign):
for target in stmt.targets:
if isinstance(target, ast.Name):
yield node.name, target.id, stmt.value
def field_has_alias(value: ast.expr | None) -> bool:
if value is None:
return False
if isinstance(value, ast.Call):
for kw in value.keywords:
if kw.arg == "alias":
return True
return False
def main() -> int:
root = Path(__file__).resolve().parents[1]
errors: list[str] = []
for rel in SCHEMA_FILES:
path = root / rel
if not path.exists():
errors.append(f"缺少文件: {rel}")
continue
source = path.read_text(encoding="utf-8")
tree = ast.parse(source, filename=str(path))
for class_name, field_name, value in iter_field_assignments(tree):
if "_" not in field_name:
continue
if field_name in SINGLE_WORD_OK or field_name == "model_config":
continue
if not field_has_alias(value):
expected = snake_to_camel(field_name)
errors.append(
f"{rel}: {class_name}.{field_name} 缺少 Field(alias=\"{expected}\")"
)
if errors:
print("PL JSON alias 校验失败(可能导致前端 camelCase 请求 422):\n")
for e in errors:
print(f" - {e}")
print("\n规范: openspec/changes/transport-plan-management/specs/pl-api-json/spec.md")
return 1
print("PL JSON alias 校验通过。")
return 0
if __name__ == "__main__":
sys.exit(main())