##// END OF EJS Templates
policy: drop custom importer for pure modules
Yuya Nishihara -
r32373:57008258 default
parent child Browse files
Show More
@@ -7,120 +7,16 b''
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import imp
11 import os
12 import sys
10 import sys
13 import zipimport
14
15 from . import (
16 policy
17 )
18
11
19 __all__ = []
12 __all__ = []
20
13
21 modulepolicy = policy.policy
22
23 # Modules that have both Python and C implementations. See also the
24 # set of .py files under mercurial/pure/.
25 _dualmodules = {
26 }
27
28 class hgimporter(object):
29 """Object that conforms to import hook interface defined in PEP-302."""
30 def find_module(self, name, path=None):
31 # We only care about modules that have both C and pure implementations.
32 if name in _dualmodules:
33 return self
34 return None
35
36 def load_module(self, name):
37 mod = sys.modules.get(name, None)
38 if mod:
39 return mod
40
41 mercurial = sys.modules['mercurial']
42
43 # The zip importer behaves sufficiently differently from the default
44 # importer to warrant its own code path.
45 loader = getattr(mercurial, '__loader__', None)
46 if isinstance(loader, zipimport.zipimporter):
47 def ziploader(*paths):
48 """Obtain a zipimporter for a directory under the main zip."""
49 path = os.path.join(loader.archive, *paths)
50 zl = sys.path_importer_cache.get(path)
51 if not zl:
52 zl = zipimport.zipimporter(path)
53 return zl
54
55 try:
56 if modulepolicy in policy.policynoc:
57 raise ImportError()
58
59 zl = ziploader('mercurial')
60 mod = zl.load_module(name)
61 # Unlike imp, ziploader doesn't expose module metadata that
62 # indicates the type of module. So just assume what we found
63 # is OK (even though it could be a pure Python module).
64 except ImportError:
65 if modulepolicy == b'c':
66 raise
67 zl = ziploader('mercurial', 'pure')
68 mod = zl.load_module(name)
69
70 sys.modules[name] = mod
71 return mod
72
73 # Unlike the default importer which searches special locations and
74 # sys.path, we only look in the directory where "mercurial" was
75 # imported from.
76
77 # imp.find_module doesn't support submodules (modules with ".").
78 # Instead you have to pass the parent package's __path__ attribute
79 # as the path argument.
80 stem = name.split('.')[-1]
81
82 try:
83 if modulepolicy in policy.policynoc:
84 raise ImportError()
85
86 modinfo = imp.find_module(stem, mercurial.__path__)
87
88 # The Mercurial installer used to copy files from
89 # mercurial/pure/*.py to mercurial/*.py. Therefore, it's possible
90 # for some installations to have .py files under mercurial/*.
91 # Loading Python modules when we expected C versions could result
92 # in a) poor performance b) loading a version from a previous
93 # Mercurial version, potentially leading to incompatibility. Either
94 # scenario is bad. So we verify that modules loaded from
95 # mercurial/* are C extensions. If the current policy allows the
96 # loading of .py modules, the module will be re-imported from
97 # mercurial/pure/* below.
98 if modinfo[2][2] != imp.C_EXTENSION:
99 raise ImportError('.py version of %s found where C '
100 'version should exist' % name)
101
102 except ImportError:
103 if modulepolicy == b'c':
104 raise
105
106 # Could not load the C extension and pure Python is allowed. So
107 # try to load them.
108 from . import pure
109 modinfo = imp.find_module(stem, pure.__path__)
110 if not modinfo:
111 raise ImportError('could not find mercurial module %s' %
112 name)
113
114 mod = imp.load_module(name, *modinfo)
115 sys.modules[name] = mod
116 return mod
117
118 # Python 3 uses a custom module loader that transforms source code between
14 # Python 3 uses a custom module loader that transforms source code between
119 # source file reading and compilation. This is done by registering a custom
15 # source file reading and compilation. This is done by registering a custom
120 # finder that changes the spec for Mercurial modules to use a custom loader.
16 # finder that changes the spec for Mercurial modules to use a custom loader.
121 if sys.version_info[0] >= 3:
17 if sys.version_info[0] >= 3:
122 from . import pure
123 import importlib
18 import importlib
19 import importlib.abc
124 import io
20 import io
125 import token
21 import token
126 import tokenize
22 import tokenize
@@ -135,14 +31,6 b' if sys.version_info[0] >= 3:'
135 if fullname.startswith('mercurial.zstd'):
31 if fullname.startswith('mercurial.zstd'):
136 return None
32 return None
137
33
138 # This assumes Python 3 doesn't support loading C modules.
139 if fullname in _dualmodules:
140 stem = fullname.split('.')[-1]
141 fullname = 'mercurial.pure.%s' % stem
142 target = pure
143 assert len(path) == 1
144 path = [os.path.join(path[0], 'pure')]
145
146 # Try to find the module using other registered finders.
34 # Try to find the module using other registered finders.
147 spec = None
35 spec = None
148 for finder in sys.meta_path:
36 for finder in sys.meta_path:
@@ -159,10 +47,6 b' if sys.version_info[0] >= 3:'
159 if not spec:
47 if not spec:
160 return None
48 return None
161
49
162 if (fullname.startswith('mercurial.pure.')
163 and fullname.replace('.pure.', '.') in _dualmodules):
164 spec.name = spec.name.replace('.pure.', '.')
165
166 # TODO need to support loaders from alternate specs, like zip
50 # TODO need to support loaders from alternate specs, like zip
167 # loaders.
51 # loaders.
168 spec.loader = hgloader(spec.name, spec.origin)
52 spec.loader = hgloader(spec.name, spec.origin)
@@ -386,13 +270,10 b' if sys.version_info[0] >= 3:'
386 # implemented them because they are very ugly.
270 # implemented them because they are very ugly.
387 return super(hgloader, self).source_to_code(data, path)
271 return super(hgloader, self).source_to_code(data, path)
388
272
389 # We automagically register our custom importer as a side-effect of loading.
273 # We automagically register our custom importer as a side-effect of
390 # This is necessary to ensure that any entry points are able to import
274 # loading. This is necessary to ensure that any entry points are able
391 # mercurial.* modules without having to perform this registration themselves.
275 # to import mercurial.* modules without having to perform this
392 if sys.version_info[0] >= 3:
276 # registration themselves.
393 _importercls = hgpathentryfinder
277 if not any(isinstance(x, hgpathentryfinder) for x in sys.meta_path):
394 else:
278 # meta_path is used before any implicit finders and before sys.path.
395 _importercls = hgimporter
279 sys.meta_path.insert(0, hgpathentryfinder())
396 if not any(isinstance(x, _importercls) for x in sys.meta_path):
397 # meta_path is used before any implicit finders and before sys.path.
398 sys.meta_path.insert(0, _importercls())
General Comments 0
You need to be logged in to leave comments. Login now