Patchwork [3,of,5] tests: quote PYTHON usage

login
register
mail settings
Submitter Matt Harbison
Date Sept. 19, 2018, 12:03 p.m.
Message ID <121c7ecc6a829a49bb66.1537358635@Envy>
Download mbox | patch
Permalink /patch/34830/
State Accepted
Headers show

Comments

Matt Harbison - Sept. 19, 2018, 12:03 p.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1537328841 14400
#      Tue Sep 18 23:47:21 2018 -0400
# Node ID 121c7ecc6a829a49bb6602cf5049dd802af69626
# Parent  b99b91e41ae278b503c91895068cd10e0d0a429a
tests: quote PYTHON usage

Python3 defaults to installing under "Program Files".

Patch

diff --git a/tests/test-addremove-similar.t b/tests/test-addremove-similar.t
--- a/tests/test-addremove-similar.t
+++ b/tests/test-addremove-similar.t
@@ -1,7 +1,7 @@ 
   $ hg init rep; cd rep
 
   $ touch empty-file
-  $ $PYTHON -c 'for x in range(10000): print(x)' > large-file
+  $ "$PYTHON" -c 'for x in range(10000): print(x)' > large-file
 
   $ hg addremove
   adding empty-file
@@ -10,7 +10,7 @@ 
   $ hg commit -m A
 
   $ rm large-file empty-file
-  $ $PYTHON -c 'for x in range(10,10000): print(x)' > another-file
+  $ "$PYTHON" -c 'for x in range(10,10000): print(x)' > another-file
 
   $ hg addremove -s50
   adding another-file
@@ -34,8 +34,8 @@  comparing two empty files caused ZeroDiv
 
   $ hg init rep2; cd rep2
 
-  $ $PYTHON -c 'for x in range(10000): print(x)' > large-file
-  $ $PYTHON -c 'for x in range(50): print(x)' > tiny-file
+  $ "$PYTHON" -c 'for x in range(10000): print(x)' > large-file
+  $ "$PYTHON" -c 'for x in range(50): print(x)' > tiny-file
 
   $ hg addremove
   adding large-file
@@ -43,7 +43,7 @@  comparing two empty files caused ZeroDiv
 
   $ hg commit -m A
 
-  $ $PYTHON -c 'for x in range(70): print(x)' > small-file
+  $ "$PYTHON" -c 'for x in range(70): print(x)' > small-file
   $ rm tiny-file
   $ rm large-file
 
@@ -57,7 +57,7 @@  comparing two empty files caused ZeroDiv
 
 should be sorted by path for stable result
 
-  $ for i in `$PYTHON $TESTDIR/seq.py 0 9`; do
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 0 9`; do
   >     cp small-file $i
   > done
   $ rm small-file
@@ -88,7 +88,7 @@  should be sorted by path for stable resu
 pick one from many identical files
 
   $ cp 0 a
-  $ rm `$PYTHON $TESTDIR/seq.py 0 9`
+  $ rm `"$PYTHON" $TESTDIR/seq.py 0 9`
   $ hg addremove
   removing 0
   removing 1
@@ -107,11 +107,11 @@  pick one from many identical files
 pick one from many similar files
 
   $ cp 0 a
-  $ for i in `$PYTHON $TESTDIR/seq.py 0 9`; do
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 0 9`; do
   >     echo $i >> $i
   > done
   $ hg commit -m 'make them slightly different'
-  $ rm `$PYTHON $TESTDIR/seq.py 0 9`
+  $ rm `"$PYTHON" $TESTDIR/seq.py 0 9`
   $ hg addremove -s50
   removing 0
   removing 1
diff --git a/tests/test-amend.t b/tests/test-amend.t
--- a/tests/test-amend.t
+++ b/tests/test-amend.t
@@ -250,15 +250,15 @@  Generates history of files having 3 stat
   $ hg init $TESTTMP/wcstates
   $ cd $TESTTMP/wcstates
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove -q --similarity 0
   $ hg commit -m0
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove -q --similarity 0
   $ hg commit -m1
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*-untracked
   $ rm *_*_missing-*
diff --git a/tests/test-annotate.t b/tests/test-annotate.t
--- a/tests/test-annotate.t
+++ b/tests/test-annotate.t
@@ -950,13 +950,13 @@  Annotate with orphaned CR (issue5798)
   ...     f.write(b'0a\r0b\r\n1c\r1d\r\n0e\n1f\n0g') and None
   $ hg ci -m1
 
-  $ hg annotate -r0 a | $PYTHON "$TESTTMP/substcr.py"
+  $ hg annotate -r0 a | "$PYTHON" "$TESTTMP/substcr.py"
   0: 0a[CR]0b[CR]
   0: 0c[CR]0d[CR]
   0: 0e
   0: 0f
   0: 0g
-  $ hg annotate -r1 a | $PYTHON "$TESTTMP/substcr.py"
+  $ hg annotate -r1 a | "$PYTHON" "$TESTTMP/substcr.py"
   0: 0a[CR]0b[CR]
   1: 1c[CR]1d[CR]
   0: 0e
diff --git a/tests/test-archive.t b/tests/test-archive.t
--- a/tests/test-archive.t
+++ b/tests/test-archive.t
@@ -341,7 +341,7 @@  invalid arch type should give 404
   > except util.urlerr.httperror as e:
   >     sys.stderr.write(str(e) + '\n')
   > EOF
-  $ $PYTHON getarchive.py "$TIP" gz | gunzip | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" gz | gunzip | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/.hg_archival.txt
   test-archive-1701ef1f1510/.hgsub
   test-archive-1701ef1f1510/.hgsubstate
@@ -349,7 +349,7 @@  invalid arch type should give 404
   test-archive-1701ef1f1510/baz/bletch
   test-archive-1701ef1f1510/foo
   test-archive-1701ef1f1510/subrepo/sub
-  $ $PYTHON getarchive.py "$TIP" bz2 | bunzip2 | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" bz2 | bunzip2 | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/.hg_archival.txt
   test-archive-1701ef1f1510/.hgsub
   test-archive-1701ef1f1510/.hgsubstate
@@ -357,7 +357,7 @@  invalid arch type should give 404
   test-archive-1701ef1f1510/baz/bletch
   test-archive-1701ef1f1510/foo
   test-archive-1701ef1f1510/subrepo/sub
-  $ $PYTHON getarchive.py "$TIP" zip > archive.zip
+  $ "$PYTHON" getarchive.py "$TIP" zip > archive.zip
   $ unzip -t archive.zip
   Archive:  archive.zip
       testing: test-archive-1701ef1f1510/.hg_archival.txt*OK (glob)
@@ -371,19 +371,19 @@  invalid arch type should give 404
 
 test that we can download single directories and files
 
-  $ $PYTHON getarchive.py "$TIP" gz baz | gunzip | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" gz baz | gunzip | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/baz/bletch
-  $ $PYTHON getarchive.py "$TIP" gz foo | gunzip | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" gz foo | gunzip | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/foo
 
 test that we detect file patterns that match no files
 
-  $ $PYTHON getarchive.py "$TIP" gz foobar
+  $ "$PYTHON" getarchive.py "$TIP" gz foobar
   HTTP Error 404: file(s) not found: foobar
 
 test that we reject unsafe patterns
 
-  $ $PYTHON getarchive.py "$TIP" gz relre:baz
+  $ "$PYTHON" getarchive.py "$TIP" gz relre:baz
   HTTP Error 404: file(s) not found: relre:baz
 
   $ killdaemons.py
@@ -464,7 +464,7 @@  rename them afterwards.
   $ sleep 1
   $ hg archive -t tgz tip.tar.gz
   $ mv tip.tar.gz tip2.tar.gz
-  $ $PYTHON md5comp.py tip1.tar.gz tip2.tar.gz
+  $ "$PYTHON" md5comp.py tip1.tar.gz tip2.tar.gz
   True
 
   $ hg archive -t zip -p /illegal test.zip
@@ -598,12 +598,12 @@  configured as GMT.
 
   $ hg -R repo archive --prefix tar-extracted archive.tar
   $ (TZ=UTC-3; export TZ; tar xf archive.tar)
-  $ $PYTHON show_mtime.py tar-extracted/a
+  $ "$PYTHON" show_mtime.py tar-extracted/a
   456789012
 
   $ hg -R repo archive --prefix zip-extracted archive.zip
   $ (TZ=UTC-3; export TZ; unzip -q archive.zip)
-  $ $PYTHON show_mtime.py zip-extracted/a
+  $ "$PYTHON" show_mtime.py zip-extracted/a
   456789012
 
   $ cd ..
diff --git a/tests/test-bad-pull.t b/tests/test-bad-pull.t
--- a/tests/test-bad-pull.t
+++ b/tests/test-bad-pull.t
@@ -7,7 +7,7 @@ 
   $ test -d copy
   [1]
 
-  $ $PYTHON "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
+  $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
   $ cat dumb.pid >> $DAEMON_PIDS
   $ hg clone http://localhost:$HGPORT/foo copy2
   abort: HTTP Error 404: * (glob)
diff --git a/tests/test-basic.t b/tests/test-basic.t
--- a/tests/test-basic.t
+++ b/tests/test-basic.t
@@ -68,7 +68,7 @@  Verify that updating to revision 0 via c
   > EOF
   $ hg up null
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ $PYTHON ./update_to_rev0.py
+  $ "$PYTHON" ./update_to_rev0.py
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg identify -n
   0
diff --git a/tests/test-blackbox.t b/tests/test-blackbox.t
--- a/tests/test-blackbox.t
+++ b/tests/test-blackbox.t
@@ -233,7 +233,7 @@  log rotation
   $ sed -e 's/\(.*test1.*\)/#\1/; s#\(.*commit2.*\)#os.rmdir(".hg/blackbox.log")\
   > os.rename(".hg/blackbox.log-", ".hg/blackbox.log")\
   > \1#' $TESTDIR/test-dispatch.py > ../test-dispatch.py
-  $ $PYTHON $TESTDIR/blackbox-readonly-dispatch.py
+  $ "$PYTHON" $TESTDIR/blackbox-readonly-dispatch.py
   running: --debug add foo
   warning: cannot write to blackbox.log: Is a directory (no-windows !)
   warning: cannot write to blackbox.log: $TESTTMP/blackboxtest3/.hg/blackbox.log: Access is denied (windows !)
@@ -343,7 +343,7 @@  when using chg, blackbox.log should get 
   > noop=$TESTTMP/noop.py
   > EOF
 
-  $ $PYTHON -c 'print("a" * 400)' > .hg/blackbox.log
+  $ "$PYTHON" -c 'print("a" * 400)' > .hg/blackbox.log
   $ chg noop
   $ chg noop
   $ chg noop
@@ -362,7 +362,7 @@  when using chg, blackbox.log should get 
   >     print('%s: %s %d' % (p, desc, limit))
   > EOF
 
-  $ $PYTHON showsize.py .hg/blackbox*
+  $ "$PYTHON" showsize.py .hg/blackbox*
   .hg/blackbox.log: < 500
   .hg/blackbox.log.1: >= 500
   .hg/blackbox.log.2: >= 500
diff --git a/tests/test-bookmarks-pushpull.t b/tests/test-bookmarks-pushpull.t
--- a/tests/test-bookmarks-pushpull.t
+++ b/tests/test-bookmarks-pushpull.t
@@ -435,7 +435,7 @@  divergent bookmarks
 
 (test that too many divergence of bookmark)
 
-  $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
+  $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
   $ hg pull ../a
   pulling from ../a
   searching for changes
@@ -463,7 +463,7 @@  divergent bookmarks
      @1                        2:0d2164f0ce0d
      @foo                      2:0d2164f0ce0d
 
-  $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
+  $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
   $ hg bookmarks -d "@1"
 
   $ hg push -f ../a
@@ -1082,7 +1082,7 @@  Check hook preventing push (issue4455)
   > ssh=ssh://user@dummy/issue4455-dest
   > http=http://localhost:$HGPORT/
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > EOF
   $ cat >> ../issue4455-dest/.hg/hgrc << EOF
   > [hooks]
diff --git a/tests/test-bundle2-format.t b/tests/test-bundle2-format.t
--- a/tests/test-bundle2-format.t
+++ b/tests/test-bundle2-format.t
@@ -232,7 +232,7 @@  Create an extension to test bundle2 API
   > [experimental]
   > evolution.createmarkers=True
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
   > [web]
   > push_ssl = false
diff --git a/tests/test-bundle2-pushback.t b/tests/test-bundle2-pushback.t
--- a/tests/test-bundle2-pushback.t
+++ b/tests/test-bundle2-pushback.t
@@ -36,7 +36,7 @@ 
 
   $ cat >> $HGRCPATH <<EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > username = nobody <no.reply@example.com>
   > 
   > [alias]
diff --git a/tests/test-bundle2-remote-changegroup.t b/tests/test-bundle2-remote-changegroup.t
--- a/tests/test-bundle2-remote-changegroup.t
+++ b/tests/test-bundle2-remote-changegroup.t
@@ -90,12 +90,12 @@  Create an extension to test bundle2 remo
 
 Start a simple HTTP server to serve bundles
 
-  $ $PYTHON "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
+  $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
   $ cat dumb.pid >> $DAEMON_PIDS
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
   > EOF
 
diff --git a/tests/test-censor.t b/tests/test-censor.t
--- a/tests/test-censor.t
+++ b/tests/test-censor.t
@@ -306,7 +306,7 @@  Can re-add file after being deleted + ce
 
 Can censor after revlog has expanded to no longer permit inline storage
 
-  $ for x in `$PYTHON $TESTDIR/seq.py 0 50000`
+  $ for x in `"$PYTHON" $TESTDIR/seq.py 0 50000`
   > do
   >   echo "Password: hunter$x" >> target
   > done
diff --git a/tests/test-check-config.t b/tests/test-check-config.t
--- a/tests/test-check-config.t
+++ b/tests/test-check-config.t
@@ -30,7 +30,7 @@  Sanity check check-config.py
 
   $ cd "$TESTDIR"/..
 
-  $ $PYTHON contrib/check-config.py < $TESTTMP/files
+  $ "$PYTHON" contrib/check-config.py < $TESTTMP/files
   foo = ui.configint('ui', 'intdefault', default=42)
   conflict on ui.intdefault: ('int', '42') != ('int', '1')
   at $TESTTMP/testfile.py:12:
@@ -44,4 +44,4 @@  Sanity check check-config.py
 New errors are not allowed. Warnings are strongly discouraged.
 
   $ testrepohg files "set:(**.py or **.txt) - tests/**" | sed 's|\\|/|g' |
-  >   $PYTHON contrib/check-config.py
+  >   "$PYTHON" contrib/check-config.py
diff --git a/tests/test-check-help.t b/tests/test-check-help.t
--- a/tests/test-check-help.t
+++ b/tests/test-check-help.t
@@ -25,5 +25,5 @@  Check if ":hg:`help TOPIC`" is valid:
 
   $ testrepohg files 'glob:{hgdemandimport,hgext,mercurial}/**/*.py' \
   > | sed 's|\\|/|g' \
-  > | xargs $PYTHON "$TESTTMP/scanhelptopics.py" \
+  > | xargs "$PYTHON" "$TESTTMP/scanhelptopics.py" \
   > | xargs -n1 hg help --config extensions.phabricator= > /dev/null
diff --git a/tests/test-check-module-imports.t b/tests/test-check-module-imports.t
--- a/tests/test-check-module-imports.t
+++ b/tests/test-check-module-imports.t
@@ -43,4 +43,4 @@  outputs, which should be fixed later.
   > -X tests/test-imports-checker.t \
   > -X tests/test-lock.py \
   > -X tests/test-verify-repo-operations.py \
-  > | sed 's-\\-/-g' | $PYTHON "$import_checker" -
+  > | sed 's-\\-/-g' | "$PYTHON" "$import_checker" -
diff --git a/tests/test-check-py3-compat.t b/tests/test-check-py3-compat.t
--- a/tests/test-check-py3-compat.t
+++ b/tests/test-check-py3-compat.t
@@ -7,7 +7,7 @@ 
   $ testrepohg files 'set:(**.py)' \
   > -X hgdemandimport/demandimportpy2.py \
   > -X mercurial/thirdparty/cbor \
-  > | sed 's|\\|/|g' | xargs $PYTHON contrib/check-py3-compat.py
+  > | sed 's|\\|/|g' | xargs "$PYTHON" contrib/check-py3-compat.py
   contrib/python-zstandard/setup.py not using absolute_import
   contrib/python-zstandard/setup_zstd.py not using absolute_import
   contrib/python-zstandard/tests/common.py not using absolute_import
@@ -30,7 +30,7 @@ 
   > -X hgext/fsmonitor/pywatchman \
   > -X mercurial/cffi \
   > -X mercurial/thirdparty \
-  > | sed 's|\\|/|g' | xargs $PYTHON contrib/check-py3-compat.py \
+  > | sed 's|\\|/|g' | xargs "$PYTHON" contrib/check-py3-compat.py \
   > | sed 's/[0-9][0-9]*)$/*)/'
   hgext/convert/transport.py: error importing: <*Error> No module named 'svn.client' (error at transport.py:*) (glob) (?)
   hgext/infinitepush/sqlindexapi.py: error importing: <*Error> No module named 'mysql' (error at sqlindexapi.py:*) (glob) (?)
