From patchwork Sat Aug 13 10:15:25 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [3, of, 5, RFC] policy: add helper to import cpy/pure module selectively From: Yuya Nishihara X-Patchwork-Id: 16270 Message-Id: <8bb0a9223bce791bae9e.1471083325@mimosa> To: mercurial-devel@mercurial-scm.org Date: Sat, 13 Aug 2016 19:15:25 +0900 # HG changeset patch # User Yuya Nishihara # Date 1470969017 -32400 # Fri Aug 12 11:30:17 2016 +0900 # Node ID 8bb0a9223bce791bae9e6a07238d6b9722e5577a # Parent bda4422fc315b54356ba1949e5ba861dd2660e86 policy: add helper to import cpy/pure module selectively Unfortunately, __import__() nor getattr() does not take bytes, and globals() is a dict keyed by unicodes on Python 3. uimportvars() is a unicode API to comply with their requirement. I really hated mixing bytes and unicodes, but bytes version of importvars() would be useless. Nit: KeyError would be raised for invalid HGMODULEPOLICY. What should we do in that case? diff --git a/mercurial/policy.py b/mercurial/policy.py --- a/mercurial/policy.py +++ b/mercurial/policy.py @@ -23,6 +23,14 @@ policy = 'c' policynoc = ('cffi', 'cffi-allow', 'py') policynocffi = ('c', 'py') +_upackagetable = { + 'c': [u'cpy'], + 'allow': [u'cpy', u'pure'], + 'cffi': [u'pure'], # TODO: [u'cffi'] + 'cffi-allow': [u'pure'], # TODO: [u'cffi', u'pure'] + 'py': [u'pure'], +} + try: from . import __modulepolicy__ policy = __modulepolicy__.modulepolicy @@ -43,3 +51,24 @@ if sys.version_info[0] >= 3: # Environment variable can always force settings. policy = os.environ.get('HGMODULEPOLICY', policy) + +def _uexportedvars(mod): + """Build dict of public names to simulate 'from mod import *'""" + modvars = vars(mod) + if u'__all__' in modvars: + allnames = modvars[u'__all__'] + return dict((k, v) for k, v in modvars.items() if k in allnames) + return dict((k, v) for k, v in modvars.items() if not k.startswith(u'_')) + +def uimportvars(uname): + """Import module according to policy and return exported vars""" + upkgnames = _upackagetable[policy] + for upkg in upkgnames: + try: + # pass globals() to resolve name relative to this module + mod = __import__(u'%s.%s' % (upkg, uname), globals(), level=1) + mod = getattr(mod, uname) + return _uexportedvars(mod) + except ImportError: + if upkg == upkgnames[-1]: + raise