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)