Coverage for src/lazy_imports_lite/_hooks.py: 100%
66 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-11 15:02 +0100
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-11 15:02 +0100
1import importlib
2from collections import defaultdict
5class LazyObject:
6 __slots__ = ("_lazy_value",)
9class LazyImportError(BaseException):
10 def __init__(self, module, package):
11 self.module = module
12 self.package = package
14 def __str__(self):
15 if self.package is None:
16 return f"Deferred importing of module '{self.module}' caused an error"
17 else:
18 return f"Deferred importing of module '{self.module}' in '{self.package}' caused an error"
21class ImportFrom(LazyObject):
22 __slots__ = ("package", "module", "name", "_lazy_value")
24 def __init__(self, package, module, name):
25 self.package = package
26 self.module = module
27 self.name = name
29 def __getattr__(self, name):
30 if name == "_lazy_value":
31 module = safe_import(self.module, self.package)
32 try:
33 attr = getattr(module, self.name)
34 except AttributeError:
35 attr = safe_import(self.module + "." + self.name, self.package)
36 self._lazy_value = attr
37 return attr
38 else:
39 assert False
42pending_imports = defaultdict(list)
43imported_modules = set()
46def safe_import(module, package=None):
47 try:
48 return importlib.import_module(module, package)
49 except LazyImportError:
50 raise
51 except:
52 raise LazyImportError(module, package)
55class Import(LazyObject):
56 __slots__ = ("module", "_lazy_value")
58 def __init__(self, module):
59 self.module = module
60 m = self.module.split(".")[0]
62 if m in imported_modules:
63 safe_import(self.module)
64 else:
65 pending_imports[m].append(module)
67 def __getattr__(self, name):
68 if name == "_lazy_value":
69 m = self.module.split(".")[0]
70 for pending in pending_imports[m]:
71 safe_import(pending)
72 result = safe_import(self.module.split(".")[0])
73 imported_modules.add(m)
74 self._lazy_value = result
75 return result
76 else:
77 assert False
80class ImportAs(LazyObject):
81 __slots__ = ("module", "_lazy_value")
83 def __init__(self, module):
84 self.module = module
86 def __getattr__(self, name):
87 if name == "_lazy_value":
88 module = safe_import(self.module)
89 self._lazy_value = module
90 return module
91 else:
92 assert False
95def make_globals(global_provider):
96 def g():
97 return {
98 key: value._lazy_value if isinstance(value, LazyObject) else value
99 for key, value in dict(global_provider()).items()
100 if key not in ("globals", "__lazy_imports_lite__")
101 }
103 return g