53 lines
2.1 KiB
Python
53 lines
2.1 KiB
Python
|
|
"""厂商集成包自动发现。
|
|||
|
|
|
|||
|
|
扫描 ``integrations/`` 目录下所有子包(厂商集成包),通过 ``importlib.import_module``
|
|||
|
|
触发子包 ``__init__.py`` 顶层副作用完成自注册。本函数不调用任何注册函数。
|
|||
|
|
|
|||
|
|
约定:
|
|||
|
|
- 使用 ``pkgutil.iter_modules`` 扫描 integrations 包路径下所有子包(ispkg=True),
|
|||
|
|
与 framework/auth_plugins/discovery.py 模式一致
|
|||
|
|
- 跳过框架自身模块黑名单:registry / schemas / discovery / operation_registry
|
|||
|
|
- 仅 ``importlib.import_module(name)``,不调用任何注册函数
|
|||
|
|
- 注册逻辑由子包 ``__init__.py`` 顶层副作用完成
|
|||
|
|
|
|||
|
|
容错策略(与 framework/registry/discovery.py::discover_adapters 对齐):
|
|||
|
|
- ImportError(可选依赖缺失)→ logger.warning,不中断启动
|
|||
|
|
- 其他异常(如 metadata 校验失败、register 键冲突)→ 向上抛出,快速失败
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
import importlib
|
|||
|
|
import logging
|
|||
|
|
import pkgutil
|
|||
|
|
from pathlib import Path
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
# 框架自身模块黑名单:非厂商集成包,跳过
|
|||
|
|
_BLACKLIST = {"registry", "schemas", "discovery", "operation_registry"}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def discover_integration_packages() -> list[str]:
|
|||
|
|
"""自动发现并导入 integrations/ 目录下所有厂商集成子包。
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
成功导入的子包完整模块名列表(如
|
|||
|
|
``["yuxi.external_systems.integrations.dynamics365"]``)。
|
|||
|
|
返回 list[str] 而非 None,便于启动日志记录与单元测试断言已加载的集成包。
|
|||
|
|
"""
|
|||
|
|
package_path = Path(__file__).parent
|
|||
|
|
package = "yuxi.external_systems.integrations"
|
|||
|
|
|
|||
|
|
imported: list[str] = []
|
|||
|
|
for _, name, ispkg in pkgutil.iter_modules([str(package_path)]):
|
|||
|
|
if not ispkg or name in _BLACKLIST or name.startswith("_"):
|
|||
|
|
continue
|
|||
|
|
module_name = f"{package}.{name}"
|
|||
|
|
try:
|
|||
|
|
importlib.import_module(module_name)
|
|||
|
|
imported.append(module_name)
|
|||
|
|
except ImportError as exc:
|
|||
|
|
logger.warning("集成包 %s 加载失败(缺少可选依赖): %s", name, exc)
|
|||
|
|
return imported
|