[PATCH 4 of 5 import-refactor] hg: gracefully handle PyPy

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


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1448168629 28800
#      Sat Nov 21 21:03:49 2015 -0800
# Node ID 1101c57a493083f9fd3dc2eb7832f862c587cd5a
# Parent  b1f0ae9d3abf60a1326e305237c31ce3fee7262b
hg: gracefully handle PyPy

PyPy isn't compatible with C extensions nor the on demand module import
mechanism.

In this patch, we add detection for PyPy in the "hg" script. When
executed via PyPy, we will now only attempt to load the pure Python
modules and will disable the on demand importer. Running ./hg with
PyPy from a source checkout will "just work," enabling easier
development and testing with PyPy.

diff --git a/hg b/hg
--- a/hg
+++ b/hg
@@ -10,48 +10,62 @@
 import imp
 import os
 import sys
 
 if os.environ.get('HGUNICODEPEDANTRY', False):
     reload(sys)
     sys.setdefaultencoding("undefined")
 
+# PyPy doesn't load C extensions and isn't compatible with demand importing.
+#
+# The canonical way to do this is to test platform.python_implementation().
+# But we don't import platform anywhere, so don't require it here.
+if '__pypy__' in sys.builtin_module_names:
+    pypy = True
+else:
+    pypy = False
 
 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'
 
+# PyPy isn't compatible with C extensions. So don't try to load them.
+if pypy:
+    modulepolicy = 'py'
+
 # 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
-try:
-    from mercurial import demandimport; demandimport.enable()
-except ImportError:
-    import sys
-    sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" %
-                     ' '.join(sys.path))
-    sys.stderr.write("(check your install and PYTHONPATH)\n")
-    sys.exit(-1)
+# On demand importing doesn't work with PyPy (yet).
+if not pypy:
+    # Enable importing on demand to reduce startup time.
+    try:
+        from mercurial import demandimport; demandimport.enable()
+    except ImportError:
+        import sys
+        sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" %
+                         ' '.join(sys.path))
+        sys.stderr.write("(check your install and PYTHONPATH)\n")
+        sys.exit(-1)
 
 # Install a PEP-302 custom module finder and loader that knows how to
 # import modules with implementations in both Python and C.
 
 # List of modules that have both Python and C implementations. See also the
 # set of .py files under mercurial/pure/.
 dualmodules = set([
     'mercurial.base85',


More information about the Mercurial-devel mailing list