[PATCH 2 of 5 import-refactor] hg: support different module load policies

Gregory Szorc gregory.szorc at gmail.com
Sun Nov 22 00:14:04 CST 2015


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1448167251 28800
#      Sat Nov 21 20:40:51 2015 -0800
# Node ID 594a8931ee9b1eb82f754a3a4eab3cfc7b3811b1
# Parent  3d32b988b6d49f95d507e456b3e627f27e816ba8
hg: support different module load policies

This patch adds a mechanism to control how we handle the loading of
modules with both Python and C implementations. We call the loading
behavior the "module load policy." There are 3 settings:

* Only load C extensions
* Only load pure Python
* Try to load C and fall back to Python

The default mode is to only load C extensions.

An environment variable allows overriding the policy at run time.

diff --git a/hg b/hg
--- a/hg
+++ b/hg
@@ -13,16 +13,29 @@ import sys
 
 if os.environ.get('HGUNICODEPEDANTRY', False):
     reload(sys)
     sys.setdefaultencoding("undefined")
 
 
 libdir = '@LIBDIR@'
 
+# Rules for how modules can be loaded. Values are:
+#    c - require C extensions
+#    allow - allow pure Python implementation when C loading fails
+#    py - only load pure Python modules
+modulepolicy = '@MODULELOADPOLICY@'
+
+# By default, require the C extensions for performance reasons.
+if modulepolicy == '@' 'MODULELOADPOLICY' '@':
+    modulepolicy = 'c'
+
+# Environment variable can always force settings.
+modulepolicy = os.environ.get('HGMODULEPOLICY', modulepolicy)
+
 if libdir != '@' 'LIBDIR' '@':
     if not os.path.isabs(libdir):
         libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                               libdir)
         libdir = os.path.abspath(libdir)
     sys.path.insert(0, libdir)
 
 # enable importing on demand to reduce startup time
@@ -66,17 +79,31 @@ class hgimporter(object):
         # 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]
 
         # C extensions are available under mercurial.*.
         # Pure Python available under mercurial.* if they are installed there
         # or mercurial.pure.* if they aren't installed.
-        modinfo = imp.find_module(stem, mercurial.__path__)
+        try:
+            if modulepolicy == 'py':
+                raise ImportError()
+
+            modinfo = imp.find_module(stem, mercurial.__path__)
+        except ImportError:
+            if modulepolicy == 'c':
+                raise
+
+            # Could not load the C extension and pure Python is allowed. So try to
+            # load them.
+            import mercurial.pure as puremod
+            modinfo = imp.find_module(stem, puremod.__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
 
 sys.meta_path.insert(0, hgimporter())
 
 import mercurial.util


More information about the Mercurial-devel mailing list