##// END OF EJS Templates
mercurial: don't load C extensions from PyPy...
Gregory Szorc -
r27224:d308a9ca default
parent child Browse files
Show More
@@ -1,106 +1,113 b''
1 1 # __init__.py - Startup and module loading logic for Mercurial.
2 2 #
3 3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
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 from __future__ import absolute_import
9 9
10 10 import imp
11 11 import os
12 12 import sys
13 13
14 14 __all__ = []
15 15
16 16 # Rules for how modules can be loaded. Values are:
17 17 #
18 18 # c - require C extensions
19 19 # allow - allow pure Python implementation when C loading fails
20 20 # py - only load pure Python modules
21 21 modulepolicy = '@MODULELOADPOLICY@'
22 22
23 23 # By default, require the C extensions for performance reasons.
24 24 if modulepolicy == '@' 'MODULELOADPOLICY' '@':
25 25 modulepolicy = 'c'
26 26
27 # PyPy doesn't load C extensions.
28 #
29 # The canonical way to do this is to test platform.python_implementation().
30 # But we don't import platform and don't bloat for it here.
31 if '__pypy__' in sys.builtin_module_names:
32 modulepolicy = 'py'
33
27 34 # Environment variable can always force settings.
28 35 modulepolicy = os.environ.get('HGMODULEPOLICY', modulepolicy)
29 36
30 37 # Modules that have both Python and C implementations. See also the
31 38 # set of .py files under mercurial/pure/.
32 39 _dualmodules = set([
33 40 'mercurial.base85',
34 41 'mercurial.bdiff',
35 42 'mercurial.diffhelpers',
36 43 'mercurial.mpatch',
37 44 'mercurial.osutil',
38 45 'mercurial.parsers',
39 46 ])
40 47
41 48 class hgimporter(object):
42 49 """Object that conforms to import hook interface defined in PEP-302."""
43 50 def find_module(self, name, path=None):
44 51 # We only care about modules that have both C and pure implementations.
45 52 if name in _dualmodules:
46 53 return self
47 54 return None
48 55
49 56 def load_module(self, name):
50 57 mod = sys.modules.get(name, None)
51 58 if mod:
52 59 return mod
53 60
54 61 mercurial = sys.modules['mercurial']
55 62
56 63 # Unlike the default importer which searches special locations and
57 64 # sys.path, we only look in the directory where "mercurial" was
58 65 # imported from.
59 66
60 67 # imp.find_module doesn't support submodules (modules with ".").
61 68 # Instead you have to pass the parent package's __path__ attribute
62 69 # as the path argument.
63 70 stem = name.split('.')[-1]
64 71
65 72 try:
66 73 if modulepolicy == 'py':
67 74 raise ImportError()
68 75
69 76 modinfo = imp.find_module(stem, mercurial.__path__)
70 77
71 78 # The Mercurial installer used to copy files from
72 79 # mercurial/pure/*.py to mercurial/*.py. Therefore, it's possible
73 80 # for some installations to have .py files under mercurial/*.
74 81 # Loading Python modules when we expected C versions could result
75 82 # in a) poor performance b) loading a version from a previous
76 83 # Mercurial version, potentially leading to incompatibility. Either
77 84 # scenario is bad. So we verify that modules loaded from
78 85 # mercurial/* are C extensions. If the current policy allows the
79 86 # loading of .py modules, the module will be re-imported from
80 87 # mercurial/pure/* below.
81 88 if modinfo[2][2] != imp.C_EXTENSION:
82 89 raise ImportError('.py version of %s found where C '
83 90 'version should exist' % name)
84 91
85 92 except ImportError:
86 93 if modulepolicy == 'c':
87 94 raise
88 95
89 96 # Could not load the C extension and pure Python is allowed. So
90 97 # try to load them.
91 98 from . import pure
92 99 modinfo = imp.find_module(stem, pure.__path__)
93 100 if not modinfo:
94 101 raise ImportError('could not find mercurial module %s' %
95 102 name)
96 103
97 104 mod = imp.load_module(name, *modinfo)
98 105 sys.modules[name] = mod
99 106 return mod
100 107
101 108 # We automagically register our custom importer as a side-effect of loading.
102 109 # This is necessary to ensure that any entry points are able to import
103 110 # mercurial.* modules without having to perform this registration themselves.
104 111 if not any(isinstance(x, hgimporter) for x in sys.meta_path):
105 112 # meta_path is used before any implicit finders and before sys.path.
106 113 sys.meta_path.insert(0, hgimporter())
General Comments 0
You need to be logged in to leave comments. Login now