@@ -42,6 +42,6 @@ 
 
 #if py3k pygments
   $ testrepohg files 'set:(**.py) and grep(pygments)' | sed 's|\\|/|g' \
-  > | xargs $PYTHON contrib/check-py3-compat.py \
+  > | xargs "$PYTHON" contrib/check-py3-compat.py \
   > | sed 's/[0-9][0-9]*)$/*)/'
 #endif
diff --git a/tests/test-chg.t b/tests/test-chg.t
--- a/tests/test-chg.t
+++ b/tests/test-chg.t
@@ -89,7 +89,7 @@  enable pager extension globally, but spa
   > [extensions]
   > pager =
   > [pager]
-  > pager = $PYTHON $TESTTMP/fakepager.py
+  > pager = "$PYTHON" $TESTTMP/fakepager.py
   > EOF
   $ chg version > /dev/null
   $ touch foo
diff --git a/tests/test-clone-cgi.t b/tests/test-clone-cgi.t
--- a/tests/test-clone-cgi.t
+++ b/tests/test-clone-cgi.t
@@ -26,13 +26,13 @@  try hgweb request
 
   $ . "$TESTDIR/cgienv"
   $ QUERY_STRING="cmd=changegroup&roots=0000000000000000000000000000000000000000"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi >page1 2>&1
-  $ $PYTHON "$TESTDIR/md5sum.py" page1
+  $ "$PYTHON" hgweb.cgi >page1 2>&1
+  $ "$PYTHON" "$TESTDIR/md5sum.py" page1
   1f424bb22ec05c3c6bc866b6e67efe43  page1
 
 make sure headers are sent even when there is no body
 
-  $ QUERY_STRING="cmd=listkeys&namespace=nosuchnamespace" $PYTHON hgweb.cgi
+  $ QUERY_STRING="cmd=listkeys&namespace=nosuchnamespace" "$PYTHON" hgweb.cgi
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 0\r (esc)
diff --git a/tests/test-clone.t b/tests/test-clone.t
--- a/tests/test-clone.t
+++ b/tests/test-clone.t
@@ -20,7 +20,7 @@  Prepare repo a:
 
 Create a non-inlined filelog:
 
-  $ $PYTHON -c 'open("data1", "wb").write(b"".join(b"%d\n" % x for x in range(10000)))'
+  $ "$PYTHON" -c 'open("data1", "wb").write(b"".join(b"%d\n" % x for x in range(10000)))'
   $ for j in 0 1 2 3 4 5 6 7 8 9; do
   >   cat data1 >> b
   >   hg commit -m test
@@ -564,7 +564,7 @@  iterable in addbranchrevs()
   > hg.clone(myui, {}, repo, dest=b"ua")
   > EOF
 
-  $ $PYTHON simpleclone.py
+  $ "$PYTHON" simpleclone.py
   updating to branch default
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
@@ -578,7 +578,7 @@  iterable in addbranchrevs()
   > hg.clone(myui, {}, repo, dest=b"ua", branch=[b"stable",])
   > EOF
 
-  $ $PYTHON branchclone.py
+  $ "$PYTHON" branchclone.py
   adding changesets
   adding manifests
   adding file changes
diff --git a/tests/test-commit-interactive-curses.t b/tests/test-commit-interactive-curses.t
--- a/tests/test-commit-interactive-curses.t
+++ b/tests/test-commit-interactive-curses.t
@@ -350,7 +350,7 @@  Check ui.interface logic for the chunkse
 The default interface is text
   $ cp $HGRCPATH.pretest $HGRCPATH
   $ chunkselectorinterface() {
-  > $PYTHON <<EOF
+  > "$PYTHON" <<EOF
   > from mercurial import hg, ui;\
   > repo = hg.repository(ui.ui.load(), ".");\
   > print(repo.ui.interface("chunkselector"))
diff --git a/tests/test-commit-interactive.t b/tests/test-commit-interactive.t
--- a/tests/test-commit-interactive.t
+++ b/tests/test-commit-interactive.t
@@ -915,7 +915,7 @@  This tests that translated help message 
   >         b''.join(escape(c) for c in pycompat.iterbytestr(l)))
   > EOF
 
-  $ hg commit -i --encoding cp932 2>&1 <<EOF | $PYTHON $TESTTMP/escape.py | grep '^y - '
+  $ hg commit -i --encoding cp932 2>&1 <<EOF | "$PYTHON" $TESTTMP/escape.py | grep '^y - '
   > ?
   > q
   > EOF
diff --git a/tests/test-commit-multiple.t b/tests/test-commit-multiple.t
--- a/tests/test-commit-multiple.t
+++ b/tests/test-commit-multiple.t
@@ -115,7 +115,7 @@  now test that we fixed the bug for all s
   > printfiles(repo, 6)
   > printfiles(repo, 7)
   > __EOF__
-  $ $PYTHON $TESTTMP/committwice.py
+  $ "$PYTHON" $TESTTMP/committwice.py
   PRE: len(repo): 6
   POST: len(repo): 8
   revision 6 files: ['bugfix', 'file1']
diff --git a/tests/test-commit.t b/tests/test-commit.t
--- a/tests/test-commit.t
+++ b/tests/test-commit.t
@@ -654,7 +654,7 @@  verify pathauditor blocks evil filepaths
   >                    b'evil', [notrc], filectxfn, 0)
   > r.commitctx(c)
   > EOF
-  $ $PYTHON evil-commit.py
+  $ "$PYTHON" evil-commit.py
 #if windows
   $ hg co --clean tip
   abort: path contains illegal component: .h\xe2\x80\x8cg\\hgrc (esc)
@@ -680,7 +680,7 @@  verify pathauditor blocks evil filepaths
   >                    b'evil', [notrc], filectxfn, 0)
   > r.commitctx(c)
   > EOF
-  $ $PYTHON evil-commit.py
+  $ "$PYTHON" evil-commit.py
   $ hg co --clean tip
   abort: path contains illegal component: HG~1/hgrc
   [255]
@@ -700,7 +700,7 @@  verify pathauditor blocks evil filepaths
   >                    b'evil', [notrc], filectxfn, 0)
   > r.commitctx(c)
   > EOF
-  $ $PYTHON evil-commit.py
+  $ "$PYTHON" evil-commit.py
   $ hg co --clean tip
   abort: path contains illegal component: HG8B6C~2/hgrc
   [255]
diff --git a/tests/test-conflict.t b/tests/test-conflict.t
--- a/tests/test-conflict.t
+++ b/tests/test-conflict.t
@@ -137,7 +137,7 @@  Verify line splitting of custom conflict
 Verify line trimming of custom conflict marker using multi-byte characters
 
   $ hg up -q --clean .
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > fp = open('logfile', 'wb')
   > fp.write(b'12345678901234567890123456789012345678901234567890' +
   >          b'1234567890') # there are 5 more columns for 80 columns
diff --git a/tests/test-contrib-dumprevlog.t b/tests/test-contrib-dumprevlog.t
--- a/tests/test-contrib-dumprevlog.t
+++ b/tests/test-contrib-dumprevlog.t
@@ -22,7 +22,7 @@ 
   checked 3 changesets with 3 changes to 1 files
 
 Dumping revlog of file a to stdout:
-  $ $PYTHON "$CONTRIBDIR/dumprevlog" .hg/store/data/a.i
+  $ "$PYTHON" "$CONTRIBDIR/dumprevlog" .hg/store/data/a.i
   file: .hg/store/data/a.i
   node: 183d2312b35066fb6b3b449b84efc370d50993d0
   linkrev: 0
@@ -54,14 +54,14 @@  Dumping revlog of file a to stdout:
 
 Dump all revlogs to file repo.dump:
 
-  $ find .hg/store -name "*.i" | sort | xargs $PYTHON "$CONTRIBDIR/dumprevlog" > ../repo.dump
+  $ find .hg/store -name "*.i" | sort | xargs "$PYTHON" "$CONTRIBDIR/dumprevlog" > ../repo.dump
   $ cd ..
 
 Undumping into repo-b:
 
   $ hg init repo-b
   $ cd repo-b
-  $ $PYTHON "$CONTRIBDIR/undumprevlog" < ../repo.dump
+  $ "$PYTHON" "$CONTRIBDIR/undumprevlog" < ../repo.dump
   .hg/store/00changelog.i
   .hg/store/00manifest.i
   .hg/store/data/a.i
diff --git a/tests/test-contrib.t b/tests/test-contrib.t
--- a/tests/test-contrib.t
+++ b/tests/test-contrib.t
@@ -14,7 +14,7 @@  Test simplemerge command:
 
 changing local directly
 
-  $ $PYTHON simplemerge local base other && echo "merge succeeded"
+  $ "$PYTHON" simplemerge local base other && echo "merge succeeded"
   merge succeeded
   $ cat local
   local
@@ -24,7 +24,7 @@  changing local directly
 
 printing to stdout
 
-  $ $PYTHON simplemerge -p local base other
+  $ "$PYTHON" simplemerge -p local base other
   local
   base
   other
@@ -43,7 +43,7 @@  conflicts
   $ echo end >> conflict-local
   $ echo end >> conflict-other
 
-  $ $PYTHON simplemerge -p conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p conflict-local base conflict-other
   base
   <<<<<<< conflict-local
   not other
@@ -55,7 +55,7 @@  conflicts
 
 1 label
 
-  $ $PYTHON simplemerge -p -L foo conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo conflict-local base conflict-other
   base
   <<<<<<< foo
   not other
@@ -67,7 +67,7 @@  1 label
 
 2 labels
 
-  $ $PYTHON simplemerge -p -L foo -L bar conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo -L bar conflict-local base conflict-other
   base
   <<<<<<< foo
   not other
@@ -79,7 +79,7 @@  2 labels
 
 3 labels
 
-  $ $PYTHON simplemerge -p -L foo -L bar -L base conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo -L bar -L base conflict-local base conflict-other
   base
   <<<<<<< foo
   not other
@@ -93,21 +93,21 @@  3 labels
 
 too many labels
 
-  $ $PYTHON simplemerge -p -L foo -L bar -L baz -L buz conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo -L bar -L baz -L buz conflict-local base conflict-other
   abort: can only specify three labels.
   [255]
 
 binary file
 
-  $ $PYTHON -c "f = open('binary-local', 'w'); f.write('\x00'); f.close()"
+  $ "$PYTHON" -c "f = open('binary-local', 'w'); f.write('\x00'); f.close()"
   $ cat orig >> binary-local
-  $ $PYTHON simplemerge -p binary-local base other
+  $ "$PYTHON" simplemerge -p binary-local base other
   warning: binary-local looks like a binary file.
   [1]
 
 binary file --text
 
-  $ $PYTHON simplemerge -a -p binary-local base other 2>&1
+  $ "$PYTHON" simplemerge -a -p binary-local base other 2>&1
   warning: binary-local looks like a binary file.
   \x00local (esc)
   base
@@ -115,7 +115,7 @@  binary file --text
 
 help
 
-  $ $PYTHON simplemerge --help
+  $ "$PYTHON" simplemerge --help
   simplemerge [OPTS] LOCAL BASE OTHER
   
       Simple three-way file merge utility with a minimal feature set.
@@ -134,7 +134,7 @@  help
 
 wrong number of arguments
 
-  $ $PYTHON simplemerge
+  $ "$PYTHON" simplemerge
   simplemerge: wrong number of arguments
   simplemerge [OPTS] LOCAL BASE OTHER
   
@@ -155,7 +155,7 @@  wrong number of arguments
 
 bad option
 
-  $ $PYTHON simplemerge --foo -p local base other
+  $ "$PYTHON" simplemerge --foo -p local base other
   simplemerge: option --foo not recognized
   simplemerge [OPTS] LOCAL BASE OTHER
   
diff --git a/tests/test-convert-bzr-ghosts.t b/tests/test-convert-bzr-ghosts.t
--- a/tests/test-convert-bzr-ghosts.t
+++ b/tests/test-convert-bzr-ghosts.t
@@ -21,7 +21,7 @@  ghost revisions
   $ bzr add -q somefile
   $ bzr commit -q -m 'Initial layout setup'
   $ echo morecontent >> somefile
-  $ $PYTHON ../../ghostcreator.py 'Commit with ghost revision' ghostrev
+  $ "$PYTHON" ../../ghostcreator.py 'Commit with ghost revision' ghostrev
   $ cd ..
   $ hg convert source source-hg
   initializing destination source-hg repository
diff --git a/tests/test-convert-bzr-treeroot.t b/tests/test-convert-bzr-treeroot.t
--- a/tests/test-convert-bzr-treeroot.t
+++ b/tests/test-convert-bzr-treeroot.t
@@ -20,7 +20,7 @@  change the id of the tree root
   $ echo content > file
   $ bzr add -q file
   $ bzr commit -q -m 'Initial add'
-  $ $PYTHON ../../treeset.py 'Changed root' new
+  $ "$PYTHON" ../../treeset.py 'Changed root' new
   $ cd ..
   $ hg convert source source-hg
   initializing destination source-hg repository
diff --git a/tests/test-convert-bzr.t b/tests/test-convert-bzr.t
--- a/tests/test-convert-bzr.t
+++ b/tests/test-convert-bzr.t
@@ -129,10 +129,10 @@  merge
   $ bzr branch -q source source-improve
   $ cd source
   $ echo more >> a
-  $ $PYTHON ../helper.py 'Editing a' 100
+  $ "$PYTHON" ../helper.py 'Editing a' 100
   $ cd ../source-improve
   $ echo content3 >> b
-  $ $PYTHON ../helper.py 'Editing b' 200
+  $ "$PYTHON" ../helper.py 'Editing b' 200
   $ cd ../source
   $ bzr merge -q ../source-improve
   $ bzr commit -q -m 'Merged improve branch'
diff --git a/tests/test-convert-clonebranches.t b/tests/test-convert-clonebranches.t
--- a/tests/test-convert-clonebranches.t
+++ b/tests/test-convert-clonebranches.t
@@ -42,7 +42,7 @@  Miss perl... sometimes
 convert
 
   $ hg convert -v --config convert.hg.clonebranches=1 source dest |
-  >     $PYTHON filter.py
+  >     "$PYTHON" filter.py
   3 adda
   2 changea
   1 addb
@@ -75,7 +75,7 @@  Add a merge with both parents and child 
 incremental conversion
 
   $ hg convert -v --config convert.hg.clonebranches=1 source dest |
-  >     $PYTHON filter.py
+  >     "$PYTHON" filter.py
   2 c1
   pulling from branch0 into branch1
   4 changesets found
diff --git a/tests/test-convert-git.t b/tests/test-convert-git.t
--- a/tests/test-convert-git.t
+++ b/tests/test-convert-git.t
@@ -420,7 +420,7 @@  test binary conversion (issue1359)
   $ mkdir git-repo3
   $ cd git-repo3
   $ git init-db >/dev/null 2>/dev/null
-  $ $PYTHON -c 'import struct; open("b", "wb").write(b"".join([struct.Struct(">B").pack(i) for i in range(256)])*16)'
+  $ "$PYTHON" -c 'import struct; open("b", "wb").write(b"".join([struct.Struct(">B").pack(i) for i in range(256)])*16)'
   $ git add b
   $ commit -a -m addbinary
   $ cd ..
@@ -437,7 +437,7 @@  convert binary file
   $ cd git-repo3-hg
   $ hg up -C
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON -c 'from __future__ import print_function; print(len(open("b", "rb").read()))'
+  $ "$PYTHON" -c 'from __future__ import print_function; print(len(open("b", "rb").read()))'
   4096
   $ cd ..
 
diff --git a/tests/test-convert-hg-source.t b/tests/test-convert-hg-source.t
--- a/tests/test-convert-hg-source.t
+++ b/tests/test-convert-hg-source.t
@@ -130,7 +130,7 @@  check shamap LF and CRLF handling
   >          for i, l in enumerate(open(sys.argv[1], 'rb'))]
   > open(sys.argv[1], 'wb').write(b''.join(lines))
   > EOF
-  $ $PYTHON rewrite.py new/.hg/shamap
+  $ "$PYTHON" rewrite.py new/.hg/shamap
   $ cd orig
   $ hg up -qC 1
   $ echo foo >> foo
diff --git a/tests/test-convert-hg-svn.t b/tests/test-convert-hg-svn.t
--- a/tests/test-convert-hg-svn.t
+++ b/tests/test-convert-hg-svn.t
@@ -12,9 +12,9 @@ 
 
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
   $ svnadmin create "$SVNREPOPATH"
diff --git a/tests/test-convert-mtn.t b/tests/test-convert-mtn.t
--- a/tests/test-convert-mtn.t
+++ b/tests/test-convert-mtn.t
@@ -43,7 +43,7 @@  create monotone repository
   $ mkdir dir
   $ echo b > dir/b
   $ echo d > dir/d
