34 |
34 |
35 from . import tracing |
35 from . import tracing |
36 |
36 |
37 _deactivated = False |
37 _deactivated = False |
38 |
38 |
|
39 |
39 class _lazyloaderex(importlib.util.LazyLoader): |
40 class _lazyloaderex(importlib.util.LazyLoader): |
40 """This is a LazyLoader except it also follows the _deactivated global and |
41 """This is a LazyLoader except it also follows the _deactivated global and |
41 the ignore list. |
42 the ignore list. |
42 """ |
43 """ |
|
44 |
43 def exec_module(self, module): |
45 def exec_module(self, module): |
44 """Make the module load lazily.""" |
46 """Make the module load lazily.""" |
45 with tracing.log('demandimport %s', module): |
47 with tracing.log('demandimport %s', module): |
46 if _deactivated or module.__name__ in ignores: |
48 if _deactivated or module.__name__ in ignores: |
47 self.loader.exec_module(module) |
49 self.loader.exec_module(module) |
48 else: |
50 else: |
49 super().exec_module(module) |
51 super().exec_module(module) |
50 |
52 |
|
53 |
51 # This is 3.6+ because with Python 3.5 it isn't possible to lazily load |
54 # This is 3.6+ because with Python 3.5 it isn't possible to lazily load |
52 # extensions. See the discussion in https://bugs.python.org/issue26186 for more. |
55 # extensions. See the discussion in https://bugs.python.org/issue26186 for more. |
53 _extensions_loader = _lazyloaderex.factory( |
56 _extensions_loader = _lazyloaderex.factory( |
54 importlib.machinery.ExtensionFileLoader) |
57 importlib.machinery.ExtensionFileLoader |
|
58 ) |
55 _bytecode_loader = _lazyloaderex.factory( |
59 _bytecode_loader = _lazyloaderex.factory( |
56 importlib.machinery.SourcelessFileLoader) |
60 importlib.machinery.SourcelessFileLoader |
|
61 ) |
57 _source_loader = _lazyloaderex.factory(importlib.machinery.SourceFileLoader) |
62 _source_loader = _lazyloaderex.factory(importlib.machinery.SourceFileLoader) |
|
63 |
58 |
64 |
59 def _makefinder(path): |
65 def _makefinder(path): |
60 return importlib.machinery.FileFinder( |
66 return importlib.machinery.FileFinder( |
61 path, |
67 path, |
62 # This is the order in which loaders are passed in in core Python. |
68 # This is the order in which loaders are passed in in core Python. |
63 (_extensions_loader, importlib.machinery.EXTENSION_SUFFIXES), |
69 (_extensions_loader, importlib.machinery.EXTENSION_SUFFIXES), |
64 (_source_loader, importlib.machinery.SOURCE_SUFFIXES), |
70 (_source_loader, importlib.machinery.SOURCE_SUFFIXES), |
65 (_bytecode_loader, importlib.machinery.BYTECODE_SUFFIXES), |
71 (_bytecode_loader, importlib.machinery.BYTECODE_SUFFIXES), |
66 ) |
72 ) |
67 |
73 |
|
74 |
68 ignores = set() |
75 ignores = set() |
|
76 |
69 |
77 |
70 def init(ignoreset): |
78 def init(ignoreset): |
71 global ignores |
79 global ignores |
72 ignores = ignoreset |
80 ignores = ignoreset |
73 |
81 |
|
82 |
74 def isenabled(): |
83 def isenabled(): |
75 return _makefinder in sys.path_hooks and not _deactivated |
84 return _makefinder in sys.path_hooks and not _deactivated |
|
85 |
76 |
86 |
77 def disable(): |
87 def disable(): |
78 try: |
88 try: |
79 while True: |
89 while True: |
80 sys.path_hooks.remove(_makefinder) |
90 sys.path_hooks.remove(_makefinder) |
81 except ValueError: |
91 except ValueError: |
82 pass |
92 pass |
83 |
93 |
|
94 |
84 def enable(): |
95 def enable(): |
85 sys.path_hooks.insert(0, _makefinder) |
96 sys.path_hooks.insert(0, _makefinder) |
|
97 |
86 |
98 |
87 @contextlib.contextmanager |
99 @contextlib.contextmanager |
88 def deactivated(): |
100 def deactivated(): |
89 # This implementation is a bit different from Python 2's. Python 3 |
101 # This implementation is a bit different from Python 2's. Python 3 |
90 # maintains a per-package finder cache in sys.path_importer_cache (see |
102 # maintains a per-package finder cache in sys.path_importer_cache (see |