ForcePilot/backend/package/yuxi/external_systems/integrations/discovery.py

53 lines
2.1 KiB
Python
Raw Normal View History

"""厂商集成包自动发现。
扫描 ``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