mercurial/__init__.py
changeset 27225 30a20167ae29
parent 27224 d308a9ca9ed7
child 28430 17b85d739b62
--- a/mercurial/__init__.py	Tue Nov 24 22:21:51 2015 -0800
+++ b/mercurial/__init__.py	Thu Dec 03 21:25:05 2015 -0800
@@ -10,6 +10,7 @@
 import imp
 import os
 import sys
+import zipimport
 
 __all__ = []
 
@@ -60,6 +61,36 @@
 
         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 == 'py':
+                    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 == '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.