-  $ $PYTHON -c 'open("bin", "wb").write(b"a\\x00b") and None'
+  $ "$PYTHON" -c 'open("bin", "wb").write(b"a\\x00b") and None'
   $ echo c > c
   $ mtn add a dir/b dir/d c bin
   mtn: adding 'a' to workspace manifest
@@ -65,7 +65,7 @@  update monotone working directory
   $ echo b >> dir/b
   $ mtn drop c
   mtn: dropping 'c' from workspace manifest
-  $ $PYTHON -c 'open("bin", "wb").write(b"b\\x00c") and None'
+  $ "$PYTHON" -c 'open("bin", "wb").write(b"b\\x00c") and None'
   $ mtn ci -m update1
   mtn: beginning commit on branch 'com.selenic.test'
   mtn: committed revision 51d0a982464573a2a2cf5ee2c9219c652aaebeff
diff --git a/tests/test-convert-p4-filetypes.t b/tests/test-convert-p4-filetypes.t
--- a/tests/test-convert-p4-filetypes.t
+++ b/tests/test-convert-p4-filetypes.t
@@ -52,7 +52,7 @@  not testing these
   >          p4 add -t $T file_$T2
   >          ;;
   >       binary*)
-  >          $PYTHON -c "open('file_$T2', 'wb').write(b'this is $T')"
+  >          "$PYTHON" -c "open('file_$T2', 'wb').write(b'this is $T')"
   >          p4 add -t $T file_$T2
   >          ;;
   >       *)
diff --git a/tests/test-convert-svn-move.t b/tests/test-convert-svn-move.t
--- a/tests/test-convert-svn-move.t
+++ b/tests/test-convert-svn-move.t
@@ -9,9 +9,9 @@ 
   $ svnadmin load -q svn-repo < "$TESTDIR/svn/move.svndump"
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
 Convert trunk and branches
diff --git a/tests/test-convert-svn-sink.t b/tests/test-convert-svn-sink.t
--- a/tests/test-convert-svn-sink.t
+++ b/tests/test-convert-svn-sink.t
@@ -10,7 +10,7 @@ 
   >        if [ $2 -gt 0 ]; then
   >            limit="--limit=$2"
   >        fi
-  >        svn log --xml -v $limit | $PYTHON "$TESTDIR/svnxml.py"
+  >        svn log --xml -v $limit | "$PYTHON" "$TESTDIR/svnxml.py"
   >     )
   > }
 
diff --git a/tests/test-convert-svn-source.t b/tests/test-convert-svn-source.t
--- a/tests/test-convert-svn-source.t
+++ b/tests/test-convert-svn-source.t
@@ -14,9 +14,9 @@ 
   $ svnadmin create svn-repo
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
   $ INVALIDREVISIONID=svn:x2147622-4a9f-4db4-a8d3-13562ff547b2/proj%20B/mytrunk@1
   $ VALIDREVISIONID=svn:a2147622-4a9f-4db4-a8d3-13562ff547b2/proj%20B/mytrunk/mytrunk@1
diff --git a/tests/test-convert.t b/tests/test-convert.t
--- a/tests/test-convert.t
+++ b/tests/test-convert.t
@@ -482,7 +482,7 @@  converting empty dir should fail "nicely
 override $PATH to ensure p4 not visible; use $PYTHON in case we're
 running from a devel copy, not a temp installation
 
-  $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
+  $ PATH="$BINDIR" "$PYTHON" "$BINDIR"/hg convert emptydir
   assuming destination emptydir-hg
   initializing destination emptydir-hg repository
   emptydir does not look like a CVS checkout
diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t
--- a/tests/test-debugcommands.t
+++ b/tests/test-debugcommands.t
@@ -544,7 +544,7 @@  Test internal debugstacktrace command
   >     util.dst('hi ...\\nfrom h hidden in g', 1, depth=2)
   > f()
   > EOF
-  $ $PYTHON debugstacktrace.py
+  $ "$PYTHON" debugstacktrace.py
   stacktrace at:
    debugstacktrace.py:12 in * (glob)
    debugstacktrace.py:5  in f
diff --git a/tests/test-diff-binary-file.t b/tests/test-diff-binary-file.t
--- a/tests/test-diff-binary-file.t
+++ b/tests/test-diff-binary-file.t
@@ -83,7 +83,7 @@  Test text mode with extended git-style d
   > path = sys.argv[1]
   > open(path, 'wb').write(b'\x00\x01\x02\x03')
   > EOF
-  $ $PYTHON writebin.py binfile.bin
+  $ "$PYTHON" writebin.py binfile.bin
   $ hg add binfile.bin
   $ hg ci -m 'add binfile.bin'
 
diff --git a/tests/test-diff-color.t b/tests/test-diff-color.t
--- a/tests/test-diff-color.t
+++ b/tests/test-diff-color.t
@@ -396,12 +396,12 @@  test inline color diff
 
 multibyte character shouldn't be broken up in word diff:
 
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > with open("utf8", "wb") as f:
   >     f.write(b"blah \xe3\x82\xa2 blah\n")
   > EOF
   $ hg ci -Am 'add utf8 char' utf8
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > with open("utf8", "wb") as f:
   >     f.write(b"blah \xe3\x82\xa4 blah\n")
   > EOF
diff --git a/tests/test-diff-newlines.t b/tests/test-diff-newlines.t
--- a/tests/test-diff-newlines.t
+++ b/tests/test-diff-newlines.t
@@ -1,6 +1,6 @@ 
   $ hg init
 
-  $ $PYTHON -c 'open("a", "wb").write(b"confuse str.splitlines\nembedded\rnewline\n")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"confuse str.splitlines\nembedded\rnewline\n")'
   $ hg ci -Ama -d '1 0'
   adding a
 
diff --git a/tests/test-diff-upgrade.t b/tests/test-diff-upgrade.t
--- a/tests/test-diff-upgrade.t
+++ b/tests/test-diff-upgrade.t
@@ -16,7 +16,7 @@  make a combination of new, changed and d
 
   $ echo regular > regular
   $ echo rmregular > rmregular
-  $ $PYTHON -c "open('bintoregular', 'wb').write(b'\0')"
+  $ "$PYTHON" -c "open('bintoregular', 'wb').write(b'\0')"
   $ touch rmempty
   $ echo exec > exec
   $ chmod +x exec
@@ -26,7 +26,7 @@  make a combination of new, changed and d
   $ echo unsetexec > unsetexec
   $ chmod +x unsetexec
   $ echo binary > binary
-  $ $PYTHON -c "open('rmbinary', 'wb').write(b'\0')"
+  $ "$PYTHON" -c "open('rmbinary', 'wb').write(b'\0')"
   $ hg ci -Am addfiles
   adding binary
   adding bintoregular
@@ -50,8 +50,8 @@  make a combination of new, changed and d
   $ rm rmexec
   $ chmod +x setexec
   $ chmod -x unsetexec
-  $ $PYTHON -c "open('binary', 'wb').write(b'\0\0')"
-  $ $PYTHON -c "open('newbinary', 'wb').write(b'\0')"
+  $ "$PYTHON" -c "open('binary', 'wb').write(b'\0\0')"
+  $ "$PYTHON" -c "open('newbinary', 'wb').write(b'\0')"
   $ rm rmbinary
   $ hg addremove -s 0
   adding newbinary
diff --git a/tests/test-encoding-align.t b/tests/test-encoding-align.t
--- a/tests/test-encoding-align.t
+++ b/tests/test-encoding-align.t
@@ -4,7 +4,7 @@  Test alignment of multibyte characters
   $ export HGENCODING
   $ hg init t
   $ cd t
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > # (byte, width) = (6, 4)
   > s = b"\xe7\x9f\xad\xe5\x90\x8d"
   > # (byte, width) = (7, 7): odd width is good for alignment test
diff --git a/tests/test-encoding.t b/tests/test-encoding.t
--- a/tests/test-encoding.t
+++ b/tests/test-encoding.t
@@ -14,7 +14,7 @@  we need a repo with some legacy latin-1 
   (run 'hg update' to get a working copy)
   $ hg co
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > f = open('latin-1', 'wb'); f.write(b"latin-1 e' encoded: \xe9"); f.close()
   > f = open('utf-8', 'wb'); f.write(b"utf-8 e' encoded: \xc3\xa9"); f.close()
   > f = open('latin-1-tag', 'wb'); f.write(b"\xe9"); f.close()
diff --git a/tests/test-eol.t b/tests/test-eol.t
--- a/tests/test-eol.t
+++ b/tests/test-eol.t
@@ -73,7 +73,7 @@  Set up helpers
   >     echo '% a.txt'
   >     cat a.txt
   >     hg diff
-  >     $PYTHON ../switch-eol.py $1 a.txt
+  >     "$PYTHON" ../switch-eol.py $1 a.txt
   >     echo '% hg diff only reports a single changed line:'
   >     hg diff
   >     echo "% reverting back to $1 format"
diff --git a/tests/test-extdiff.t b/tests/test-extdiff.t
--- a/tests/test-extdiff.t
+++ b/tests/test-extdiff.t
@@ -265,7 +265,7 @@  and start tool
 
 #if windows
   $ cat > 'diff tool.bat' << EOF
-  > @$PYTHON "`pwd`/diff tool.py"
+  > @"$PYTHON" "`pwd`/diff tool.py"
   > EOF
   $ hg extdiff -p "`pwd`/diff tool.bat"
   [1]
diff --git a/tests/test-extension.t b/tests/test-extension.t
--- a/tests/test-extension.t
+++ b/tests/test-extension.t
@@ -145,7 +145,7 @@  Check hgweb's load order of extensions a
   > EOF
   $ . "$TESTDIR/cgienv"
 
-  $ PATH_INFO='/' SCRIPT_NAME='' $PYTHON hgweb.cgi \
+  $ PATH_INFO='/' SCRIPT_NAME='' "$PYTHON" hgweb.cgi \
   >    | grep '^[0-9]) ' # ignores HTML output
   1) foo imported
   1) bar imported
@@ -164,7 +164,7 @@  Check hgweb's load order of extensions a
   $ PATH_INFO='/shortlog'
 #endif
   $ export PATH_INFO
-  $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' $PYTHON hgweb.cgi \
+  $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' "$PYTHON" hgweb.cgi \
   >     | grep '<a href="/rev/[0-9a-z]*">'
      <a href="/rev/c24b9ac61126">add file</a>
 
diff --git a/tests/test-fastannotate-protocol.t b/tests/test-fastannotate-protocol.t
--- a/tests/test-fastannotate-protocol.t
+++ b/tests/test-fastannotate-protocol.t
@@ -1,6 +1,6 @@ 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > [extensions]
   > fastannotate=
   > [fastannotate]
diff --git a/tests/test-fileset-generated.t b/tests/test-fileset-generated.t
--- a/tests/test-fileset-generated.t
+++ b/tests/test-fileset-generated.t
@@ -2,15 +2,15 @@ 
 
 Set up history and working copy
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove -q --similarity 0
   $ hg commit -m first
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove -q --similarity 0
   $ hg commit -m second
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*-untracked
   $ rm *_*_missing-*
diff --git a/tests/test-fix-topology.t b/tests/test-fix-topology.t
--- a/tests/test-fix-topology.t
+++ b/tests/test-fix-topology.t
@@ -9,7 +9,7 @@  A script that implements uppercasing all
   > sys.stdout.write(sys.stdin.read().upper())
   > EOF
   $ TESTLINES="foo\nbar\nbaz\n"
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
   FOO
   BAR
   BAZ
@@ -22,7 +22,7 @@  relationships. We indicate fixed file co
   > [extensions]
   > fix =
   > [fix]
-  > uppercase-whole-file:command=$PYTHON $UPPERCASEPY
+  > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY
   > uppercase-whole-file:fileset=set:**
   > EOF
 
diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -22,32 +22,32 @@  approximates the behavior of code format
   >     sys.stdout.write(line)
   > EOF
   $ TESTLINES="foo\nbar\nbaz\nqux\n"
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
   foo
   bar
   baz
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY all
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY all
   FOO
   BAR
   BAZ
   QUX
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-1
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-1
   FOO
   bar
   baz
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-2
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-2
   FOO
   BAR
   baz
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-3
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-3
   foo
   BAR
   BAZ
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-2 4-4
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-2 4-4
   foo
   BAR
   baz
@@ -65,9 +65,9 @@  choose which behavior to use by naming f
   > evolution.createmarkers=True
   > evolution.allowunstable=True
   > [fix]
-  > uppercase-whole-file:command=$PYTHON $UPPERCASEPY all
+  > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all
   > uppercase-whole-file:fileset=set:**.whole
-  > uppercase-changed-lines:command=$PYTHON $UPPERCASEPY
+  > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
   > uppercase-changed-lines:linerange={first}-{last}
   > uppercase-changed-lines:fileset=set:**.changed
   > EOF
