27 # run without recompiling the C extensions. This will be overridden by |
27 # run without recompiling the C extensions. This will be overridden by |
28 # __modulepolicy__ generated by setup.py. |
28 # __modulepolicy__ generated by setup.py. |
29 policy = b'allow' |
29 policy = b'allow' |
30 _packageprefs = { |
30 _packageprefs = { |
31 # policy: (versioned package, pure package) |
31 # policy: (versioned package, pure package) |
32 b'c': (r'cext', None), |
32 b'c': ('cext', None), |
33 b'allow': (r'cext', r'pure'), |
33 b'allow': ('cext', 'pure'), |
34 b'cffi': (r'cffi', None), |
34 b'cffi': ('cffi', None), |
35 b'cffi-allow': (r'cffi', r'pure'), |
35 b'cffi-allow': ('cffi', 'pure'), |
36 b'py': (None, r'pure'), |
36 b'py': (None, 'pure'), |
37 # For now, rust policies impact importrust only |
37 # For now, rust policies impact importrust only |
38 b'rust+c': (r'cext', None), |
38 b'rust+c': ('cext', None), |
39 b'rust+c-allow': (r'cext', r'pure'), |
39 b'rust+c-allow': ('cext', 'pure'), |
40 } |
40 } |
41 |
41 |
42 try: |
42 try: |
43 from . import __modulepolicy__ |
43 from . import __modulepolicy__ |
44 |
44 |
48 |
48 |
49 # PyPy doesn't load C extensions. |
49 # PyPy doesn't load C extensions. |
50 # |
50 # |
51 # The canonical way to do this is to test platform.python_implementation(). |
51 # The canonical way to do this is to test platform.python_implementation(). |
52 # But we don't import platform and don't bloat for it here. |
52 # But we don't import platform and don't bloat for it here. |
53 if r'__pypy__' in sys.builtin_module_names: |
53 if '__pypy__' in sys.builtin_module_names: |
54 policy = b'cffi' |
54 policy = b'cffi' |
55 |
55 |
56 # Environment variable can always force settings. |
56 # Environment variable can always force settings. |
57 if sys.version_info[0] >= 3: |
57 if sys.version_info[0] >= 3: |
58 if r'HGMODULEPOLICY' in os.environ: |
58 if 'HGMODULEPOLICY' in os.environ: |
59 policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8') |
59 policy = os.environ['HGMODULEPOLICY'].encode('utf-8') |
60 else: |
60 else: |
61 policy = os.environ.get(r'HGMODULEPOLICY', policy) |
61 policy = os.environ.get('HGMODULEPOLICY', policy) |
62 |
62 |
63 |
63 |
64 def _importfrom(pkgname, modname): |
64 def _importfrom(pkgname, modname): |
65 # from .<pkgname> import <modname> (where . is looked through this module) |
65 # from .<pkgname> import <modname> (where . is looked through this module) |
66 fakelocals = {} |
66 fakelocals = {} |
67 pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1) |
67 pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1) |
68 try: |
68 try: |
69 fakelocals[modname] = mod = getattr(pkg, modname) |
69 fakelocals[modname] = mod = getattr(pkg, modname) |
70 except AttributeError: |
70 except AttributeError: |
71 raise ImportError(r'cannot import name %s' % modname) |
71 raise ImportError('cannot import name %s' % modname) |
72 # force import; fakelocals[modname] may be replaced with the real module |
72 # force import; fakelocals[modname] may be replaced with the real module |
73 getattr(mod, '__doc__', None) |
73 getattr(mod, '__doc__', None) |
74 return fakelocals[modname] |
74 return fakelocals[modname] |
75 |
75 |
76 |
76 |
77 # keep in sync with "version" in C modules |
77 # keep in sync with "version" in C modules |
78 _cextversions = { |
78 _cextversions = { |
79 (r'cext', r'base85'): 1, |
79 ('cext', 'base85'): 1, |
80 (r'cext', r'bdiff'): 3, |
80 ('cext', 'bdiff'): 3, |
81 (r'cext', r'mpatch'): 1, |
81 ('cext', 'mpatch'): 1, |
82 (r'cext', r'osutil'): 4, |
82 ('cext', 'osutil'): 4, |
83 (r'cext', r'parsers'): 13, |
83 ('cext', 'parsers'): 13, |
84 } |
84 } |
85 |
85 |
86 # map import request to other package or module |
86 # map import request to other package or module |
87 _modredirects = { |
87 _modredirects = { |
88 (r'cext', r'charencode'): (r'cext', r'parsers'), |
88 ('cext', 'charencode'): ('cext', 'parsers'), |
89 (r'cffi', r'base85'): (r'pure', r'base85'), |
89 ('cffi', 'base85'): ('pure', 'base85'), |
90 (r'cffi', r'charencode'): (r'pure', r'charencode'), |
90 ('cffi', 'charencode'): ('pure', 'charencode'), |
91 (r'cffi', r'parsers'): (r'pure', r'parsers'), |
91 ('cffi', 'parsers'): ('pure', 'parsers'), |
92 } |
92 } |
93 |
93 |
94 |
94 |
95 def _checkmod(pkgname, modname, mod): |
95 def _checkmod(pkgname, modname, mod): |
96 expected = _cextversions.get((pkgname, modname)) |
96 expected = _cextversions.get((pkgname, modname)) |
97 actual = getattr(mod, 'version', None) |
97 actual = getattr(mod, 'version', None) |
98 if actual != expected: |
98 if actual != expected: |
99 raise ImportError( |
99 raise ImportError( |
100 r'cannot import module %s.%s ' |
100 'cannot import module %s.%s ' |
101 r'(expected version: %d, actual: %r)' |
101 '(expected version: %d, actual: %r)' |
102 % (pkgname, modname, expected, actual) |
102 % (pkgname, modname, expected, actual) |
103 ) |
103 ) |
104 |
104 |
105 |
105 |
106 def importmod(modname): |
106 def importmod(modname): |
107 """Import module according to policy and check API version""" |
107 """Import module according to policy and check API version""" |
108 try: |
108 try: |
109 verpkg, purepkg = _packageprefs[policy] |
109 verpkg, purepkg = _packageprefs[policy] |
110 except KeyError: |
110 except KeyError: |
111 raise ImportError(r'invalid HGMODULEPOLICY %r' % policy) |
111 raise ImportError('invalid HGMODULEPOLICY %r' % policy) |
112 assert verpkg or purepkg |
112 assert verpkg or purepkg |
113 if verpkg: |
113 if verpkg: |
114 pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname)) |
114 pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname)) |
115 try: |
115 try: |
116 mod = _importfrom(pn, mn) |
116 mod = _importfrom(pn, mn) |