Skip to content

Commit 8d83281

Browse files
committed
[break] change api, bare imports are now varargs, sub imports can be kwvarargs
1 parent decd82c commit 8d83281

File tree

3 files changed

+47
-13
lines changed

3 files changed

+47
-13
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ import lazimp
3030
math: lazimp.ModuleType
3131
heavy_module: lazimp.ModuleType
3232

33-
__getattr__ = lazimp.lazy_import({'math'}, {'heavy_module': 'package'})
33+
__getattr__ = lazimp.lazy_import(
34+
'math',
35+
heavy_module='package',
36+
)
3437
```
3538

3639
Now, when you import the package:

examples/basic/package/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@
33
math: lazimp.ModuleType
44
heavy_module: lazimp.ModuleType
55

6-
__getattr__ = lazimp.lazy_import({'math'}, {'heavy_module': 'package'})
6+
# __getattr__ = lazimp.lazy_import('math', 'package.heavy_module')
7+
__getattr__ = lazimp.lazy_import(
8+
'math',
9+
heavy_module='package',
10+
)

src/lazimp/__init__.py

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,61 @@
11
import collections.abc
22

3-
# noinspection PyUnresolvedReferences
43
from types import ModuleType
54

65

76
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,
108
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)
1640
if aliases is None:
1741
aliases = {}
42+
if sub_import is None:
43+
sub_import = {}
44+
sub_import = sub_import | kw_sub_import
1845

1946
import functools
2047
import importlib
2148

2249
@functools.cache
23-
def getattr_(name: str):
50+
def getattr_(name: str) -> ModuleType:
2451
name = aliases.get(name, name)
2552

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:
2754
raise AttributeError(
2855
f'Module has no attribute {name!r}'
2956
) from None
3057

31-
if name in bare_import:
58+
if name in imports:
3259
try:
3360
return importlib.import_module(name)
3461
except ModuleNotFoundError as e:

0 commit comments

Comments
 (0)