Coverage for src / c41811 / config / lazy_import.py: 100%
32 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-06 06:04 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-06 06:04 +0000
1# cython: language_level = 3 # noqa: ERA001
4"""
5懒加载处理
7.. versionadded:: 0.3.0
8"""
10import inspect
11from importlib import import_module
12from typing import TYPE_CHECKING
13from typing import Any
15if TYPE_CHECKING:
16 from collections.abc import Callable
17else:
18 from collections.abc import Callable
21def lazy_import(properties: dict[str, str], /) -> tuple[list[str], Callable[[str], Any]]:
22 """
23 为 `__init__` 文件生成 `__all__` 和 `__getattr__`
25 :param properties: 属性字典 ``dict[属性, 模块]``
26 :type properties: dict[str, str]
28 :return: 返回 ``tuple[__all__, __getattr__]``
29 :rtype: tuple[tuple[str, ...], Callable[[str], Any]]
31 .. versionadded:: 0.3.0
32 """
33 if (caller_module := inspect.getmodule(inspect.stack()[1][0])) is None: # pragma: no cover
34 msg = "Cannot find caller module"
35 raise RuntimeError(msg)
36 caller_package = caller_module.__name__
37 property_list = list(properties.keys())
39 def attr_getter(name: str) -> Any:
40 from .errors import DependencyNotFoundError # noqa: PLC0415
41 from .errors import UnavailableAttribute # noqa: PLC0415
43 try:
44 sub_pkg = properties[name]
45 except KeyError:
46 # noinspection PyShadowingNames
47 msg = f"module '{caller_package}' has no attribute '{name}'"
48 raise AttributeError(msg) from None
49 try:
50 module = import_module(sub_pkg, package=caller_package)
51 except DependencyNotFoundError as err:
52 property_list.remove(name)
53 del properties[name]
54 return UnavailableAttribute(name, err)
55 attr = getattr(module, name)
56 if isinstance(attr, UnavailableAttribute):
57 property_list.remove(name)
58 del properties[name]
59 return attr
61 attr_getter.__name__ = "__getattr__"
62 attr_getter.__qualname__ = f"{caller_package}.__getattr__"
63 attr_getter.__module__ = caller_package
65 return property_list, attr_getter
68__all__ = ("lazy_import",)