|
1 | 1 | import collections.abc |
2 | 2 |
|
3 | | -# noinspection PyUnresolvedReferences |
4 | 3 | from types import ModuleType |
5 | 4 |
|
6 | 5 |
|
7 | 6 | def lazy_import( |
8 | | - bare_import: collections.abc.Container | None = None, |
9 | | - sub_import: collections.abc.Mapping[str, str | None] | None = None, |
| 7 | + *imports: str, |
10 | 8 | aliases: collections.abc.Mapping[str, str] | None = None, |
11 | | -): |
12 | | - if bare_import is None: |
13 | | - bare_import = set() |
14 | | - if sub_import is None: |
15 | | - sub_import = {} |
| 9 | + sub_import: collections.abc.Mapping[str, str] | None = None, |
| 10 | + **kw_sub_import: str, |
| 11 | +) -> collections.abc.Callable[[str], ModuleType]: |
| 12 | + """ |
| 13 | + Lazily import modules. |
| 14 | +
|
| 15 | + >>> lazy_import('package', 'package_2', 'package_3', ...) |
| 16 | + >>> lazy_import('package.submodule') # fail ATM |
| 17 | + >>> lazy_import(submodule='package') |
| 18 | + >>> lazy_import(sub_import={'submodule':'package'}) |
| 19 | + >>> lazy_import('module', aliases={'md': 'module'}) |
| 20 | + >>> lazy_import(aliases={'smd': 'submodule'}, submodule='package') |
| 21 | + >>> lazy_import( |
| 22 | + 'module', |
| 23 | + aliases={'md': 'module', 'smd': 'submodule'}, |
| 24 | + submodule='package', |
| 25 | + ) |
| 26 | + >>> lazy_import( |
| 27 | + 'module', |
| 28 | + aliases={'md': 'module', 'smd': 'submodule', 'smd2': 'submodule2'}, |
| 29 | + submodule='package', |
| 30 | + sub_import={'submodule2':'package'} |
| 31 | + ) |
| 32 | +
|
| 33 | + :param imports: Any number of module names to import. |
| 34 | + :param aliases: A mapping of alias names to module names. |
| 35 | + :param sub_import: A mapping of module names to package names. |
| 36 | + :param kw_sub_import: Keyword arguments of module names to package names. |
| 37 | + :return: A function that returns the imported modules. |
| 38 | + """ |
| 39 | + imports = set(imports) |
16 | 40 | if aliases is None: |
17 | 41 | aliases = {} |
| 42 | + if sub_import is None: |
| 43 | + sub_import = {} |
| 44 | + sub_import = sub_import | kw_sub_import |
18 | 45 |
|
19 | 46 | import functools |
20 | 47 | import importlib |
21 | 48 |
|
22 | 49 | @functools.cache |
23 | | - def getattr_(name: str): |
| 50 | + def getattr_(name: str) -> ModuleType: |
24 | 51 | name = aliases.get(name, name) |
25 | 52 |
|
26 | | - if name not in bare_import and name not in sub_import: |
| 53 | + if name not in imports and name not in sub_import: |
27 | 54 | raise AttributeError( |
28 | 55 | f'Module has no attribute {name!r}' |
29 | 56 | ) from None |
30 | 57 |
|
31 | | - if name in bare_import: |
| 58 | + if name in imports: |
32 | 59 | try: |
33 | 60 | return importlib.import_module(name) |
34 | 61 | except ModuleNotFoundError as e: |
|
0 commit comments