##// END OF EJS Templates
demandimportpy3: update to pass import checker
Augie Fackler -
r33899:3595e4e0 default
parent child Browse files
Show More
@@ -1,110 +1,109
1 1 # demandimportpy3 - global demand-loading of modules for Mercurial
2 2 #
3 3 # Copyright 2017 Facebook Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 """Lazy loading for Python 3.6 and above.
9 9
10 10 This uses the new importlib finder/loader functionality available in Python 3.5
11 11 and up. The code reuses most of the mechanics implemented inside importlib.util,
12 12 but with a few additions:
13 13
14 14 * Allow excluding certain modules from lazy imports.
15 15 * Expose an interface that's substantially the same as demandimport for
16 16 Python 2.
17 17
18 18 This also has some limitations compared to the Python 2 implementation:
19 19
20 20 * Much of the logic is per-package, not per-module, so any packages loaded
21 21 before demandimport is enabled will not be lazily imported in the future. In
22 22 practice, we only expect builtins to be loaded before demandimport is
23 23 enabled.
24 24 """
25 25
26 26 # This line is unnecessary, but it satisfies test-check-py3-compat.t.
27 27 from __future__ import absolute_import
28 28
29 29 import contextlib
30 import sys
31
32 30 import importlib.abc
33 31 import importlib.machinery
34 32 import importlib.util
33 import sys
35 34
36 35 _deactivated = False
37 36
38 37 class _lazyloaderex(importlib.util.LazyLoader):
39 38 """This is a LazyLoader except it also follows the _deactivated global and
40 39 the ignore list.
41 40 """
42 41 def exec_module(self, module):
43 42 """Make the module load lazily."""
44 43 if _deactivated or module.__name__ in ignore:
45 44 self.loader.exec_module(module)
46 45 else:
47 46 super().exec_module(module)
48 47
49 48 # This is 3.6+ because with Python 3.5 it isn't possible to lazily load
50 49 # extensions. See the discussion in https://python.org/sf/26186 for more.
51 50 _extensions_loader = _lazyloaderex.factory(
52 51 importlib.machinery.ExtensionFileLoader)
53 52 _bytecode_loader = _lazyloaderex.factory(
54 53 importlib.machinery.SourcelessFileLoader)
55 54 _source_loader = _lazyloaderex.factory(importlib.machinery.SourceFileLoader)
56 55
57 56 def _makefinder(path):
58 57 return importlib.machinery.FileFinder(
59 58 path,
60 59 # This is the order in which loaders are passed in in core Python.
61 60 (_extensions_loader, importlib.machinery.EXTENSION_SUFFIXES),
62 61 (_source_loader, importlib.machinery.SOURCE_SUFFIXES),
63 62 (_bytecode_loader, importlib.machinery.BYTECODE_SUFFIXES),
64 63 )
65 64
66 65 ignore = []
67 66
68 67 def init(ignorelist):
69 68 global ignore
70 69 ignore = ignorelist
71 70
72 71 def isenabled():
73 72 return _makefinder in sys.path_hooks and not _deactivated
74 73
75 74 def disable():
76 75 try:
77 76 while True:
78 77 sys.path_hooks.remove(_makefinder)
79 78 except ValueError:
80 79 pass
81 80
82 81 def enable():
83 82 sys.path_hooks.insert(0, _makefinder)
84 83
85 84 @contextlib.contextmanager
86 85 def deactivated():
87 86 # This implementation is a bit different from Python 2's. Python 3
88 87 # maintains a per-package finder cache in sys.path_importer_cache (see
89 88 # PEP 302). This means that we can't just call disable + enable.
90 89 # If we do that, in situations like:
91 90 #
92 91 # demandimport.enable()
93 92 # ...
94 93 # from foo.bar import mod1
95 94 # with demandimport.deactivated():
96 95 # from foo.bar import mod2
97 96 #
98 97 # mod2 will be imported lazily. (The converse also holds -- whatever finder
99 98 # first gets cached will be used.)
100 99 #
101 100 # Instead, have a global flag the LazyLoader can use.
102 101 global _deactivated
103 102 demandenabled = isenabled()
104 103 if demandenabled:
105 104 _deactivated = True
106 105 try:
107 106 yield
108 107 finally:
109 108 if demandenabled:
110 109 _deactivated = False
General Comments 0
You need to be logged in to leave comments. Login now