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 |
|
273 | # We automagically register our custom importer as a side-effect of | |
390 |
# This is necessary to ensure that any entry points are able |
|
274 | # loading. This is necessary to ensure that any entry points are able | |
391 |
# mercurial.* modules without having to perform this |
|
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