pycompat: make fewer assumptions about sys.executable
authorRodrigo Damazio Bovendorp <rdamazio@google.com>
Tue, 25 Jun 2019 19:28:41 -0700
changeset 42523 49998d5ba66a
parent 42522 d29db0a0c4eb
child 42524 f3fa10a5877d
pycompat: make fewer assumptions about sys.executable There are many Python "bundlers" which create an archive to run a Python binary from, and they may not set sys.executable at all - handle that case properly, especially to run tests. Differential Revision: https://phab.mercurial-scm.org/D6575
mercurial/chgserver.py
mercurial/debugcommands.py
tests/run-tests.py
--- a/mercurial/chgserver.py	Thu Jun 27 11:39:35 2019 +0200
+++ b/mercurial/chgserver.py	Tue Jun 25 19:28:41 2019 -0700
@@ -138,7 +138,9 @@
         modules.append(__version__)
     except ImportError:
         pass
-    files = [pycompat.sysexecutable]
+    files = []
+    if pycompat.sysexecutable:
+        files.append(pycompat.sysexecutable)
     for m in modules:
         try:
             files.append(pycompat.fsencode(inspect.getabsfile(m)))
--- a/mercurial/debugcommands.py	Thu Jun 27 11:39:35 2019 +0200
+++ b/mercurial/debugcommands.py	Tue Jun 25 19:28:41 2019 -0700
@@ -1240,7 +1240,7 @@
 
     # Python
     fm.write('pythonexe', _("checking Python executable (%s)\n"),
-             pycompat.sysexecutable)
+             pycompat.sysexecutable or _("unknown"))
     fm.write('pythonver', _("checking Python version (%s)\n"),
              ("%d.%d.%d" % sys.version_info[:3]))
     fm.write('pythonlib', _("checking Python lib (%s)...\n"),
--- a/tests/run-tests.py	Thu Jun 27 11:39:35 2019 +0200
+++ b/tests/run-tests.py	Tue Jun 25 19:28:41 2019 -0700
@@ -282,7 +282,16 @@
 
     return p
 
-PYTHON = _bytespath(sys.executable.replace('\\', '/'))
+if sys.executable:
+    sysexecutable = sys.executable
+elif os.environ.get('PYTHONEXECUTABLE'):
+    sysexecutable = os.environ['PYTHONEXECUTABLE']
+elif os.environ.get('PYTHON'):
+    sysexecutable = os.environ['PYTHON']
+else:
+    raise AssertionError('Could not find Python interpreter')
+
+PYTHON = _bytespath(sysexecutable.replace('\\', '/'))
 IMPL_PATH = b'PYTHONPATH'
 if 'java' in sys.platform:
     IMPL_PATH = b'JYTHONPATH'
@@ -1094,7 +1103,7 @@
         env["HGRCPATH"] = _strpath(os.path.join(self._threadtmp, b'.hgrc'))
         env["DAEMON_PIDS"] = _strpath(os.path.join(self._threadtmp,
                                                    b'daemon.pids'))
-        env["HGEDITOR"] = ('"' + sys.executable + '"'
+        env["HGEDITOR"] = ('"' + sysexecutable + '"'
                            + ' -c "import sys; sys.exit(0)"')
         env["HGUSER"]   = "test"
         env["HGENCODING"] = "ascii"
@@ -2349,7 +2358,7 @@
             withhg = self._runner.options.with_hg
             if withhg:
                 opts += ' --with-hg=%s ' % shellquote(_strpath(withhg))
-            rtc = '%s %s %s %s' % (sys.executable, sys.argv[0], opts,
+            rtc = '%s %s %s %s' % (sysexecutable, sys.argv[0], opts,
                                    test)
             data = pread(bisectcmd + ['--command', rtc])
             m = re.search(
@@ -3003,25 +3012,25 @@
         # Administrator rights.
         if getattr(os, 'symlink', None) and os.name != 'nt':
             vlog("# Making python executable in test path a symlink to '%s'" %
-                 sys.executable)
+                 sysexecutable)
             mypython = os.path.join(self._tmpbindir, pyexename)
             try:
-                if os.readlink(mypython) == sys.executable:
+                if os.readlink(mypython) == sysexecutable:
                     return
                 os.unlink(mypython)
             except OSError as err:
                 if err.errno != errno.ENOENT:
                     raise
-            if self._findprogram(pyexename) != sys.executable:
+            if self._findprogram(pyexename) != sysexecutable:
                 try:
-                    os.symlink(sys.executable, mypython)
+                    os.symlink(sysexecutable, mypython)
                     self._createdfiles.append(mypython)
                 except OSError as err:
                     # child processes may race, which is harmless
                     if err.errno != errno.EEXIST:
                         raise
         else:
-            exedir, exename = os.path.split(sys.executable)
+            exedir, exename = os.path.split(sysexecutable)
             vlog("# Modifying search path to find %s as %s in '%s'" %
                  (exename, pyexename, exedir))
             path = os.environ['PATH'].split(os.pathsep)
@@ -3048,7 +3057,7 @@
 
         # Run installer in hg root
         script = os.path.realpath(sys.argv[0])
-        exe = sys.executable
+        exe = sysexecutable
         if PYTHON3:
             compiler = _bytespath(compiler)
             script = _bytespath(script)