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