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
--- 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)