##// END OF EJS Templates
policy: extend API version checks for cffi...
Yuya Nishihara -
r32511:2e431fb9 default
parent child Browse files
Show More
@@ -1,106 +1,106
1 # policy.py - module policy logic for Mercurial.
1 # policy.py - module policy logic for Mercurial.
2 #
2 #
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
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.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import os
10 import os
11 import sys
11 import sys
12
12
13 # Rules for how modules can be loaded. Values are:
13 # Rules for how modules can be loaded. Values are:
14 #
14 #
15 # c - require C extensions
15 # c - require C extensions
16 # allow - allow pure Python implementation when C loading fails
16 # allow - allow pure Python implementation when C loading fails
17 # cffi - required cffi versions (implemented within pure module)
17 # cffi - required cffi versions (implemented within pure module)
18 # cffi-allow - allow pure Python implementation if cffi version is missing
18 # cffi-allow - allow pure Python implementation if cffi version is missing
19 # py - only load pure Python modules
19 # py - only load pure Python modules
20 #
20 #
21 # By default, fall back to the pure modules so the in-place build can
21 # By default, fall back to the pure modules so the in-place build can
22 # run without recompiling the C extensions. This will be overridden by
22 # run without recompiling the C extensions. This will be overridden by
23 # __modulepolicy__ generated by setup.py.
23 # __modulepolicy__ generated by setup.py.
24 policy = b'allow'
24 policy = b'allow'
25 policynoc = (b'cffi', b'cffi-allow', b'py')
25 policynoc = (b'cffi', b'cffi-allow', b'py')
26 policynocffi = (b'c', b'py')
26 policynocffi = (b'c', b'py')
27 _packageprefs = {
27 _packageprefs = {
28 # policy: (versioned package, pure package)
28 # policy: (versioned package, pure package)
29 b'c': (r'cext', None),
29 b'c': (r'cext', None),
30 b'allow': (r'cext', r'pure'),
30 b'allow': (r'cext', r'pure'),
31 b'cffi': (None, r'pure'), # TODO: (r'cffi', None)
31 b'cffi': (None, r'pure'), # TODO: (r'cffi', None)
32 b'cffi-allow': (None, r'pure'), # TODO: (r'cffi', r'pure')
32 b'cffi-allow': (None, r'pure'), # TODO: (r'cffi', r'pure')
33 b'py': (None, r'pure'),
33 b'py': (None, r'pure'),
34 }
34 }
35
35
36 try:
36 try:
37 from . import __modulepolicy__
37 from . import __modulepolicy__
38 policy = __modulepolicy__.modulepolicy
38 policy = __modulepolicy__.modulepolicy
39 except ImportError:
39 except ImportError:
40 pass
40 pass
41
41
42 # PyPy doesn't load C extensions.
42 # PyPy doesn't load C extensions.
43 #
43 #
44 # The canonical way to do this is to test platform.python_implementation().
44 # The canonical way to do this is to test platform.python_implementation().
45 # But we don't import platform and don't bloat for it here.
45 # But we don't import platform and don't bloat for it here.
46 if r'__pypy__' in sys.builtin_module_names:
46 if r'__pypy__' in sys.builtin_module_names:
47 policy = b'cffi'
47 policy = b'cffi'
48
48
49 # Our C extensions aren't yet compatible with Python 3. So use pure Python
49 # Our C extensions aren't yet compatible with Python 3. So use pure Python
50 # on Python 3 for now.
50 # on Python 3 for now.
51 if sys.version_info[0] >= 3:
51 if sys.version_info[0] >= 3:
52 policy = b'py'
52 policy = b'py'
53
53
54 # Environment variable can always force settings.
54 # Environment variable can always force settings.
55 if sys.version_info[0] >= 3:
55 if sys.version_info[0] >= 3:
56 if r'HGMODULEPOLICY' in os.environ:
56 if r'HGMODULEPOLICY' in os.environ:
57 policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8')
57 policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8')
58 else:
58 else:
59 policy = os.environ.get(r'HGMODULEPOLICY', policy)
59 policy = os.environ.get(r'HGMODULEPOLICY', policy)
60
60
61 def _importfrom(pkgname, modname):
61 def _importfrom(pkgname, modname):
62 # from .<pkgname> import <modname> (where . is looked through this module)
62 # from .<pkgname> import <modname> (where . is looked through this module)
63 fakelocals = {}
63 fakelocals = {}
64 pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
64 pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
65 try:
65 try:
66 fakelocals[modname] = mod = getattr(pkg, modname)
66 fakelocals[modname] = mod = getattr(pkg, modname)
67 except AttributeError:
67 except AttributeError:
68 raise ImportError(r'cannot import name %s' % modname)
68 raise ImportError(r'cannot import name %s' % modname)
69 # force import; fakelocals[modname] may be replaced with the real module
69 # force import; fakelocals[modname] may be replaced with the real module
70 getattr(mod, r'__doc__', None)
70 getattr(mod, r'__doc__', None)
71 return fakelocals[modname]
71 return fakelocals[modname]
72
72
73 # keep in sync with "version" in C modules
73 # keep in sync with "version" in C modules
74 _cextversions = {
74 _cextversions = {
75 r'base85': 1,
75 (r'cext', r'base85'): 1,
76 r'bdiff': 1,
76 (r'cext', r'bdiff'): 1,
77 r'diffhelpers': 1,
77 (r'cext', r'diffhelpers'): 1,
78 r'mpatch': 1,
78 (r'cext', r'mpatch'): 1,
79 r'osutil': 1,
79 (r'cext', r'osutil'): 1,
80 r'parsers': 1,
80 (r'cext', r'parsers'): 1,
81 }
81 }
82
82
83 def _checkmod(pkgname, modname, mod):
83 def _checkmod(pkgname, modname, mod):
84 expected = _cextversions.get(modname)
84 expected = _cextversions.get((pkgname, modname))
85 actual = getattr(mod, r'version', None)
85 actual = getattr(mod, r'version', None)
86 if actual != expected:
86 if actual != expected:
87 raise ImportError(r'cannot import module %s.%s '
87 raise ImportError(r'cannot import module %s.%s '
88 r'(expected version: %d, actual: %r)'
88 r'(expected version: %d, actual: %r)'
89 % (pkgname, modname, expected, actual))
89 % (pkgname, modname, expected, actual))
90
90
91 def importmod(modname):
91 def importmod(modname):
92 """Import module according to policy and check API version"""
92 """Import module according to policy and check API version"""
93 try:
93 try:
94 verpkg, purepkg = _packageprefs[policy]
94 verpkg, purepkg = _packageprefs[policy]
95 except KeyError:
95 except KeyError:
96 raise ImportError(r'invalid HGMODULEPOLICY %r' % policy)
96 raise ImportError(r'invalid HGMODULEPOLICY %r' % policy)
97 assert verpkg or purepkg
97 assert verpkg or purepkg
98 if verpkg:
98 if verpkg:
99 try:
99 try:
100 mod = _importfrom(verpkg, modname)
100 mod = _importfrom(verpkg, modname)
101 _checkmod(verpkg, modname, mod)
101 _checkmod(verpkg, modname, mod)
102 return mod
102 return mod
103 except ImportError:
103 except ImportError:
104 if not purepkg:
104 if not purepkg:
105 raise
105 raise
106 return _importfrom(purepkg, modname)
106 return _importfrom(purepkg, modname)
General Comments 0
You need to be logged in to leave comments. Login now