Mercurial > hg
comparison mercurial/policy.py @ 32366:8e0327dae3f4
policy: add helper to import cext/pure module
These functions are sysstr API since __import__() and getattr() hate byte
strings on Python 3.
There's a minor BC, which is ImportError will be raised if invalid
HGMODULEPOLICY is specified. I think this is more desired behavior.
We're planning to add strict checking for C API compatibility. This patch
includes the stub for it.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Fri, 12 Aug 2016 11:30:17 +0900 |
parents | a04f5c651e52 |
children | 28b773aa3ff2 |
comparison
equal
deleted
inserted
replaced
32365:b2b5605285ec | 32366:8e0327dae3f4 |
---|---|
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 = { | |
28 # policy: (versioned package, pure package) | |
29 b'c': (r'cext', None), | |
30 b'allow': (r'cext', r'pure'), | |
31 b'cffi': (None, r'pure'), # TODO: (r'cffi', None) | |
32 b'cffi-allow': (None, r'pure'), # TODO: (r'cffi', r'pure') | |
33 b'py': (None, r'pure'), | |
34 } | |
27 | 35 |
28 try: | 36 try: |
29 from . import __modulepolicy__ | 37 from . import __modulepolicy__ |
30 policy = __modulepolicy__.modulepolicy | 38 policy = __modulepolicy__.modulepolicy |
31 except ImportError: | 39 except ImportError: |
47 if sys.version_info[0] >= 3: | 55 if sys.version_info[0] >= 3: |
48 if r'HGMODULEPOLICY' in os.environ: | 56 if r'HGMODULEPOLICY' in os.environ: |
49 policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8') | 57 policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8') |
50 else: | 58 else: |
51 policy = os.environ.get(r'HGMODULEPOLICY', policy) | 59 policy = os.environ.get(r'HGMODULEPOLICY', policy) |
60 | |
61 def _importfrom(pkgname, modname): | |
62 # from .<pkgname> import <modname> (where . is looked through this module) | |
63 fakelocals = {} | |
64 pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1) | |
65 try: | |
66 fakelocals[modname] = mod = getattr(pkg, modname) | |
67 except AttributeError: | |
68 raise ImportError(r'cannot import name %s' % modname) | |
69 # force import; fakelocals[modname] may be replaced with the real module | |
70 getattr(mod, r'__doc__', None) | |
71 return fakelocals[modname] | |
72 | |
73 def _checkmod(pkgname, modname, mod): | |
74 expected = 1 # TODO: maybe defined in table? | |
75 actual = getattr(mod, r'version', None) | |
76 if actual != expected: | |
77 raise ImportError(r'cannot import module %s.%s ' | |
78 r'(expected version: %d, actual: %r)' | |
79 % (pkgname, modname, expected, actual)) | |
80 | |
81 def importmod(modname): | |
82 """Import module according to policy and check API version""" | |
83 try: | |
84 verpkg, purepkg = _packageprefs[policy] | |
85 except KeyError: | |
86 raise ImportError(r'invalid HGMODULEPOLICY %r' % policy) | |
87 assert verpkg or purepkg | |
88 if verpkg: | |
89 try: | |
90 mod = _importfrom(verpkg, modname) | |
91 _checkmod(verpkg, modname, mod) | |
92 return mod | |
93 except ImportError: | |
94 if not purepkg: | |
95 raise | |
96 return _importfrom(purepkg, modname) |