diff --git a/tests/test-gendoc.t b/tests/test-gendoc.t
--- a/tests/test-gendoc.t
+++ b/tests/test-gendoc.t
@@ -8,7 +8,7 @@  Test document extraction
   $ { echo C; ls "$TESTDIR/../i18n"/*.po | sort; } | while read PO; do
   >     LOCALE=`basename "$PO" .po`
   >     echo "% extracting documentation from $LOCALE"
-  >     LANGUAGE=$LOCALE $PYTHON "$TESTDIR/../doc/gendoc.py" >> gendoc-$LOCALE.txt 2> /dev/null || exit
+  >     LANGUAGE=$LOCALE "$PYTHON" "$TESTDIR/../doc/gendoc.py" >> gendoc-$LOCALE.txt 2> /dev/null || exit
   > 
   >     if [ $LOCALE != C ]; then
   >         if [ ! -f $TESTDIR/test-gendoc-$LOCALE.t ]; then
diff --git a/tests/test-glog-beautifygraph.t b/tests/test-glog-beautifygraph.t
--- a/tests/test-glog-beautifygraph.t
+++ b/tests/test-glog-beautifygraph.t
@@ -1809,7 +1809,7 @@  Test multiple --include/--exclude/paths
 
 Test glob expansion of pats
 
-  $ expandglobs=`$PYTHON -c "import mercurial.util; \
+  $ expandglobs=`"$PYTHON" -c "import mercurial.util; \
   >   print(mercurial.util.expandglobs and 'true' or 'false')"`
   $ if [ $expandglobs = "true" ]; then
   >    testlog 'a*';
diff --git a/tests/test-glog.t b/tests/test-glog.t
--- a/tests/test-glog.t
+++ b/tests/test-glog.t
@@ -1659,7 +1659,7 @@  Test multiple --include/--exclude/paths
 
 Test glob expansion of pats
 
-  $ expandglobs=`$PYTHON -c "import mercurial.util; \
+  $ expandglobs=`"$PYTHON" -c "import mercurial.util; \
   >   print(mercurial.util.expandglobs and 'true' or 'false')"`
   $ if [ $expandglobs = "true" ]; then
   >    testlog 'a*';
diff --git a/tests/test-grep.t b/tests/test-grep.t
--- a/tests/test-grep.t
+++ b/tests/test-grep.t
@@ -300,7 +300,7 @@  test substring match: '^' should only ma
 
 match in last "line" without newline
 
-  $ $PYTHON -c 'fp = open("noeol", "wb"); fp.write(b"no infinite loop"); fp.close();'
+  $ "$PYTHON" -c 'fp = open("noeol", "wb"); fp.write(b"no infinite loop"); fp.close();'
   $ hg ci -Amnoeol
   adding noeol
   $ hg grep -r tip:0 loop
diff --git a/tests/test-hardlinks.t b/tests/test-hardlinks.t
--- a/tests/test-hardlinks.t
+++ b/tests/test-hardlinks.t
@@ -11,7 +11,7 @@ 
 
   $ nlinksdir()
   > {
-  >     find "$@" -type f | $PYTHON $TESTTMP/nlinks.py
+  >     find "$@" -type f | "$PYTHON" $TESTTMP/nlinks.py
   > }
 
 Some implementations of cp can't create hardlinks (replaces 'cp -al' on Linux):
@@ -25,7 +25,7 @@  Some implementations of cp can't create 
 
   $ linkcp()
   > {
-  >     $PYTHON $TESTTMP/linkcp.py $1 $2
+  >     "$PYTHON" $TESTTMP/linkcp.py $1 $2
   > }
 
 Prepare repo r1:
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -1772,7 +1772,7 @@  replacement makes message meaningless.
 This tests that section lookup by translated string isn't broken by
 such str.lower().
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > def escape(s):
   >     return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
   > # translation of "record" in ja_JP.cp932
@@ -1806,7 +1806,7 @@  such str.lower().
   > ambiguous = ./ambiguous.py
   > EOF
 
-  $ $PYTHON <<EOF | sh
+  $ "$PYTHON" <<EOF | sh
   > upper = "\x8bL\x98^"
   > print("hg --encoding cp932 help -e ambiguous.%s" % upper)
   > EOF
@@ -1816,7 +1816,7 @@  such str.lower().
   Upper name should show only this message
   
 
-  $ $PYTHON <<EOF | sh
+  $ "$PYTHON" <<EOF | sh
   > lower = "\x8bl\x98^"
   > print("hg --encoding cp932 help -e ambiguous.%s" % lower)
   > EOF
@@ -2026,7 +2026,7 @@  Compression engines listed in `hg help b
 Test usage of section marks in help documents
 
   $ cd "$TESTDIR"/../doc
-  $ $PYTHON check-seclevel.py
+  $ "$PYTHON" check-seclevel.py
   $ cd $TESTTMP
 
 #if serve
diff --git a/tests/test-hghave.t b/tests/test-hghave.t
--- a/tests/test-hghave.t
+++ b/tests/test-hghave.t
@@ -22,7 +22,7 @@  Testing hghave extensibility for third p
   > EOF
   $ ( \
   > testrepohgenv; \
-  > $PYTHON $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE test-hghaveaddon.t \
+  > "$PYTHON" $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE test-hghaveaddon.t \
   > )
   .
   # Ran 1 tests, 0 skipped, 0 failed.
diff --git a/tests/test-hgignore.t b/tests/test-hgignore.t
--- a/tests/test-hgignore.t
+++ b/tests/test-hgignore.t
@@ -19,7 +19,7 @@  Issue562: .hgignore requires newline at 
   > f.close()
   > EOF
 
-  $ $PYTHON makeignore.py
+  $ "$PYTHON" makeignore.py
 
 Should display baz only:
 
diff --git a/tests/test-hgrc.t b/tests/test-hgrc.t
--- a/tests/test-hgrc.t
+++ b/tests/test-hgrc.t
@@ -58,7 +58,7 @@  issue1829: wrong indentation
   unexpected leading whitespace
   [255]
 
-  $ $PYTHON -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n  de\n fg \nbaz = bif cb \n')" \
+  $ "$PYTHON" -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n  de\n fg \nbaz = bif cb \n')" \
   > > $HGRC
   $ hg showconfig foo
   foo.bar=a\nb\nc\nde\nfg
diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t
+++ b/tests/test-hgweb-commands.t
@@ -2282,7 +2282,7 @@  bookmarks view doesn't choke on bookmark
   $ . "$TESTDIR/cgienv"
   $ PATH_INFO=/bookmarks; export PATH_INFO
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi | grep -v ETag:
+  $ "$PYTHON" hgweb.cgi | grep -v ETag:
   Status: 200 Script output follows\r (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
   \r (esc)
@@ -2291,7 +2291,7 @@  listbookmarks hides secret bookmarks
 
   $ PATH_INFO=/; export PATH_INFO
   $ QUERY_STRING='cmd=listkeys&namespace=bookmarks'
-  $ $PYTHON hgweb.cgi
+  $ "$PYTHON" hgweb.cgi
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 0\r (esc)
@@ -2301,7 +2301,7 @@  search works with filtering
 
   $ PATH_INFO=/log; export PATH_INFO
   $ QUERY_STRING='rev=babar'
-  $ $PYTHON hgweb.cgi > search
+  $ "$PYTHON" hgweb.cgi > search
   $ grep Status search
   Status: 200 Script output follows\r (esc)
 
@@ -2309,7 +2309,7 @@  summary works with filtering (issue3810)
 
   $ PATH_INFO=/summary; export PATH_INFO
   $ QUERY_STRING='style=monoblue'; export QUERY_STRING
-  $ $PYTHON hgweb.cgi > summary.out
+  $ "$PYTHON" hgweb.cgi > summary.out
   $ grep "^Status" summary.out
   Status: 200 Script output follows\r (esc)
 
@@ -2320,7 +2320,7 @@  proper status for filtered revision
 
   $ PATH_INFO=/rev/5; export PATH_INFO
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi #> search
+  $ "$PYTHON" hgweb.cgi #> search
   Status: 404 Not Found\r (esc)
   ETag: W/"*"\r (glob) (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
@@ -2334,7 +2334,7 @@  proper status for filtered revision
 
   $ PATH_INFO=/rev/4; export PATH_INFO
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi #> search
+  $ "$PYTHON" hgweb.cgi #> search
   Status: 404 Not Found\r (esc)
   ETag: W/"*"\r (glob) (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
@@ -2362,11 +2362,11 @@  filtered '0' changeset
   $ hg phase --force --secret 0
   $ PATH_INFO=/graph/; export PATH_INFO
   $ QUERY_STRING=''
-  $ $PYTHON hgweb.cgi | grep Status
+  $ "$PYTHON" hgweb.cgi | grep Status
   Status: 200 Script output follows\r (esc)
 (check rendered revision)
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi | grep -v ETag
+  $ "$PYTHON" hgweb.cgi | grep -v ETag
   Status: 200 Script output follows\r (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
   \r (esc)
diff --git a/tests/test-hgweb-json.t b/tests/test-hgweb-json.t
--- a/tests/test-hgweb-json.t
+++ b/tests/test-hgweb-json.t
@@ -2196,7 +2196,7 @@  Error page shouldn't crash
 Commit message with Japanese Kanji 'Noh', which ends with '\x5c'
 
   $ echo foo >> da/foo
-  $ HGENCODING=cp932 hg ci -m `$PYTHON -c 'print("\x94\x5c")'`
+  $ HGENCODING=cp932 hg ci -m `"$PYTHON" -c 'print("\x94\x5c")'`
 
 Commit message with null character
 
diff --git a/tests/test-hgweb-no-path-info.t b/tests/test-hgweb-no-path-info.t
--- a/tests/test-hgweb-no-path-info.t
+++ b/tests/test-hgweb-no-path-info.t
@@ -70,7 +70,7 @@  should be used from d74fc8dec2b4 onward 
   > env['QUERY_STRING'] = 'style=raw'
   > process(hgwebdir({b'repo': b'.'}))
   > EOF
-  $ $PYTHON request.py
+  $ "$PYTHON" request.py
   ---- STATUS
   200 Script output follows
   ---- HEADERS
diff --git a/tests/test-hgweb-no-request-uri.t b/tests/test-hgweb-no-request-uri.t
--- a/tests/test-hgweb-no-request-uri.t
+++ b/tests/test-hgweb-no-request-uri.t
@@ -81,7 +81,7 @@  should be used from d74fc8dec2b4 onward 
   > env['QUERY_STRING'] = 'style=raw'
   > process(hgwebdir({b'repo': b'.'}))
   > EOF
-  $ $PYTHON request.py
+  $ "$PYTHON" request.py
   ---- STATUS
   200 Script output follows
   ---- HEADERS
diff --git a/tests/test-hgweb-non-interactive.t b/tests/test-hgweb-non-interactive.t
--- a/tests/test-hgweb-non-interactive.t
+++ b/tests/test-hgweb-non-interactive.t
@@ -76,7 +76,7 @@  by the WSGI standard and strictly implem
   > with i._obtainrepo() as repo:
   >     print(sorted([x for x in repo.ui.environ if x.startswith(b'wsgi')]))
   > EOF
-  $ $PYTHON request.py
+  $ "$PYTHON" request.py
   ---- STATUS
   200 Script output follows
   ---- HEADERS
diff --git a/tests/test-hgweb.t b/tests/test-hgweb.t
--- a/tests/test-hgweb.t
+++ b/tests/test-hgweb.t
@@ -329,7 +329,7 @@  stop and restart
 
 Test the access/error files are opened in append mode
 
-  $ $PYTHON -c "from __future__ import print_function; print(len(open('access.log', 'rb').readlines()), 'log lines written')"
+  $ "$PYTHON" -c "from __future__ import print_function; print(len(open('access.log', 'rb').readlines()), 'log lines written')"
   14 log lines written
 
 static file
diff --git a/tests/test-highlight.t b/tests/test-highlight.t
--- a/tests/test-highlight.t
+++ b/tests/test-highlight.t
@@ -947,7 +947,7 @@  errors encountered
   $ cd ..
   $ hg init eucjp
   $ cd eucjp
-  $ $PYTHON -c 'print("\265\376")' >> eucjp.txt  # Japanese kanji "Kyo"
+  $ "$PYTHON" -c 'print("\265\376")' >> eucjp.txt  # Japanese kanji "Kyo"
   $ hg ci -Ama
   adding eucjp.txt
   $ hgserveget () {
diff --git a/tests/test-histedit-arguments.t b/tests/test-histedit-arguments.t
--- a/tests/test-histedit-arguments.t
+++ b/tests/test-histedit-arguments.t
@@ -279,7 +279,7 @@  short hash. This tests issue3893.
 Test that trimming description using multi-byte characters
 --------------------------------------------------------------------
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > fp = open('logfile', 'wb')
   > fp.write(b'12345678901234567890123456789012345678901234567890' +
   >          b'12345') # there are 5 more columns for 80 columns
diff --git a/tests/test-i18n.t b/tests/test-i18n.t
--- a/tests/test-i18n.t
+++ b/tests/test-i18n.t
@@ -45,8 +45,8 @@  Check Mercurial specific translation pro
 tool itself by doctest
 
   $ cd "$TESTDIR"/../i18n
-  $ $PYTHON check-translation.py *.po
-  $ $PYTHON check-translation.py --doctest
+  $ "$PYTHON" check-translation.py *.po
+  $ "$PYTHON" check-translation.py --doctest
   $ cd $TESTTMP
 
 #if gettext
diff --git a/tests/test-impexp-branch.t b/tests/test-impexp-branch.t
--- a/tests/test-impexp-branch.t
+++ b/tests/test-impexp-branch.t
@@ -32,12 +32,12 @@ 
   $ hg export 1 > ../r1.patch
   $ cd ..
 
-  $ if $PYTHON findbranch.py < r0.patch; then
+  $ if "$PYTHON" findbranch.py < r0.patch; then
   >     echo "Export of default branch revision has Branch header" 1>&2
   >     exit 1
   > fi
 
-  $ if $PYTHON findbranch.py < r1.patch; then
+  $ if "$PYTHON" findbranch.py < r1.patch; then
   >     :  # Do nothing
   > else
   >     echo "Export of branch revision is missing Branch header" 1>&2
diff --git a/tests/test-import-bypass.t b/tests/test-import-bypass.t
--- a/tests/test-import-bypass.t
+++ b/tests/test-import-bypass.t
@@ -227,7 +227,7 @@  Test patch.eol is handled
 (this also tests that editor is not invoked for '--bypass', if the
 commit message is explicitly specified, regardless of '--edit')
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\r\n")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\r\n")'
   $ hg ci -m makeacrlf
   $ HGEDITOR=cat hg import -m 'should fail because of eol' --edit --bypass ../test.diff
   applying ../test.diff
diff --git a/tests/test-import-context.t b/tests/test-import-context.t
--- a/tests/test-import-context.t
+++ b/tests/test-import-context.t
@@ -26,10 +26,10 @@  Initialize the test repository
 
   $ hg init repo
   $ cd repo
-  $ $PYTHON ../writepatterns.py a 0 5A 1B 5C 1D
-  $ $PYTHON ../writepatterns.py b 1 1A 1B
-  $ $PYTHON ../writepatterns.py c 1 5A
-  $ $PYTHON ../writepatterns.py d 1 5A 1B
+  $ "$PYTHON" ../writepatterns.py a 0 5A 1B 5C 1D
+  $ "$PYTHON" ../writepatterns.py b 1 1A 1B
+  $ "$PYTHON" ../writepatterns.py c 1 5A
+  $ "$PYTHON" ../writepatterns.py d 1 5A 1B
   $ hg add
   adding a
   adding b
@@ -114,13 +114,13 @@  Add file, missing a last end of line
 
 What's in a
 
-  $ $PYTHON ../cat.py a
+  $ "$PYTHON" ../cat.py a
   'A\nA\nA\nA\nA\nE\nC\nC\nC\nC\nC\nF\nF\n'
-  $ $PYTHON ../cat.py newnoeol
+  $ "$PYTHON" ../cat.py newnoeol
   'a\nb'
-  $ $PYTHON ../cat.py c
+  $ "$PYTHON" ../cat.py c
   'A\nA\nA\nA\nA\nB\nB\n'
-  $ $PYTHON ../cat.py d
+  $ "$PYTHON" ../cat.py d
   'A\nA\nA\nA\n'
 
   $ cd ..
diff --git a/tests/test-import-eol.t b/tests/test-import-eol.t
--- a/tests/test-import-eol.t
+++ b/tests/test-import-eol.t
@@ -29,14 +29,14 @@ 
 
 Test different --eol values
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\nbbb\ncc\n\nd\ne")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\nbbb\ncc\n\nd\ne")'
   $ hg ci -Am adda
   adding .hgignore
   adding a
-  $ $PYTHON ../makepatch.py empty:lf eol.diff
-  $ $PYTHON ../makepatch.py empty:crlf eol-empty-crlf.diff
-  $ $PYTHON ../makepatch.py empty:stripped-lf eol-empty-stripped-lf.diff
-  $ $PYTHON ../makepatch.py empty:stripped-crlf eol-empty-stripped-crlf.diff
+  $ "$PYTHON" ../makepatch.py empty:lf eol.diff
+  $ "$PYTHON" ../makepatch.py empty:crlf eol-empty-crlf.diff
+  $ "$PYTHON" ../makepatch.py empty:stripped-lf eol-empty-stripped-lf.diff
+  $ "$PYTHON" ../makepatch.py empty:stripped-crlf eol-empty-stripped-crlf.diff
 
 invalid eol
 
@@ -116,7 +116,7 @@  auto EOL on LF file
 
 auto EOL on CRLF file
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\r\nbbb\r\ncc\r\n\r\nd\r\ne")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\r\nbbb\r\ncc\r\n\r\nd\r\ne")'
   $ hg commit -m 'switch EOLs in a'
   $ hg --traceback --config patch.eol='auto' import eol.diff
   applying eol.diff
@@ -132,11 +132,11 @@  auto EOL on CRLF file
 
 auto EOL on new file or source without any EOL
 
-  $ $PYTHON -c 'open("noeol", "wb").write(b"noeol")'
+  $ "$PYTHON" -c 'open("noeol", "wb").write(b"noeol")'
   $ hg add noeol
   $ hg commit -m 'add noeol'
-  $ $PYTHON -c 'open("noeol", "wb").write(b"noeol\r\nnoeol\n")'
-  $ $PYTHON -c 'open("neweol", "wb").write(b"neweol\nneweol\r\n")'
+  $ "$PYTHON" -c 'open("noeol", "wb").write(b"noeol\r\nnoeol\n")'
+  $ "$PYTHON" -c 'open("neweol", "wb").write(b"neweol\nneweol\r\n")'
   $ hg add neweol
   $ hg diff --git > noeol.diff
   $ hg revert --no-backup noeol neweol
@@ -154,10 +154,10 @@  auto EOL on new file or source without a
 
 Test --eol and binary patches
 
-  $ $PYTHON -c 'open("b", "wb").write(b"a\x00\nb\r\nd")'
+  $ "$PYTHON" -c 'open("b", "wb").write(b"a\x00\nb\r\nd")'
   $ hg ci -Am addb
   adding b
-  $ $PYTHON -c 'open("b", "wb").write(b"a\x00\nc\r\nd")'
+  $ "$PYTHON" -c 'open("b", "wb").write(b"a\x00\nc\r\nd")'
   $ hg diff --git > bin.diff
   $ hg revert --no-backup b
 
diff --git a/tests/test-import.t b/tests/test-import.t
--- a/tests/test-import.t
+++ b/tests/test-import.t
@@ -305,7 +305,7 @@  plain diff in email, subject, message bo
   new changesets 80971e65b431
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON mkmsg.py diffed-tip.patch msg.patch
+  $ "$PYTHON" mkmsg.py diffed-tip.patch msg.patch
   $ hg --cwd b import ../msg.patch
   applying ../msg.patch
   $ hg --cwd b tip | grep email
@@ -371,7 +371,7 @@  hg export in email, should use patch hea
   new changesets 80971e65b431
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON mkmsg.py exported-tip.patch msg.patch
+  $ "$PYTHON" mkmsg.py exported-tip.patch msg.patch
   $ cat msg.patch | hg --cwd b import -
   applying patch from stdin
   $ hg --cwd b tip | grep second
@@ -403,7 +403,7 @@  plain diff in email, [PATCH] subject, me
   new changesets 80971e65b431
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON mkmsg2.py diffed-tip.patch msg.patch
+  $ "$PYTHON" mkmsg2.py diffed-tip.patch msg.patch
   $ cat msg.patch | hg --cwd b import -
   applying patch from stdin
   $ hg --cwd b tip --template '{desc}\n'
@@ -865,7 +865,7 @@  Test importing a patch ending with a bin
   $ hg init binaryremoval
   $ cd binaryremoval
   $ echo a > a
-  $ $PYTHON -c "open('b', 'wb').write(b'a\x00b')"
+  $ "$PYTHON" -c "open('b', 'wb').write(b'a\x00b')"
   $ hg ci -Am addall
   adding a
   adding b
diff --git a/tests/test-imports-checker.t b/tests/test-imports-checker.t
--- a/tests/test-imports-checker.t
+++ b/tests/test-imports-checker.t
@@ -8,7 +8,7 @@  Run the doctests from the import checker
 it's working correctly.
   $ TERM=dumb
   $ export TERM
-  $ $PYTHON -m doctest $import_checker
+  $ "$PYTHON" -m doctest $import_checker
 
 Run additional tests for the import checker
 
@@ -136,7 +136,7 @@  Run additional tests for the import chec
   > from . import errors
   > EOF
 
-  $ $PYTHON "$import_checker" testpackage*/*.py testpackage/subpackage/*.py \
+  $ "$PYTHON" "$import_checker" testpackage*/*.py testpackage/subpackage/*.py \
   >   email/*.py
   testpackage/importalias.py:2: ui module must be "as" aliased to uimod
   testpackage/importfromalias.py:2: ui from testpackage must be "as" aliased to uimod
diff --git a/tests/test-inherit-mode.t b/tests/test-inherit-mode.t
--- a/tests/test-inherit-mode.t
+++ b/tests/test-inherit-mode.t
@@ -48,7 +48,7 @@  before commit
 store can be written by the group, other files cannot
 store is setgid
 
-  $ $PYTHON ../printmodes.py .
+  $ "$PYTHON" ../printmodes.py .
   00700 ./.hg/
   00600 ./.hg/00changelog.i
   00600 ./.hg/requires
@@ -64,7 +64,7 @@  files created in .hg can be written by t
 (in particular, store/**, dirstate, branch cache file, undo files)
 new directories are setgid
 
-  $ $PYTHON ../printmodes.py .
+  $ "$PYTHON" ../printmodes.py .
   00700 ./.hg/
   00600 ./.hg/00changelog.i
   00770 ./.hg/cache/
@@ -109,7 +109,7 @@  new directories are setgid
 before push
 group can write everything
 
-  $ $PYTHON ../printmodes.py ../push
+  $ "$PYTHON" ../printmodes.py ../push
   00770 ../push/.hg/
   00660 ../push/.hg/00changelog.i
   00660 ../push/.hg/requires
@@ -121,7 +121,7 @@  group can write everything
 after push
 group can still write everything
 
-  $ $PYTHON ../printmodes.py ../push
+  $ "$PYTHON" ../printmodes.py ../push
   00770 ../push/.hg/
   00660 ../push/.hg/00changelog.i
   00770 ../push/.hg/cache/
@@ -163,8 +163,8 @@  just check that directories have the sam
   $ mkdir dir
   $ touch dir/file
   $ hg ci -qAm 'add dir/file'
-  $ storemode=`$PYTHON ../mode.py .hg/store`
-  $ dirmode=`$PYTHON ../mode.py .hg/store/data/dir`
+  $ storemode=`"$PYTHON" ../mode.py .hg/store`
+  $ dirmode=`"$PYTHON" ../mode.py .hg/store/data/dir`
   $ if [ "$storemode" != "$dirmode" ]; then
   >  echo "$storemode != $dirmode"
   > fi
diff --git a/tests/test-install.t b/tests/test-install.t
--- a/tests/test-install.t
+++ b/tests/test-install.t
@@ -205,7 +205,7 @@  not found (this is intentionally using b
   >     print('  %s' % f)
   > EOF
 
-  $ ( testrepohgenv; $PYTHON wixxml.py help )
+  $ ( testrepohgenv; "$PYTHON" wixxml.py help )
   Not installed:
     help/common.txt
     help/hg-ssh.8.txt
@@ -214,7 +214,7 @@  not found (this is intentionally using b
     help/hgrc.5.txt
   Not tracked:
 
-  $ ( testrepohgenv; $PYTHON wixxml.py templates )
+  $ ( testrepohgenv; "$PYTHON" wixxml.py templates )
   Not installed:
   Not tracked:
 
@@ -231,7 +231,7 @@  Note: --no-site-packages is deprecated, 
 ancient virtualenv from their linux distro or similar and it's not yet
 the default for them.
   $ unset PYTHONPATH
-  $ $PYTHON -m virtualenv --no-site-packages --never-download installenv >> pip.log
+  $ "$PYTHON" -m virtualenv --no-site-packages --never-download installenv >> pip.log
 Note: we use this weird path to run pip and hg to avoid platform differences,
 since it's bin on most platforms but Scripts on Windows.
   $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log
diff --git a/tests/test-issue4074.t b/tests/test-issue4074.t
--- a/tests/test-issue4074.t
+++ b/tests/test-issue4074.t
@@ -16,12 +16,12 @@  A script to generate nasty diff worst-ca
 
 Check in a big file:
 
-  $ $PYTHON ../s.py > a
+  $ "$PYTHON" ../s.py > a
   $ hg ci -qAm0
 
 Modify it:
 
-  $ $PYTHON ../s.py > a
+  $ "$PYTHON" ../s.py > a
 
 Time a check-in, should never take more than 10 seconds user time:
 
diff --git a/tests/test-largefiles-misc.t b/tests/test-largefiles-misc.t
--- a/tests/test-largefiles-misc.t
+++ b/tests/test-largefiles-misc.t
@@ -1095,7 +1095,7 @@  largefiles (issue4547)
 Move (and then undo) a directory move with only largefiles.
 
   $ cd subrepo-root
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir/
@@ -1110,7 +1110,7 @@  Move (and then undo) a directory move wi
   $ hg mv dir/subdir dir/subdir2
   moving .hglf/dir/subdir/large.bin to .hglf/dir/subdir2/large.bin
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir2/
@@ -1150,7 +1150,7 @@  The content of the forgotten file should
 
 The standin for subdir2 should be deleted, not just dropped
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir/
@@ -1177,7 +1177,7 @@  existed under .hglf/.
   R dir/subdir/large.bin
   ? large.orig
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir2/
@@ -1202,7 +1202,7 @@  Start from scratch, and rename something
     dir/subdir/large.bin
   R dir/subdir/large.bin
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir2/
   .hglf/dir2/subdir/
@@ -1221,7 +1221,7 @@  Start from scratch, and rename something
   $ hg status -C
   ? dir2/subdir/large.bin
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir/
diff --git a/tests/test-largefiles.t b/tests/test-largefiles.t
--- a/tests/test-largefiles.t
+++ b/tests/test-largefiles.t
@@ -225,7 +225,7 @@  Test largefiles can be loaded in hgweb (
   $ . "$TESTDIR/cgienv"
 
   $ SCRIPT_NAME='' \
-  > $PYTHON "$TESTTMP/hgweb.cgi" > /dev/null
+  > "$PYTHON" "$TESTTMP/hgweb.cgi" > /dev/null
 
 Test archiving the various revisions.  These hit corner cases known with
 archiving.
diff --git a/tests/test-lfs-largefiles.t b/tests/test-lfs-largefiles.t
--- a/tests/test-lfs-largefiles.t
+++ b/tests/test-lfs-largefiles.t
@@ -201,7 +201,7 @@  largefiles since it hooks cmdutil.add() 
 commit.  By the time the commit occurs, the tracked file is smaller than the
 threshold (assuming it is > 41, so the standins don't become lfs objects).
 
-  $ $PYTHON -c 'import sys ; sys.stdout.write("y\n" * 1048576)' > large_by_size.bin
+  $ "$PYTHON" -c 'import sys ; sys.stdout.write("y\n" * 1048576)' > large_by_size.bin
   $ hg --config largefiles.minsize=1 ci -Am 'large by size'
   adding large_by_size.bin as a largefile
   $ hg manifest
diff --git a/tests/test-lfs-serve-access.t b/tests/test-lfs-serve-access.t
--- a/tests/test-lfs-serve-access.t
+++ b/tests/test-lfs-serve-access.t
@@ -52,7 +52,7 @@  Downloads fail...
   abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=download)!
   [255]
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
@@ -141,7 +141,7 @@  Blob URIs are correct when --prefix is u
   lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
   $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
@@ -174,7 +174,7 @@  though the client doesn't send the blob.
   server2/.hg/store/lfs/objects
   server2/.hg/store/lfs/objects/f0
   server2/.hg/store/lfs/objects/f0/3217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
   $ cat $TESTTMP/errors.log
 
   $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
@@ -286,7 +286,7 @@  Test a checksum failure during the proce
   abort: HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
   [255]
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
@@ -438,7 +438,7 @@  the GET/PUT request.
     "transfer": "basic"
   }
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 401 - (glob)
diff --git a/tests/test-lfs-serve.t b/tests/test-lfs-serve.t
--- a/tests/test-lfs-serve.t
+++ b/tests/test-lfs-serve.t
@@ -509,7 +509,7 @@  Only the files required by diff are pref
 
 #endif
 
-  $ $PYTHON $TESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $TESTDIR/killdaemons.py $DAEMON_PIDS
 
 #if lfsremote-on
   $ cat $TESTTMP/errors.log | grep '^[A-Z]'
diff --git a/tests/test-lfs-test-server.t b/tests/test-lfs-test-server.t
--- a/tests/test-lfs-test-server.t
+++ b/tests/test-lfs-test-server.t
@@ -36,7 +36,7 @@ 
   >             sys.exit(0)
   > sys.exit(1)
   > EOF
-  $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
+  $ "$PYTHON" $TESTTMP/spawn.py >> $DAEMON_PIDS
 #endif
 
   $ cat >> $HGRCPATH <<EOF
@@ -850,7 +850,7 @@  Check error message when object does not
 
 (Restart the server in a different location so it no longer has the content)
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
 #if hg-server
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
@@ -888,7 +888,7 @@  Check error message when object does not
 #endif
 
 #if windows git-server
-  $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
+  $ "$PYTHON" $TESTTMP/spawn.py >> $DAEMON_PIDS
 #endif
 
 #if hg-server
@@ -938,4 +938,4 @@  Check error message when object does not
   abort: LFS server error for "a": The object does not exist!
   [255]
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
diff --git a/tests/test-lfs.t b/tests/test-lfs.t
--- a/tests/test-lfs.t
+++ b/tests/test-lfs.t
@@ -486,7 +486,7 @@  enabled adds the lfs requirement
   > [lfs]
   > track=all()
   > EOF
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > def write(path, content):
   >     with open(path, 'wb') as f:
   >         f.write(content)
diff --git a/tests/test-logexchange.t b/tests/test-logexchange.t
--- a/tests/test-logexchange.t
+++ b/tests/test-logexchange.t
@@ -3,7 +3,7 @@  Testing the functionality to pull remote
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > [alias]
   > glog = log -G -T '{rev}:{node|short}  {desc}'
   > [extensions]
diff --git a/tests/test-mactext.t b/tests/test-mactext.t
--- a/tests/test-mactext.t
+++ b/tests/test-mactext.t
@@ -24,7 +24,7 @@ 
   $ hg add f
   $ hg ci -m 1
 
-  $ $PYTHON unix2mac.py f
+  $ "$PYTHON" unix2mac.py f
   $ hg ci -m 2
   attempt to commit or push text file(s) using CR line endings
   in dea860dc51ec: f
@@ -32,7 +32,7 @@ 
   rollback completed
   abort: pretxncommit.cr hook failed
   [255]
-  $ hg cat f | $PYTHON print.py
+  $ hg cat f | "$PYTHON" print.py
   hello<LF>
-  $ cat f | $PYTHON print.py
+  $ cat f | "$PYTHON" print.py
   hello<CR>
diff --git a/tests/test-merge-force.t b/tests/test-merge-force.t
--- a/tests/test-merge-force.t
+++ b/tests/test-merge-force.t
@@ -10,26 +10,26 @@  remote content, then finally forgotten.
 
 Create base changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 1
   $ hg addremove -q --similarity 0
   $ hg commit -qm 'base'
 
 Create remote changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 2
   $ hg addremove -q --similarity 0
   $ hg commit -qm 'remote'
 
 Create local changeset
 
   $ hg update -q 0
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 3
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 3
   $ hg addremove -q --similarity 0
   $ hg commit -qm 'local'
 
 Set up working directory
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*_*-untracked
   $ rm *_*_*_missing-*
@@ -311,7 +311,7 @@  missing_missing_content3_missing-tracked
 the remote side did not touch the file
 
   $ checkstatus() {
-  >   for f in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 3`
+  >   for f in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 3`
   >   do
   >     echo
   >     hg status -A $f
@@ -692,7 +692,7 @@  the remote side did not touch the file
   missing_missing_missing_missing-untracked: * (glob)
   <missing>
 
-  $ for f in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 3`
+  $ for f in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 3`
   > do
   >   if test -f ${f}.orig
   >   then
@@ -834,7 +834,7 @@  Set up working directory again
 
   $ hg -q update --clean 2
   $ hg --config extensions.purge= purge
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*_*-untracked
   $ rm *_*_*_missing-*
diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
--- a/tests/test-merge-tools.t
+++ b/tests/test-merge-tools.t
@@ -68,7 +68,7 @@  hg merge -r 2
 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
 running from a devel copy, not a temp installation
 
-  $ PATH="$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
+  $ PATH="$BINDIR:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
   merging f
   warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
@@ -117,7 +117,7 @@  unexecutable file in $PATH shouldn't be 
 
   $ echo "echo fail" > false
   $ hg up -qC 1
-  $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
+  $ PATH="`pwd`:$BINDIR:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
   merging f
   warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
@@ -131,7 +131,7 @@  executable directory in $PATH shouldn't 
 
   $ mkdir false
   $ hg up -qC 1
-  $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
+  $ PATH="`pwd`:$BINDIR:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
   merging f
   warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
diff --git a/tests/test-mq-eol.t b/tests/test-mq-eol.t
--- a/tests/test-mq-eol.t
+++ b/tests/test-mq-eol.t
@@ -44,11 +44,11 @@  Test interactions between mq and patch.e
 
 Test different --eol values
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\nb\nc\nd\ne")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\nb\nc\nd\ne")'
   $ hg ci -Am adda
   adding .hgignore
   adding a
-  $ $PYTHON ../makepatch.py
+  $ "$PYTHON" ../makepatch.py
   $ hg qimport eol.diff
   adding eol.diff to series file
 
@@ -85,7 +85,7 @@  force LF
   applying eol.diff
   now at: eol.diff
   $ hg qrefresh
-  $ $PYTHON ../cateol.py .hg/patches/eol.diff
+  $ "$PYTHON" ../cateol.py .hg/patches/eol.diff
   # HG changeset patch<LF>
   # Parent  0d0bf99a8b7a3842c6f8ef09e34f69156c4bd9d0<LF>
   test message<LF>
@@ -106,7 +106,7 @@  force LF
   +d<CR><LF>
   +z<LF>
   \ No newline at end of file<LF>
-  $ $PYTHON ../cateol.py a
+  $ "$PYTHON" ../cateol.py a
   a<CR><LF>
   y<CR><LF>
   c<CR><LF>
@@ -121,7 +121,7 @@  push again forcing LF and compare revisi
   $ hg --config patch.eol='CRLF' qpush
   applying eol.diff
   now at: eol.diff
-  $ $PYTHON ../cateol.py a
+  $ "$PYTHON" ../cateol.py a
   a<CR><LF>
   y<CR><LF>
   c<CR><LF>
@@ -136,7 +136,7 @@  push again without LF and compare revisi
   $ hg qpush
   applying eol.diff
   now at: eol.diff
-  $ $PYTHON ../cateol.py a
+  $ "$PYTHON" ../cateol.py a
   a<CR><LF>
   y<CR><LF>
   c<CR><LF>
@@ -152,15 +152,15 @@  Test .rej file EOL are left unchanged
 
   $ hg init testeol
   $ cd testeol
-  $ $PYTHON -c "open('a', 'wb').write(b'1\r\n2\r\n3\r\n4')"
+  $ "$PYTHON" -c "open('a', 'wb').write(b'1\r\n2\r\n3\r\n4')"
   $ hg ci -Am adda
   adding a
-  $ $PYTHON -c "open('a', 'wb').write(b'1\r\n2\r\n33\r\n4')"
+  $ "$PYTHON" -c "open('a', 'wb').write(b'1\r\n2\r\n33\r\n4')"
   $ hg qnew patch1
   $ hg qpop
   popping patch1
   patch queue now empty
-  $ $PYTHON -c "open('a', 'wb').write(b'1\r\n22\r\n33\r\n4')"
+  $ "$PYTHON" -c "open('a', 'wb').write(b'1\r\n22\r\n33\r\n4')"
   $ hg ci -m changea
 
   $ hg --config 'patch.eol=LF' qpush
diff --git a/tests/test-mq-missingfiles.t b/tests/test-mq-missingfiles.t
--- a/tests/test-mq-missingfiles.t
+++ b/tests/test-mq-missingfiles.t
@@ -23,11 +23,11 @@  future qrefresh.
 
   $ hg init normal
   $ cd normal
-  $ $PYTHON ../writelines.py b 10 'a\n'
+  $ "$PYTHON" ../writelines.py b 10 'a\n'
   $ hg ci -Am addb
   adding b
   $ echo a > a
-  $ $PYTHON ../writelines.py b 2 'b\n' 10 'a\n' 2 'c\n'
+  $ "$PYTHON" ../writelines.py b 2 'b\n' 10 'a\n' 2 'c\n'
   $ echo c > c
   $ hg add a c
   $ hg qnew -f changeb
@@ -82,7 +82,7 @@  Test missing renamed file
   $ hg up -qC 0
   $ echo a > a
   $ hg mv b bb
-  $ $PYTHON ../writelines.py bb 2 'b\n' 10 'a\n' 2 'c\n'
+  $ "$PYTHON" ../writelines.py bb 2 'b\n' 10 'a\n' 2 'c\n'
   $ echo c > c
   $ hg add a c
   $ hg qnew changebb
@@ -129,11 +129,11 @@  Test missing renamed file
 
   $ hg init git
   $ cd git
-  $ $PYTHON ../writelines.py b 1 '\x00'
+  $ "$PYTHON" ../writelines.py b 1 '\x00'
   $ hg ci -Am addb
   adding b
   $ echo a > a
-  $ $PYTHON ../writelines.py b 1 '\x01' 1 '\x00'
+  $ "$PYTHON" ../writelines.py b 1 '\x01' 1 '\x00'
   $ echo c > c
   $ hg add a c
   $ hg qnew -f changeb
diff --git a/tests/test-mq-qimport.t b/tests/test-mq-qimport.t
--- a/tests/test-mq-qimport.t
+++ b/tests/test-mq-qimport.t
@@ -149,10 +149,10 @@  qimport -f
 
 build diff with CRLF
 
-  $ $PYTHON ../writelines.py b 5 'a\n' 5 'a\r\n'
+  $ "$PYTHON" ../writelines.py b 5 'a\n' 5 'a\r\n'
   $ hg ci -Am addb
   adding b
-  $ $PYTHON ../writelines.py b 2 'a\n' 10 'b\n' 2 'a\r\n'
+  $ "$PYTHON" ../writelines.py b 2 'a\n' 10 'b\n' 2 'a\r\n'
   $ hg diff > b.diff
   $ hg up -C
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
diff --git a/tests/test-mq-qpush-fail.t b/tests/test-mq-qpush-fail.t
--- a/tests/test-mq-qpush-fail.t
+++ b/tests/test-mq-qpush-fail.t
@@ -31,7 +31,7 @@  test qpush on empty series
   popping patch2
   popping patch1
   patch queue now empty
-  $ $PYTHON -c 'import sys; getattr(sys.stdout, "buffer", sys.stdout).write(b"\xe9\n")' > message
+  $ "$PYTHON" -c 'import sys; getattr(sys.stdout, "buffer", sys.stdout).write(b"\xe9\n")' > message
   $ cat .hg/patches/bad-patch >> message
   $ mv message .hg/patches/bad-patch
   $ cat > $TESTTMP/wrapplayback.py <<EOF
diff --git a/tests/test-mq-subrepo-svn.t b/tests/test-mq-subrepo-svn.t
--- a/tests/test-mq-subrepo-svn.t
+++ b/tests/test-mq-subrepo-svn.t
@@ -24,9 +24,9 @@  handle svn subrepos safely
 
   $ SVNREPOPATH=`pwd`/svn-repo-2499/project
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
   $ mkdir -p svn-project-2499/trunk
diff --git a/tests/test-mq.t b/tests/test-mq.t
--- a/tests/test-mq.t
+++ b/tests/test-mq.t
@@ -1128,9 +1128,9 @@  create a git binary patch
   > path = sys.argv[1]
   > open(path, 'wb').write(b'BIN\x00ARY')
   > EOF
-  $ $PYTHON writebin.py bucephalus
+  $ "$PYTHON" writebin.py bucephalus
 
-  $ $PYTHON "$TESTDIR/md5sum.py" bucephalus
+  $ "$PYTHON" "$TESTDIR/md5sum.py" bucephalus
   8ba2a2f3e77b55d03051ff9c24ad65e7  bucephalus
   $ hg add bucephalus
   $ hg qnew -f --git addbucephalus
@@ -1149,7 +1149,7 @@  check binary patches can be popped and p
   applying addbucephalus
   now at: addbucephalus
   $ test -f bucephalus
-  $ $PYTHON "$TESTDIR/md5sum.py" bucephalus
+  $ "$PYTHON" "$TESTDIR/md5sum.py" bucephalus
   8ba2a2f3e77b55d03051ff9c24ad65e7  bucephalus
 
 
@@ -1575,7 +1575,7 @@  Test that secret mq patch does not break
   $ PATH_INFO=/tags; export PATH_INFO
 #endif
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi | grep '^tip'
+  $ "$PYTHON" hgweb.cgi | grep '^tip'
   tip	[0-9a-f]{40} (re)
 
   $ cd ..
diff --git a/tests/test-narrow-clone-non-narrow-server.t b/tests/test-narrow-clone-non-narrow-server.t
--- a/tests/test-narrow-clone-non-narrow-server.t
+++ b/tests/test-narrow-clone-non-narrow-server.t
@@ -31,7 +31,7 @@  Verify that narrow is advertised in the 
   > print(unquote(list(sys.stdin)[1]))
   > EOF
   $ echo hello | hg -R . serve --stdio | \
-  >   $PYTHON unquote.py | grep narrow
+  >   "$PYTHON" unquote.py | grep narrow
   narrow=v0
   rev-branch-cache changegroupsubset exp-narrow-1 getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
 
diff --git a/tests/test-newcgi.t b/tests/test-newcgi.t
--- a/tests/test-newcgi.t
+++ b/tests/test-newcgi.t
@@ -52,15 +52,15 @@  before d74fc8dec2b4 still work.
   $ chmod 755 hgwebdir.cgi
 
   $ . "$TESTDIR/cgienv"
-  $ $PYTHON hgweb.cgi > page1
-  $ $PYTHON hgwebdir.cgi > page2
+  $ "$PYTHON" hgweb.cgi > page1
+  $ "$PYTHON" hgwebdir.cgi > page2
 
   $ PATH_INFO="/test/"
   $ PATH_TRANSLATED="/var/something/test.cgi"
   $ REQUEST_URI="/test/test/"
   $ SCRIPT_URI="http://hg.omnifarious.org/test/test/"
   $ SCRIPT_URL="/test/test/"
-  $ $PYTHON hgwebdir.cgi > page3
+  $ "$PYTHON" hgwebdir.cgi > page3
 
   $ grep -i error page1 page2 page3
   [1]
diff --git a/tests/test-newercgi.t b/tests/test-newercgi.t
--- a/tests/test-newercgi.t
+++ b/tests/test-newercgi.t
@@ -46,15 +46,15 @@  This is a rudimentary test of the CGI fi
   $ chmod 755 hgwebdir.cgi
 
   $ . "$TESTDIR/cgienv"
-  $ $PYTHON hgweb.cgi > page1
-  $ $PYTHON hgwebdir.cgi > page2
+  $ "$PYTHON" hgweb.cgi > page1
+  $ "$PYTHON" hgwebdir.cgi > page2
 
   $ PATH_INFO="/test/"
   $ PATH_TRANSLATED="/var/something/test.cgi"
   $ REQUEST_URI="/test/test/"
   $ SCRIPT_URI="http://hg.omnifarious.org/test/test/"
   $ SCRIPT_URL="/test/test/"
-  $ $PYTHON hgwebdir.cgi > page3
+  $ "$PYTHON" hgwebdir.cgi > page3
 
   $ grep -i error page1 page2 page3
   [1]
diff --git a/tests/test-notify-changegroup.t b/tests/test-notify-changegroup.t
--- a/tests/test-notify-changegroup.t
+++ b/tests/test-notify-changegroup.t
@@ -39,7 +39,7 @@  commit
 push
 
   $ hg --traceback --cwd b push ../a 2>&1 |
-  >     $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
+  >     "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
   pushing to ../a
   searching for changes
   adding changesets
@@ -93,7 +93,7 @@  unbundle with unrelated source
 unbundle with correct source
 
   $ hg --config notify.sources=unbundle --cwd a unbundle ../test.hg 2>&1 |
-  >     $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
+  >     "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
   adding changesets
   adding manifests
   adding file changes
@@ -169,7 +169,7 @@  merge as a different user
 push
 
   $ hg --traceback --cwd b --config notify.fromauthor=True push ../a 2>&1 |
-  >     $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
+  >     "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
   pushing to ../a
   searching for changes
   adding changesets
diff --git a/tests/test-notify.t b/tests/test-notify.t
--- a/tests/test-notify.t
+++ b/tests/test-notify.t
@@ -190,7 +190,7 @@  the python call below wraps continuation
 of the very long subject line
 pull (minimal config)
 
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
@@ -249,7 +249,7 @@  pull
 
   $ hg --cwd b rollback
   repository tip rolled back to revision 0 (undo pull)
-  $ hg --traceback --cwd b pull ../a  | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a  | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
@@ -297,7 +297,7 @@  pull
 
   $ hg --cwd b rollback
   repository tip rolled back to revision 0 (undo pull)
-  $ hg --traceback --config notify.maxdiffstat=1 --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --config notify.maxdiffstat=1 --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
@@ -348,7 +348,7 @@  test merge
   (branch merge, don't forget to commit)
   $ hg ci -m merge -d '3 0'
   $ cd ..
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
@@ -412,9 +412,9 @@  non-ascii content and truncation of mult
   > EOF
   $ echo a >> a/a
   $ hg --cwd a --encoding utf-8 commit -A -d '0 0' \
-  >   -m `$PYTHON -c 'print "\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4"'`
+  >   -m `"$PYTHON" -c 'print "\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4"'`
   $ hg --traceback --cwd b --encoding utf-8 pull ../a | \
-  >   $PYTHON $TESTTMP/filter.py
+  >   "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
@@ -455,7 +455,7 @@  long lines
   > test = False
   > mbox = mbox
   > EOF
-  $ $PYTHON -c 'open("a/a", "ab").write("no" * 500 + "\xd1\x84" + "\n")'
+  $ "$PYTHON" -c 'open("a/a", "ab").write("no" * 500 + "\xd1\x84" + "\n")'
   $ hg --cwd a commit -A -m "long line"
   $ hg --traceback --cwd b pull ../a
   pulling from ../a
@@ -467,7 +467,7 @@  long lines
   new changesets a846b5f6ebb7
   notify: sending 2 subscribers 1 changes
   (run 'hg update' to get a working copy)
-  $ $PYTHON $TESTTMP/filter.py < b/mbox
+  $ "$PYTHON" $TESTTMP/filter.py < b/mbox
   From test@test.com ... ... .. ..:..:.. .... (re)
   MIME-Version: 1.0
   Content-Type: text/plain; charset="*" (glob)
@@ -527,7 +527,7 @@  long lines
   (branches are permanent and global, did you want a bookmark?)
   $ echo a >> a/a
   $ hg --cwd a ci -m test -d '1 0'
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
@@ -557,7 +557,7 @@  from different branch
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo a >> a/a
   $ hg --cwd a ci -m test -d '1 0'
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
@@ -586,7 +586,7 @@  default template:
   $ mv "$HGRCPATH.new" $HGRCPATH
   $ echo a >> a/a
   $ hg --cwd a commit -m 'default template'
-  $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py
+  $ hg --cwd b pull ../a -q | "$PYTHON" $TESTTMP/filter.py
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
@@ -615,7 +615,7 @@  with style:
   > EOF
   $ echo a >> a/a
   $ hg --cwd a commit -m 'with style'
-  $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py
+  $ hg --cwd b pull ../a -q | "$PYTHON" $TESTTMP/filter.py
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
@@ -638,7 +638,7 @@  with template (overrides style):
   > EOF
   $ echo a >> a/a
   $ hg --cwd a commit -m 'with template'
-  $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py
+  $ hg --cwd b pull ../a -q | "$PYTHON" $TESTTMP/filter.py
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
diff --git a/tests/test-obsmarker-template.t b/tests/test-obsmarker-template.t
--- a/tests/test-obsmarker-template.t
+++ b/tests/test-obsmarker-template.t
@@ -2591,7 +2591,7 @@  Test metadata encoding (issue5754)
   > [extensions]
   > amend =
   > EOF
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > with open('test1', 'wb') as f:
   >    f.write(b't\xe8st1') and None
   > with open('test2', 'wb') as f:
diff --git a/tests/test-oldcgi.t b/tests/test-oldcgi.t
--- a/tests/test-oldcgi.t
+++ b/tests/test-oldcgi.t
@@ -4,7 +4,7 @@  This tests if CGI files from before d0db
 
   $ hg init test
   $ cat >hgweb.cgi <<HGWEB
-  > #!$PYTHON
+  > #!"$PYTHON"
   > #
   > # An example CGI script to use hgweb, edit as necessary
   > 
@@ -26,7 +26,7 @@  This tests if CGI files from before d0db
   > HGWEBDIRCONF
 
   $ cat >hgwebdir.cgi <<HGWEBDIR
-  > #!$PYTHON
+  > #!"$PYTHON"
   > #
   > # An example CGI script to export multiple hgweb repos, edit as necessary
   > 
@@ -62,15 +62,15 @@  This tests if CGI files from before d0db
   $ chmod 755 hgwebdir.cgi
 
   $ . "$TESTDIR/cgienv"
-  $ $PYTHON hgweb.cgi > page1
-  $ $PYTHON hgwebdir.cgi > page2
+  $ "$PYTHON" hgweb.cgi > page1
+  $ "$PYTHON" hgwebdir.cgi > page2
 
   $ PATH_INFO="/test/"
   $ PATH_TRANSLATED="/var/something/test.cgi"
   $ REQUEST_URI="/test/test/"
   $ SCRIPT_URI="http://hg.omnifarious.org/test/test/"
   $ SCRIPT_URL="/test/test/"
-  $ $PYTHON hgwebdir.cgi > page3
+  $ "$PYTHON" hgwebdir.cgi > page3
 
   $ grep -i error page1 page2 page3
   [1]
diff --git a/tests/test-pager-legacy.t b/tests/test-pager-legacy.t
--- a/tests/test-pager-legacy.t
+++ b/tests/test-pager-legacy.t
@@ -14,7 +14,7 @@  pager was running.
   > [extensions]
   > pager=
   > [pager]
-  > pager = $PYTHON $TESTTMP/fakepager.py
+  > pager = "$PYTHON" $TESTTMP/fakepager.py
   > EOF
 
   $ hg init repo
@@ -22,7 +22,7 @@  pager was running.
   $ echo a >> a
   $ hg add a
   $ hg ci -m 'add a'
-  $ for x in `$PYTHON $TESTDIR/seq.py 1 10`; do
+  $ for x in `"$PYTHON" $TESTDIR/seq.py 1 10`; do
   >   echo a $x >> a
   >   hg ci -m "modify a $x"
   > done
diff --git a/tests/test-pager.t b/tests/test-pager.t
--- a/tests/test-pager.t
+++ b/tests/test-pager.t
@@ -16,7 +16,7 @@  pager was running.
   > formatted = yes
   > color = no
   > [pager]
-  > pager = $PYTHON $TESTTMP/fakepager.py
+  > pager = "$PYTHON" $TESTTMP/fakepager.py
   > EOF
 
   $ hg init repo
@@ -24,7 +24,7 @@  pager was running.
   $ echo a >> a
   $ hg add a
   $ hg ci -m 'add a'
-  $ for x in `$PYTHON $TESTDIR/seq.py 1 10`; do
+  $ for x in `"$PYTHON" $TESTDIR/seq.py 1 10`; do
   >   echo a $x >> a
   >   hg ci -m "modify a $x"
   > done
@@ -404,7 +404,7 @@  Environment variables like LESS and LV a
   > [ui]
   > formatted=1
   > [pager]
-  > pager = $PYTHON $TESTTMP/printlesslv.py
+  > pager = "$PYTHON" $TESTTMP/printlesslv.py
   > EOF
   $ unset LESS
   $ unset LV
diff --git a/tests/test-parseindex.t b/tests/test-parseindex.t
--- a/tests/test-parseindex.t
+++ b/tests/test-parseindex.t
@@ -61,7 +61,7 @@  We approximate that by reducing the read
   > for r in cl:
   >     print(short(cl.node(r)))
   > EOF
-  $ $PYTHON test.py
+  $ "$PYTHON" test.py
   2 revisions:
   7c31755bf9b5
   26333235a41c
@@ -74,7 +74,7 @@  Test SEGV caused by bad revision passed 
 
   $ cd a
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > from __future__ import print_function
   > from mercurial import changelog, vfs
   > cl = changelog.changelog(vfs.vfs('.hg/store'))
@@ -137,7 +137,7 @@  Test corrupted p1/p2 fields that could c
   $ hg clone --pull -q --config phases.publish=False ../a segv
   $ rm -R limit/.hg/cache segv/.hg/cache
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > data = open("limit/.hg/store/00changelog.i", "rb").read()
   > for n, p in [(b'limit', b'\0\0\0\x02'), (b'segv', b'\0\x01\0\0')]:
   >     # corrupt p1 at rev0 and p2 at rev1
@@ -188,13 +188,13 @@  Test corrupted p1/p2 fields that could c
   >         print(inst)
   > EOF
 
-  $ $PYTHON test.py limit/.hg/store
+  $ "$PYTHON" test.py limit/.hg/store
   reachableroots: parent out of range
   compute_phases_map_sets: parent out of range
   index_headrevs: parent out of range
   find_gca_candidates: parent out of range
   find_deepest: parent out of range
-  $ $PYTHON test.py segv/.hg/store
+  $ "$PYTHON" test.py segv/.hg/store
   reachableroots: parent out of range
   compute_phases_map_sets: parent out of range
   index_headrevs: parent out of range
diff --git a/tests/test-patch-offset.t b/tests/test-patch-offset.t
--- a/tests/test-patch-offset.t
+++ b/tests/test-patch-offset.t
@@ -23,7 +23,7 @@  the patch.  So all the patch hunks need 
 within this file.  If the offset isn't tracked then the hunks can be
 applied to the wrong lines of this file.
 
-  $ $PYTHON ../writepatterns.py a 34X 10A 1B 10A 1C 10A 1B 10A 1D 10A 1B 10A 1E 10A 1B 10A
+  $ "$PYTHON" ../writepatterns.py a 34X 10A 1B 10A 1C 10A 1B 10A 1D 10A 1B 10A 1E 10A 1B 10A
   $ hg commit -Am adda
   adding a
 
@@ -76,7 +76,7 @@  import patch
 
 compare imported changes against reference file
 
-  $ $PYTHON ../writepatterns.py aref 34X 10A 1B 1a 9A 1C 10A 1B 10A 1D 10A 1B 1a 9A 1E 10A 1B 1a 9A
+  $ "$PYTHON" ../writepatterns.py aref 34X 10A 1B 1a 9A 1C 10A 1B 10A 1D 10A 1B 1a 9A 1E 10A 1B 1a 9A
   $ diff aref a
 
   $ cd ..
diff --git a/tests/test-patch.t b/tests/test-patch.t
--- a/tests/test-patch.t
+++ b/tests/test-patch.t
@@ -7,7 +7,7 @@ 
   > EOF
 
   $ echo "[ui]" >> $HGRCPATH
-  $ echo "patch=$PYTHON ../patchtool.py" >> $HGRCPATH
+  $ echo "patch=\"$PYTHON\" ../patchtool.py" >> $HGRCPATH
 
   $ hg init a
   $ cd a
diff --git a/tests/test-patchbomb-tls.t b/tests/test-patchbomb-tls.t
--- a/tests/test-patchbomb-tls.t
+++ b/tests/test-patchbomb-tls.t
@@ -5,7 +5,7 @@  Set up SMTP server:
   $ CERTSDIR="$TESTDIR/sslcerts"
   $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
 
-  $ $PYTHON "$TESTDIR/dummysmtpd.py" -p $HGPORT --pid-file a.pid -d \
+  $ "$PYTHON" "$TESTDIR/dummysmtpd.py" -p $HGPORT --pid-file a.pid -d \
   > --tls smtps --certificate `pwd`/server.pem
   listening at localhost:$HGPORT (?)
   $ cat a.pid >> $DAEMON_PIDS
diff --git a/tests/test-patchbomb.t b/tests/test-patchbomb.t
--- a/tests/test-patchbomb.t
+++ b/tests/test-patchbomb.t
@@ -442,7 +442,7 @@  with a specific bundle type
   --===============*==-- (glob)
 
 utf-8 patch:
-  $ $PYTHON -c 'fp = open("utf", "wb"); fp.write(b"h\xC3\xB6mma!\n"); fp.close();'
+  $ "$PYTHON" -c 'fp = open("utf", "wb"); fp.write(b"h\xC3\xB6mma!\n"); fp.close();'
   $ hg commit -A -d '4 0' -m 'utf-8 content'
   adding description
   adding utf
@@ -558,7 +558,7 @@  mime encoded mbox (base64):
   $ rm mbox
 
 mime encoded mbox (quoted-printable):
-  $ $PYTHON -c 'fp = open("long", "wb"); fp.write(b"%s\nfoo\n\nbar\n" % (b"x" * 1024)); fp.close();'
+  $ "$PYTHON" -c 'fp = open("long", "wb"); fp.write(b"%s\nfoo\n\nbar\n" % (b"x" * 1024)); fp.close();'
   $ hg commit -A -d '4 0' -m 'long line'
   adding long
 
@@ -672,7 +672,7 @@  mime encoded mbox (quoted-printable):
   $ rm mbox
 
 iso-8859-1 patch:
-  $ $PYTHON -c 'fp = open("isolatin", "wb"); fp.write(b"h\xF6mma!\n"); fp.close();'
+  $ "$PYTHON" -c 'fp = open("isolatin", "wb"); fp.write(b"h\xF6mma!\n"); fp.close();'
   $ hg commit -A -d '5 0' -m 'isolatin 8-bit encoding'
   adding isolatin
 
diff --git a/tests/test-profile.t b/tests/test-profile.t
--- a/tests/test-profile.t
+++ b/tests/test-profile.t
@@ -105,7 +105,7 @@  Various statprof formatters work
 
 statprof can be used as a standalone module
 
-  $ $PYTHON -m mercurial.statprof hotpath
+  $ "$PYTHON" -m mercurial.statprof hotpath
   must specify --file to load
   [1]
 
diff --git a/tests/test-pull.t b/tests/test-pull.t
--- a/tests/test-pull.t
+++ b/tests/test-pull.t
@@ -109,12 +109,12 @@  MSYS changes 'file:' into 'file;'
 It's tricky to make file:// URLs working on every platform with
 regular shell commands.
 
-  $ URL=`$PYTHON -c "from __future__ import print_function; import os; print('file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
+  $ URL=`"$PYTHON" -c "from __future__ import print_function; import os; print('file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
   $ hg pull -q "$URL"
   abort: file:// URLs can only refer to localhost
   [255]
 
-  $ URL=`$PYTHON -c "from __future__ import print_function; import os; print('file://localhost' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
+  $ URL=`"$PYTHON" -c "from __future__ import print_function; import os; print('file://localhost' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
   $ hg pull -q "$URL"
 
 SEC: check for unsafe ssh url
diff --git a/tests/test-purge.t b/tests/test-purge.t
--- a/tests/test-purge.t
+++ b/tests/test-purge.t
@@ -49,7 +49,7 @@  delete an untracked file
 
   $ touch untracked_file
   $ touch untracked_file_readonly
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > import os, stat
   > f= 'untracked_file_readonly'
   > os.chmod(f, stat.S_IMODE(os.stat(f).st_mode) & ~stat.S_IWRITE)
diff --git a/tests/test-push-cgi.t b/tests/test-push-cgi.t
--- a/tests/test-push-cgi.t
+++ b/tests/test-push-cgi.t
@@ -38,7 +38,7 @@  test preparation
 expect failure because heads doesn't match (formerly known as 'unsynced changes')
 
   $ QUERY_STRING="cmd=unbundle&heads=0000000000000000000000000000000000000000"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page1 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page1 2>&1
   $ cat page1
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
@@ -50,7 +50,7 @@  expect failure because heads doesn't mat
 successful force push
 
   $ QUERY_STRING="cmd=unbundle&heads=666f726365"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page2 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page2 2>&1
   $ cat page2
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
@@ -65,7 +65,7 @@  successful force push
 successful push, list of heads
 
   $ QUERY_STRING="cmd=unbundle&heads=f7b1eb17ad24730a1651fccd46c43826d1bbc2ac"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page3 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page3 2>&1
   $ cat page3
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
@@ -80,7 +80,7 @@  successful push, list of heads
 successful push, SHA1 hash of heads (unbundlehash capability)
 
   $ QUERY_STRING="cmd=unbundle&heads=686173686564 5a785a5f9e0d433b88ed862b206b011b0c3a9d13"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page4 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page4 2>&1
   $ cat page4
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
diff --git a/tests/test-push-race.t b/tests/test-push-race.t
--- a/tests/test-push-race.t
+++ b/tests/test-push-race.t
@@ -102,7 +102,7 @@  A set of extension and shell functions e
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > # simplify output
   > logtemplate = {node|short} {desc} ({branch})
   > [phases]
diff --git a/tests/test-push-warn.t b/tests/test-push-warn.t
--- a/tests/test-push-warn.t
+++ b/tests/test-push-warn.t
@@ -419,7 +419,7 @@  multiple new heads but also doesn't repo
   adding c
   created new head
 
-  $ for i in `$PYTHON $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
 
   $ hg -R i push h
   pushing to h
diff --git a/tests/test-rebase-base-flag.t b/tests/test-rebase-base-flag.t
--- a/tests/test-rebase-base-flag.t
+++ b/tests/test-rebase-base-flag.t
@@ -14,7 +14,7 @@  flag should probably live in somewhere e
   > EOF
 
   $ rebasewithdag() {
-  >   N=`$PYTHON -c "print($N+1)"`
+  >   N=`"$PYTHON" -c "print($N+1)"`
   >   hg init repo$N && cd repo$N
   >   hg debugdrawdag
   >   hg rebase "$@" > _rebasetmp
diff --git a/tests/test-rebase-dest.t b/tests/test-rebase-dest.t
--- a/tests/test-rebase-dest.t
+++ b/tests/test-rebase-dest.t
@@ -119,7 +119,7 @@  Setup rebase with multiple destinations
   > EOF
 
   $ rebasewithdag() {
-  >   N=`$PYTHON -c "print($N+1)"`
+  >   N=`"$PYTHON" -c "print($N+1)"`
   >   hg init repo$N && cd repo$N
   >   hg debugdrawdag
   >   hg rebase "$@" > _rebasetmp
diff --git a/tests/test-rebase-partial.t b/tests/test-rebase-partial.t
--- a/tests/test-rebase-partial.t
+++ b/tests/test-rebase-partial.t
@@ -15,7 +15,7 @@  destination (issue5422)
   > EOF
 
   $ rebasewithdag() {
-  >   N=`$PYTHON -c "print($N+1)"`
+  >   N=`"$PYTHON" -c "print($N+1)"`
   >   hg init repo$N && cd repo$N
   >   hg debugdrawdag
   >   hg rebase "$@" > _rebasetmp
diff --git a/tests/test-relink.t b/tests/test-relink.t
--- a/tests/test-relink.t
+++ b/tests/test-relink.t
@@ -49,7 +49,7 @@  don't sit forever trying to double-lock 
 
 Test files are read in binary mode
 
-  $ $PYTHON -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\r\nb\n')"
+  $ "$PYTHON" -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\r\nb\n')"
   $ cd ..
 
 
@@ -68,7 +68,7 @@  clone and pull to break links
   $ echo b >> b
   $ hg ci -m changeb
   created new head
-  $ $PYTHON -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\nb\r\n')"
+  $ "$PYTHON" -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\nb\r\n')"
 
 
 relink
@@ -98,9 +98,9 @@  relink
 
 check hardlinks
 
-  $ $PYTHON arelinked.py repo/.hg/store/data/a.i clone/.hg/store/data/a.i
+  $ "$PYTHON" arelinked.py repo/.hg/store/data/a.i clone/.hg/store/data/a.i
   repo/.hg/store/data/a.i == clone/.hg/store/data/a.i
-  $ $PYTHON arelinked.py repo/.hg/store/data/b.i clone/.hg/store/data/b.i
+  $ "$PYTHON" arelinked.py repo/.hg/store/data/b.i clone/.hg/store/data/b.i
   repo/.hg/store/data/b.i != clone/.hg/store/data/b.i
 
 #endif
diff --git a/tests/test-rename-merge2.t b/tests/test-rename-merge2.t
--- a/tests/test-rename-merge2.t
+++ b/tests/test-rename-merge2.t
@@ -47,7 +47,7 @@  args:
   >     echo "--------------"
   >     echo "test L:$1 R:$2 W:$3 - $4"
   >     echo "--------------"
-  >     hg merge -y --debug --traceback --tool="$PYTHON ../merge"
+  >     hg merge -y --debug --traceback --tool="\"$PYTHON\" ../merge"
   > 
   >     echo "--------------"
   >     hg status -camC -X rev
diff --git a/tests/test-repair-strip.t b/tests/test-repair-strip.t
--- a/tests/test-repair-strip.t
+++ b/tests/test-repair-strip.t
@@ -21,7 +21,7 @@ 
   >   hg verify
   >   echo % journal contents
   >   if [ -f .hg/store/journal ]; then
-  >       cat .hg/store/journal | $PYTHON $TESTTMP/dumpjournal.py
+  >       cat .hg/store/journal | "$PYTHON" $TESTTMP/dumpjournal.py
   >   else
   >       echo "(no journal)"
   >   fi
diff --git a/tests/test-revert.t b/tests/test-revert.t
--- a/tests/test-revert.t
+++ b/tests/test-revert.t
@@ -495,7 +495,7 @@  Write the python script to disk
 
 check list of planned files
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py filelist 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 2
   content1_content1_content1-tracked
   content1_content1_content1-untracked
   content1_content1_content3-tracked
@@ -550,7 +550,7 @@  Generate appropriate repo state
 
 Generate base changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove --similarity 0
   adding content1_content1_content1-tracked
   adding content1_content1_content1-untracked
@@ -597,7 +597,7 @@  Generate base changeset
 
 (create a simple text version of the content)
 
-  $ $PYTHON ../dircontent.py > ../content-base.txt
+  $ "$PYTHON" ../dircontent.py > ../content-base.txt
   $ cat ../content-base.txt
   content1 content1_content1_content1-tracked
   content1 content1_content1_content1-untracked
@@ -622,7 +622,7 @@  Generate base changeset
 
 Create parent changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove --similarity 0
   removing content1_missing_content1-tracked
   removing content1_missing_content1-untracked
@@ -661,7 +661,7 @@  Create parent changeset
 
 (create a simple text version of the content)
 
-  $ $PYTHON ../dircontent.py > ../content-parent.txt
+  $ "$PYTHON" ../dircontent.py > ../content-parent.txt
   $ cat ../content-parent.txt
   content1 content1_content1_content1-tracked
   content1 content1_content1_content1-untracked
@@ -686,7 +686,7 @@  Create parent changeset
 
 Setup working directory
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove --similarity 0
   adding content1_missing_content1-tracked
   adding content1_missing_content1-untracked
@@ -754,7 +754,7 @@  Setup working directory
 
 (create a simple text version of the content)
 
-  $ $PYTHON ../dircontent.py > ../content-wc.txt
+  $ "$PYTHON" ../dircontent.py > ../content-wc.txt
   $ cat ../content-wc.txt
   content1 content1_content1_content1-tracked
   content1 content1_content1_content1-untracked
@@ -818,7 +818,7 @@  Compare resulting directory with revert 
 The diff is filtered to include change only. The only difference should be
 additional `.orig` backup file when applicable.
 
-  $ $PYTHON ../dircontent.py > ../content-parent-all.txt
+  $ "$PYTHON" ../dircontent.py > ../content-parent-all.txt
   $ cd ..
   $ diff -U 0 -- content-parent.txt content-parent-all.txt | grep _
   +content3 content1_content1_content3-tracked.orig
@@ -875,7 +875,7 @@  Compare resulting directory with revert 
 The diff is filtered to include change only. The only difference should be
 additional `.orig` backup file when applicable.
 
-  $ $PYTHON ../dircontent.py > ../content-base-all.txt
+  $ "$PYTHON" ../dircontent.py > ../content-base-all.txt
   $ cd ..
   $ diff -U 0 -- content-base.txt content-base-all.txt | grep _
   +content3 content1_content1_content3-tracked.orig
@@ -902,7 +902,7 @@  Test revert to parent content with expli
 revert all files individually and check the output
 (output is expected to be different than in the --all case)
 
-  $ for file in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 2`; do
+  $ for file in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 2`; do
   >   echo '### revert for:' $file;
   >   hg revert $file;
   >   echo
@@ -979,7 +979,7 @@  revert all files individually and check 
 check resulting directory against the --all run
 (There should be no difference)
 
-  $ $PYTHON ../dircontent.py > ../content-parent-explicit.txt
+  $ "$PYTHON" ../dircontent.py > ../content-parent-explicit.txt
   $ cd ..
   $ diff -U 0 -- content-parent-all.txt content-parent-explicit.txt | grep _
   [1]
@@ -995,7 +995,7 @@  Test revert to "base" content with expli
 revert all files individually and check the output
 (output is expected to be different than in the --all case)
 
-  $ for file in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 2`; do
+  $ for file in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 2`; do
   >   echo '### revert for:' $file;
   >   hg revert $file --rev 'desc(base)';
   >   echo
@@ -1072,7 +1072,7 @@  revert all files individually and check 
 check resulting directory against the --all run
 (There should be no difference)
 
-  $ $PYTHON ../dircontent.py > ../content-base-explicit.txt
+  $ "$PYTHON" ../dircontent.py > ../content-base-explicit.txt
   $ cd ..
   $ diff -U 0 -- content-base-all.txt content-base-explicit.txt | grep _
   [1]
diff --git a/tests/test-revset2.t b/tests/test-revset2.t
--- a/tests/test-revset2.t
+++ b/tests/test-revset2.t
@@ -413,14 +413,14 @@  no crash by empty group "()" while optim
 test that chained `or` operations never eat up stack (issue4624)
 (uses `0:1` instead of `0` to avoid future optimization of trivial revisions)
 
-  $ hg log -T '{rev}\n' -r `$PYTHON -c "print '+'.join(['0:1'] * 500)"`
+  $ hg log -T '{rev}\n' -r `"$PYTHON" -c "print '+'.join(['0:1'] * 500)"`
   0
   1
 
 test that repeated `-r` options never eat up stack (issue4565)
 (uses `-r 0::1` to avoid possible optimization at old-style parser)
 
-  $ hg log -T '{rev}\n' `$PYTHON -c "for i in range(500): print '-r 0::1 ',"`
+  $ hg log -T '{rev}\n' `"$PYTHON" -c "for i in range(500): print '-r 0::1 ',"`
   0
   1
 
@@ -1527,7 +1527,7 @@  test author/desc/keyword in problematic 
   $ hg init problematicencoding
   $ cd problematicencoding
 
-  $ $PYTHON > setup.sh <<EOF
+  $ "$PYTHON" > setup.sh <<EOF
   > print u'''
   > echo a > text
   > hg add text
@@ -1543,7 +1543,7 @@  test author/desc/keyword in problematic 
   $ sh < setup.sh
 
 test in problematic encoding
-  $ $PYTHON > test.sh <<EOF
+  $ "$PYTHON" > test.sh <<EOF
   > print u'''
   > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
   > echo ====
diff --git a/tests/test-run-tests.t b/tests/test-run-tests.t
--- a/tests/test-run-tests.t
+++ b/tests/test-run-tests.t
@@ -6,7 +6,7 @@  Avoid interference from actual test env:
 
 Smoke test with install
 ============
-  $ $PYTHON $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE -l
+  $ "$PYTHON" $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE -l
   
   # Ran 0 tests, 0 skipped, 0 failed.
 
@@ -14,14 +14,14 @@  Define a helper to avoid the install ste
 =============
   $ rt()
   > {
-  >     $PYTHON $TESTDIR/run-tests.py --with-hg=`which hg` "$@"
+  >     "$PYTHON" $TESTDIR/run-tests.py --with-hg=`which hg` "$@"
   > }
 
 error paths
 
 #if symlink
   $ ln -s `which true` hg
-  $ $PYTHON $TESTDIR/run-tests.py --with-hg=./hg
+  $ "$PYTHON" $TESTDIR/run-tests.py --with-hg=./hg
   warning: --with-hg should specify an hg script
   
   # Ran 0 tests, 0 skipped, 0 failed.
@@ -30,7 +30,7 @@  error paths
 
 #if execbit
   $ touch hg
-  $ $PYTHON $TESTDIR/run-tests.py --with-hg=./hg
+  $ "$PYTHON" $TESTDIR/run-tests.py --with-hg=./hg
   usage: run-tests.py [options] [tests]
   run-tests.py: error: --with-hg must specify an executable hg script
   [2]
@@ -1283,7 +1283,7 @@  Test globbing of local IP addresses
 Add support for external test formatter
 =======================================
 
-  $ CUSTOM_TEST_RESULT=basic_test_result $PYTHON $TESTDIR/run-tests.py --with-hg=`which hg` "$@" test-success.t test-failure.t
+  $ CUSTOM_TEST_RESULT=basic_test_result "$PYTHON" $TESTDIR/run-tests.py --with-hg=`which hg` "$@" test-success.t test-failure.t
   
   # Ran 2 tests, 0 skipped, 0 failed.
   ON_START! <__main__.TestSuite tests=[<__main__.TTest testMethod=test-failure.t>, <__main__.TTest testMethod=test-success.t>]>
diff --git a/tests/test-serve.t b/tests/test-serve.t
--- a/tests/test-serve.t
+++ b/tests/test-serve.t
@@ -79,7 +79,7 @@  With --prefix /foo/
   listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?)
   % errors
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
 With out of bounds accesses
 
diff --git a/tests/test-setdiscovery.t b/tests/test-setdiscovery.t
--- a/tests/test-setdiscovery.t
+++ b/tests/test-setdiscovery.t
@@ -504,9 +504,9 @@  Issue 4438 - test coverage for 3ef893520
 #if false
 generate new bundles:
   $ hg init r1
-  $ for i in `$PYTHON $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
   $ hg clone -q r1 r2
-  $ for i in `$PYTHON $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
   $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change
   $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg
   $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg
diff --git a/tests/test-simple-update.t b/tests/test-simple-update.t
--- a/tests/test-simple-update.t
+++ b/tests/test-simple-update.t
@@ -79,7 +79,7 @@  update with worker processes
   > [worker]
   > numcpus = 4
   > EOF
-  $ for i in `$PYTHON $TESTDIR/seq.py 1 100`; do
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 1 100`; do
   >   echo $i > $i
   > done
   $ hg ci -qAm 'add 100 files'
diff --git a/tests/test-sparse-clone.t b/tests/test-sparse-clone.t
--- a/tests/test-sparse-clone.t
+++ b/tests/test-sparse-clone.t
@@ -2,7 +2,7 @@  test sparse
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$RUNTESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$RUNTESTDIR/dummyssh"
   > username = nobody <no.reply@fb.com>
   > [extensions]
   > sparse=
diff --git a/tests/test-sparse.t b/tests/test-sparse.t
--- a/tests/test-sparse.t
+++ b/tests/test-sparse.t
@@ -294,7 +294,7 @@  Mix files and subdirectories, both "glob
   $ touch dir1/notshown
   $ hg commit -A dir1/notshown -m "notshown"
   $ hg debugsparse --include 'dir1/dir2'
-  $ $PYTHON $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
+  $ "$PYTHON" $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
   ./
   ./dir1/
   ./dir1/dir2/
@@ -302,7 +302,7 @@  Mix files and subdirectories, both "glob
   ./hide.orig
   $ hg debugsparse --delete 'dir1/dir2'
   $ hg debugsparse --include 'glob:dir1/dir2'
-  $ $PYTHON $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
+  $ "$PYTHON" $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
   ./
   ./dir1/
   ./dir1/dir2/
diff --git a/tests/test-split.t b/tests/test-split.t
--- a/tests/test-split.t
+++ b/tests/test-split.t
@@ -1,7 +1,7 @@ 
 #testcases obsstore-on obsstore-off
 
   $ cat > $TESTTMP/editor.py <<EOF
-  > #!$PYTHON
+  > #!"$PYTHON"
   > import os
   > import sys
   > path = os.path.join(os.environ['TESTTMP'], 'messages')
diff --git a/tests/test-ssh-bundle1.t b/tests/test-ssh-bundle1.t
--- a/tests/test-ssh-bundle1.t
+++ b/tests/test-ssh-bundle1.t
@@ -395,7 +395,7 @@  parameters:
   abort: no suitable response from remote hg!
   [255]
 
-  $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" $PYTHON "$TESTDIR/../contrib/hg-ssh"
+  $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" "$PYTHON" "$TESTDIR/../contrib/hg-ssh"
   Illegal command "'hg' serve -R 'a'repo' --stdio": No closing quotation
   [255]
 
diff --git a/tests/test-ssh-proto.t b/tests/test-ssh-proto.t
--- a/tests/test-ssh-proto.t
+++ b/tests/test-ssh-proto.t
@@ -22,7 +22,7 @@  protocols with inline conditional output
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > [devel]
   > debug.peer-request = true
   > [extensions]
diff --git a/tests/test-ssh-repoerror.t b/tests/test-ssh-repoerror.t
--- a/tests/test-ssh-repoerror.t
+++ b/tests/test-ssh-repoerror.t
@@ -4,7 +4,7 @@  initial setup
 
   $ cat << EOF >> $HGRCPATH
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > EOF
 
 repository itself is non-readable
diff --git a/tests/test-ssh.t b/tests/test-ssh.t
--- a/tests/test-ssh.t
+++ b/tests/test-ssh.t
@@ -284,7 +284,7 @@  a bad, evil hook that prints to stdout
 
   $ cat <<EOF >> ../remote/.hg/hgrc
   > [hooks]
-  > changegroup.stdout = $PYTHON $TESTTMP/badhook
+  > changegroup.stdout = "$PYTHON" $TESTTMP/badhook
   > changegroup.pystdout = python:$TESTTMP/badpyhook.py:hook
   > EOF
   $ echo r > r
@@ -408,7 +408,7 @@  parameters:
   abort: no suitable response from remote hg!
   [255]
 
-  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" $PYTHON "$TESTDIR/../contrib/hg-ssh"
+  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" "$PYTHON" "$TESTDIR/../contrib/hg-ssh"
   Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
   [255]
 
diff --git a/tests/test-static-http.t b/tests/test-static-http.t
--- a/tests/test-static-http.t
+++ b/tests/test-static-http.t
@@ -9,7 +9,7 @@ 
 This server doesn't do range requests so it's basically only good for
 one pull
 
-  $ $PYTHON "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid \
+  $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid \
   > --logfile server.log
   $ cat dumb.pid >> $DAEMON_PIDS
   $ hg init remote
diff --git a/tests/test-status-rev.t b/tests/test-status-rev.t
--- a/tests/test-status-rev.t
+++ b/tests/test-status-rev.t
@@ -5,7 +5,7 @@  combined correctly with the dirstate sta
 
 First commit
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove --similarity 0
   adding content1_content1_content1-tracked
   adding content1_content1_content1-untracked
@@ -31,7 +31,7 @@  First commit
 
 Second commit
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove --similarity 0
   removing content1_missing_content1-tracked
   removing content1_missing_content1-untracked
@@ -49,7 +49,7 @@  Second commit
 
 Working copy
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove --similarity 0
   adding content1_missing_content1-tracked
   adding content1_missing_content1-untracked
diff --git a/tests/test-subrepo-svn.t b/tests/test-subrepo-svn.t
--- a/tests/test-subrepo-svn.t
+++ b/tests/test-subrepo-svn.t
@@ -2,9 +2,9 @@ 
 
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
   $ filter_svn_output () {
@@ -247,7 +247,7 @@  debugsub in clone
 
 verify subrepo is contained within the repo directory
 
-  $ $PYTHON -c "import os.path; print os.path.exists('s')"
+  $ "$PYTHON" -c "import os.path; print os.path.exists('s')"
   True
 
 update to nullrev (must delete the subrepo)
diff --git a/tests/test-tag.t b/tests/test-tag.t
--- a/tests/test-tag.t
+++ b/tests/test-tag.t
@@ -230,7 +230,7 @@  cloning local tags
 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
 doesn't end with EOL
 
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > f = open('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
   > f = open('.hg/localtags', 'w'); f.write(last); f.close()
   > EOF
@@ -242,7 +242,7 @@  doesn't end with EOL
   c2899151f4e76890c602a2597a650a72666681bf localnewline
   
 
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > f = open('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
   > f = open('.hgtags', 'w'); f.write(last); f.close()
   > EOF
diff --git a/tests/test-template-functions.t b/tests/test-template-functions.t
--- a/tests/test-template-functions.t
+++ b/tests/test-template-functions.t
@@ -1393,7 +1393,7 @@  Set up repository for non-ascii encoding
 
   $ hg init nonascii
   $ cd nonascii
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > open('latin1', 'wb').write(b'\xe9')
   > open('utf-8', 'wb').write(b'\xc3\xa9')
   > EOF
diff --git a/tests/test-tools.t b/tests/test-tools.t
--- a/tests/test-tools.t
+++ b/tests/test-tools.t
@@ -51,10 +51,10 @@  Tests of the file helper tool
 #endif
 
 #if no-windows
-  $ $PYTHON $TESTDIR/seq.py 10 > bar
+  $ "$PYTHON" $TESTDIR/seq.py 10 > bar
 #else
 Convert CRLF -> LF for consistency
-  $ $PYTHON $TESTDIR/seq.py 10 | sed "s/$//" > bar
+  $ "$PYTHON" $TESTDIR/seq.py 10 | sed "s/$//" > bar
 #endif
 
 #if unix-permissions symlink
diff --git a/tests/test-transplant.t b/tests/test-transplant.t
--- a/tests/test-transplant.t
+++ b/tests/test-transplant.t
@@ -758,7 +758,7 @@  test with a win32ext like setup (differi
   $ cd twin2
   $ echo '[patch]' >> .hg/hgrc
   $ echo 'eol = crlf' >> .hg/hgrc
-  $ $PYTHON -c "open('b', 'wb').write(b'b\r\nb\r\n')"
+  $ "$PYTHON" -c "open('b', 'wb').write(b'b\r\nb\r\n')"
   $ hg ci -Am addb
   adding b
   $ hg transplant -s ../twin1 tip
diff --git a/tests/test-treemanifest.t b/tests/test-treemanifest.t
--- a/tests/test-treemanifest.t
+++ b/tests/test-treemanifest.t
@@ -1,6 +1,6 @@ 
   $ cat << EOF >> $HGRCPATH
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > EOF
 
 Set up repo
diff --git a/tests/test-walk.t b/tests/test-walk.t
--- a/tests/test-walk.t
+++ b/tests/test-walk.t
@@ -603,13 +603,13 @@  Test patterns:
 
 Test listfile and listfile0
 
-  $ $PYTHON -c "open('listfile0', 'wb').write(b'fenugreek\0new\0')"
+  $ "$PYTHON" -c "open('listfile0', 'wb').write(b'fenugreek\0new\0')"
   $ hg debugwalk -v -I 'listfile0:listfile0'
   * matcher:
   <includematcher includes='(?:fenugreek(?:/|$)|new(?:/|$))'>
   f  fenugreek  fenugreek
   f  new        new
-  $ $PYTHON -c "open('listfile', 'wb').write(b'fenugreek\nnew\r\nmammals/skunk\n')"
+  $ "$PYTHON" -c "open('listfile', 'wb').write(b'fenugreek\nnew\r\nmammals/skunk\n')"
   $ hg debugwalk -v -I 'listfile:listfile'
   * matcher:
   <includematcher includes='(?:fenugreek(?:/|$)|new(?:/|$)|mammals/skunk(?:/|$))'>
@@ -644,7 +644,7 @@  Test split patterns on overflow
   > for i in range(20000 // 100):
   >   print('x' * 100)
   > EOF
-  $ $PYTHON printnum.py >> overflow.list
+  $ "$PYTHON" printnum.py >> overflow.list
   $ echo fenugreek >> overflow.list
   $ hg debugwalk 'listfile:overflow.list' 2>&1 | egrep -v '^xxx'
   f  fennel     fennel     exact
diff --git a/tests/test-win32text.t b/tests/test-win32text.t
--- a/tests/test-win32text.t
+++ b/tests/test-win32text.t
@@ -28,7 +28,7 @@  commit should succeed
   updating to branch default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cp .hg/hgrc ../zoz/.hg
-  $ $PYTHON unix2dos.py f
+  $ "$PYTHON" unix2dos.py f
 
 commit should fail
 
@@ -102,7 +102,7 @@  and now for something completely differe
 
   $ mkdir d
   $ echo hello > d/f2
-  $ $PYTHON unix2dos.py d/f2
+  $ "$PYTHON" unix2dos.py d/f2
   $ hg add d/f2
   $ hg ci -m 3
   attempt to commit or push text file(s) using CRLF line endings
@@ -118,7 +118,7 @@  and now for something completely differe
   $ hg rem f
   $ hg ci -m 4
 
-  $ $PYTHON -c 'open("bin", "wb").write(b"hello\x00\x0D\x0A")'
+  $ "$PYTHON" -c 'open("bin", "wb").write(b"hello\x00\x0D\x0A")'
   $ hg add bin
   $ hg ci -m 5
   $ hg log -v
@@ -181,7 +181,7 @@  and now for something completely differe
   adding dupe/b
   adding dupe/c
   adding dupe/d
-  $ $PYTHON unix2dos.py dupe/b dupe/c dupe/d
+  $ "$PYTHON" unix2dos.py dupe/b dupe/c dupe/d
   $ hg -R dupe ci -m a dupe/a
   $ hg -R dupe ci -m b/c dupe/[bc]
   $ hg -R dupe ci -m d dupe/d
@@ -342,7 +342,7 @@  and now for something completely differe
   
   $ rm .hg/hgrc
   $ (echo some; echo text) > f3
-  $ $PYTHON -c 'open("f4.bat", "wb").write(b"rem empty\x0D\x0A")'
+  $ "$PYTHON" -c 'open("f4.bat", "wb").write(b"rem empty\x0D\x0A")'
   $ hg add f3 f4.bat
   $ hg ci -m 6
   $ cat bin
@@ -395,7 +395,7 @@  Disable warning:
   $ cat f4.bat
   rem empty\r (esc)
 
-  $ $PYTHON -c 'open("f5.sh", "wb").write(b"# empty\x0D\x0A")'
+  $ "$PYTHON" -c 'open("f5.sh", "wb").write(b"# empty\x0D\x0A")'
   $ hg add f5.sh
   $ hg ci -m 7
   $ cat f5.sh