"""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")