Coverage for src/symphra_modules/loader/package.py: 93.55%

1"""包加载器实现."""

2

3 import importlib

4 from pathlib import Path

5

6 from symphra_modules.abc import ModuleInterface

7 from symphra_modules.exceptions import ModuleLoadError

8 from symphra_modules.loader.base import ModuleLoader

9

10

11 class PackageLoader(ModuleLoader):

12 """从包名加载模块."""

13

14 def load(self, source: str) -> dict[str, type[ModuleInterface]]:

15 """从包名加载模块.

16

17 Args:

18 source: 包名（如 "my_package.modules"）

19

20 Returns:

21 模块类字典

22

23 Raises:

24 ModuleLoadError: 包未找到时抛出

25 """

26 try:

27 module = importlib.import_module(source)

28 return self._find_module_classes(module)

29 except ImportError as e:

30 raise ModuleLoadError(f"包未找到: {source}") from e

31

32 def discover(self, source: str) -> list[str]:

33 """发现包中的模块.

34

35 Args:

36 source: 包名

37

38 Returns:

39 模块名称列表

40 """

41 try:

42 package = importlib.import_module(source)

43 package_path = Path(package.__file__).parent if package.__file__ else Path.cwd() / source

44

45 module_names: list[str] = []

46

47 # 扫描包内的模块

48 for item in package_path.iterdir():

49 if item.is_file() and item.suffix == ".py" and not item.name.startswith("_"):

50 module_names.append(item.stem)

51 elif item.is_dir() and (item / "__init__.py").exists(): 51 ↛ 52line 51 didn't jump to line 52 because the condition on line 51 was never true

52 module_names.append(item.name)

53

54 return module_names

55

56 except (ImportError, AttributeError):

57 return []