77 lines
3.0 KiB
Python
77 lines
3.0 KiB
Python
|
|
"""D3 模型拆分归属保护(批次 4,2026-09-17)。
|
|||
|
|
|
|||
|
|
锁定三个拆分成果:
|
|||
|
|
1. 三包模型全量注册后 mapper 可配置、31 表齐全;
|
|||
|
|
2. 单模块部署(inventory-only / moldinsight-only + auth)独立配置 mapper 成功——
|
|||
|
|
跨模块 ORM relationship 已清零,任何一侧不注册对方模型也能工作;
|
|||
|
|
3. 旧 shared.models.database 模块已删除且无兼容 facade(诚实原则:不留假象)。
|
|||
|
|
"""
|
|||
|
|
import importlib
|
|||
|
|
import subprocess
|
|||
|
|
import sys
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
SRC = str(Path(__file__).resolve().parent.parent / "src")
|
|||
|
|
|
|||
|
|
EXPECTED_TABLES = {
|
|||
|
|
# identity(shared.models.identity)
|
|||
|
|
"users", "roles", "permissions", "user_roles", "role_permissions",
|
|||
|
|
"user_activities", "system_logs",
|
|||
|
|
# moldinsight.models
|
|||
|
|
"stp_files", "geometry_data", "mesh_data", "html_files", "processing_tasks",
|
|||
|
|
"mold_cavity_data", "feature_detections", "design_recommendations", "analysis_metrics",
|
|||
|
|
# inventory.models
|
|||
|
|
"products", "product_materials", "material_price_history", "material_suppliers",
|
|||
|
|
"suppliers", "customers", "warehouses", "inventory", "stock_movements",
|
|||
|
|
"purchase_orders", "purchase_order_items", "sales_orders", "sales_order_items",
|
|||
|
|
"finance_transactions", "finance_allocations",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_full_registration_covers_all_31_tables():
|
|||
|
|
import shared.models.identity # noqa: F401
|
|||
|
|
import moldinsight.models # noqa: F401
|
|||
|
|
import inventory.models # noqa: F401
|
|||
|
|
from sqlalchemy.orm import configure_mappers
|
|||
|
|
|
|||
|
|
from shared.models.base import Base
|
|||
|
|
|
|||
|
|
configure_mappers()
|
|||
|
|
assert set(Base.metadata.tables) == EXPECTED_TABLES
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_single_module_deployments_configure_mappers_independently():
|
|||
|
|
"""单模块注册子进程验证:inventory-only 与 moldinsight-only(含 auth identity)
|
|||
|
|
均可在不 import 对方业务模型的情况下 configure_mappers 成功。
|
|||
|
|
用子进程隔离,避免污染本进程的 mapper 注册表。"""
|
|||
|
|
code = (
|
|||
|
|
"import sys; sys.path.insert(0, r'%s')\n"
|
|||
|
|
"from sqlalchemy.orm import configure_mappers\n"
|
|||
|
|
"%s\n"
|
|||
|
|
"configure_mappers()\n"
|
|||
|
|
"print('ok')\n"
|
|||
|
|
)
|
|||
|
|
cases = [
|
|||
|
|
# inventory-only:inventory 模型 + auth 必带的 identity
|
|||
|
|
"import inventory.models, shared.models.identity",
|
|||
|
|
# moldinsight-only:moldinsight 模型 + auth 必带的 identity
|
|||
|
|
"import moldinsight.models, shared.models.identity",
|
|||
|
|
]
|
|||
|
|
for imports in cases:
|
|||
|
|
proc = subprocess.run(
|
|||
|
|
[sys.executable, "-c", code % (SRC, imports)],
|
|||
|
|
capture_output=True, text=True, timeout=120,
|
|||
|
|
)
|
|||
|
|
assert proc.returncode == 0, f"{imports} 配置失败:\n{proc.stderr}"
|
|||
|
|
assert proc.stdout.strip().endswith("ok")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def test_legacy_database_module_is_gone():
|
|||
|
|
"""旧 shared.models.database 已物理删除,无兼容 facade。"""
|
|||
|
|
try:
|
|||
|
|
importlib.import_module("shared.models.database")
|
|||
|
|
except ModuleNotFoundError:
|
|||
|
|
pass
|
|||
|
|
else:
|
|||
|
|
raise AssertionError("shared.models.database 仍可导入——拆分后不允许残留兼容 facade")
|