# HG changeset patch # User Yuya Nishihara # Date 1471058932 -32400 # Node ID 5700825889fbbf1e299a898542833b2074808605 # Parent df448de7cf3b4a95f34f7b7b34346ffe8be687ed policy: drop custom importer for pure modules diff -r df448de7cf3b -r 5700825889fb mercurial/__init__.py --- a/mercurial/__init__.py Sat Aug 13 12:23:56 2016 +0900 +++ b/mercurial/__init__.py Sat Aug 13 12:28:52 2016 +0900 @@ -7,120 +7,16 @@ from __future__ import absolute_import -import imp -import os import sys -import zipimport - -from . import ( - policy -) __all__ = [] -modulepolicy = policy.policy - -# Modules that have both Python and C implementations. See also the -# set of .py files under mercurial/pure/. -_dualmodules = { -} - -class hgimporter(object): - """Object that conforms to import hook interface defined in PEP-302.""" - def find_module(self, name, path=None): - # We only care about modules that have both C and pure implementations. - if name in _dualmodules: - return self - return None - - def load_module(self, name): - mod = sys.modules.get(name, None) - if mod: - return mod - - mercurial = sys.modules['mercurial'] - - # The zip importer behaves sufficiently differently from the default - # importer to warrant its own code path. - loader = getattr(mercurial, '__loader__', None) - if isinstance(loader, zipimport.zipimporter): - def ziploader(*paths): - """Obtain a zipimporter for a directory under the main zip.""" - path = os.path.join(loader.archive, *paths) - zl = sys.path_importer_cache.get(path) - if not zl: - zl = zipimport.zipimporter(path) - return zl - - try: - if modulepolicy in policy.policynoc: - raise ImportError() - - zl = ziploader('mercurial') - mod = zl.load_module(name) - # Unlike imp, ziploader doesn't expose module metadata that - # indicates the type of module. So just assume what we found - # is OK (even though it could be a pure Python module). - except ImportError: - if modulepolicy == b'c': - raise - zl = ziploader('mercurial', 'pure') - mod = zl.load_module(name) - - sys.modules[name] = mod - return mod - - # Unlike the default importer which searches special locations and - # sys.path, we only look in the directory where "mercurial" was - # imported from. - - # imp.find_module doesn't support submodules (modules with "."). - # Instead you have to pass the parent package's __path__ attribute - # as the path argument. - stem = name.split('.')[-1] - - try: - if modulepolicy in policy.policynoc: - raise ImportError() - - modinfo = imp.find_module(stem, mercurial.__path__) - - # The Mercurial installer used to copy files from - # mercurial/pure/*.py to mercurial/*.py. Therefore, it's possible - # for some installations to have .py files under mercurial/*. - # Loading Python modules when we expected C versions could result - # in a) poor performance b) loading a version from a previous - # Mercurial version, potentially leading to incompatibility. Either - # scenario is bad. So we verify that modules loaded from - # mercurial/* are C extensions. If the current policy allows the - # loading of .py modules, the module will be re-imported from - # mercurial/pure/* below. - if modinfo[2][2] != imp.C_EXTENSION: - raise ImportError('.py version of %s found where C ' - 'version should exist' % name) - - except ImportError: - if modulepolicy == b'c': - raise - - # Could not load the C extension and pure Python is allowed. So - # try to load them. - from . import pure - modinfo = imp.find_module(stem, pure.__path__) - if not modinfo: - raise ImportError('could not find mercurial module %s' % - name) - - mod = imp.load_module(name, *modinfo) - sys.modules[name] = mod - return mod - # Python 3 uses a custom module loader that transforms source code between # source file reading and compilation. This is done by registering a custom # finder that changes the spec for Mercurial modules to use a custom loader. if sys.version_info[0] >= 3: - from . import pure import importlib + import importlib.abc import io import token import tokenize @@ -135,14 +31,6 @@ if fullname.startswith('mercurial.zstd'): return None - # This assumes Python 3 doesn't support loading C modules. - if fullname in _dualmodules: - stem = fullname.split('.')[-1] - fullname = 'mercurial.pure.%s' % stem - target = pure - assert len(path) == 1 - path = [os.path.join(path[0], 'pure')] - # Try to find the module using other registered finders. spec = None for finder in sys.meta_path: @@ -159,10 +47,6 @@ if not spec: return None - if (fullname.startswith('mercurial.pure.') - and fullname.replace('.pure.', '.') in _dualmodules): - spec.name = spec.name.replace('.pure.', '.') - # TODO need to support loaders from alternate specs, like zip # loaders. spec.loader = hgloader(spec.name, spec.origin) @@ -386,13 +270,10 @@ # implemented them because they are very ugly. return super(hgloader, self).source_to_code(data, path) -# We automagically register our custom importer as a side-effect of loading. -# This is necessary to ensure that any entry points are able to import -# mercurial.* modules without having to perform this registration themselves. -if sys.version_info[0] >= 3: - _importercls = hgpathentryfinder -else: - _importercls = hgimporter -if not any(isinstance(x, _importercls) for x in sys.meta_path): - # meta_path is used before any implicit finders and before sys.path. - sys.meta_path.insert(0, _importercls()) + # We automagically register our custom importer as a side-effect of + # loading. This is necessary to ensure that any entry points are able + # to import mercurial.* modules without having to perform this + # registration themselves. + if not any(isinstance(x, hgpathentryfinder) for x in sys.meta_path): + # meta_path is used before any implicit finders and before sys.path. + sys.meta_path.insert(0, hgpathentryfinder())