Files
shanxia2.0/backend/scripts/check_pl_json_aliases.py
T
2026-06-21 09:19:07 +08:00

106 lines
2.8 KiB
Python
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 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())