py3: allow run-tests.py to run on Windows
authorMatt Harbison <matt_harbison@yahoo.com>
Sat, 15 Sep 2018 00:04:06 -0400
changeset 39647 543a788eea2d
parent 39646 f3d1229555d9
child 39648 e37a0fcd82c0
py3: allow run-tests.py to run on Windows This is now functional: HGMODULEPOLICY=py py -3 run-tests.py --local test-help.t --pure --view bcompare However, on this machine without a C compiler, it tries to load cext anyway, and blows up. I haven't looked into why, other than to see that it does set the environment variable. When the test exits though, I see it can't find killdaemons.py, get-with-headers.py, etc. I have no idea why these changes are needed, given that it runs on Linux. But os.system() is insisting that it take a str, and subprocess.Popen() blows up without str: Errored test-help.t: Traceback (most recent call last): File "run-tests.py", line 810, in run self.runTest() File "run-tests.py", line 858, in runTest ret, out = self._run(env) File "run-tests.py", line 1268, in _run exitcode, output = self._runcommand(cmd, env) File "run-tests.py", line 1141, in _runcommand env=env) File "C:\Program Files\Python37\lib\subprocess.py", line 756, in __init__ restore_signals, start_new_session) File "C:\Program Files\Python37\lib\subprocess.py", line 1100, in _execute_child args = list2cmdline(args) File "C:\Program Files\Python37\lib\subprocess.py", line 511, in list2cmdline needquote = (" " in arg) or ("\t" in arg) or not arg TypeError: argument of type 'int' is not iterable This is exactly how it crashes when trying to spin up a pager too. I left one instance of os.system() unchanged in _installhg(), because it doesn't get there.
tests/run-tests.py
--- a/tests/run-tests.py	Fri Sep 14 23:04:18 2018 -0400
+++ b/tests/run-tests.py	Sat Sep 15 00:04:06 2018 -0400
@@ -229,7 +229,8 @@
 closefds = os.name == 'posix'
 def Popen4(cmd, wd, timeout, env=None):
     processlock.acquire()
-    p = subprocess.Popen(cmd, shell=True, bufsize=-1, cwd=wd, env=env,
+    p = subprocess.Popen(_strpath(cmd), shell=True, bufsize=-1,
+                         cwd=_strpath(wd), env=env,
                          close_fds=closefds,
                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                          stderr=subprocess.STDOUT)
@@ -988,7 +989,7 @@
             return (
                 (b''.join(c.isalpha() and b'[%s%s]' % (c.lower(), c.upper()) or
                     c in b'/\\' and br'[/\\]' or c.isdigit() and c or b'\\' + c
-                    for c in p))
+                    for c in [p[i:i + 1] for i in range(len(p))]))
             )
         else:
             return re.escape(p)
@@ -1137,7 +1138,8 @@
         Return a tuple (exitcode, output). output is None in debug mode.
         """
         if self._debug:
-            proc = subprocess.Popen(cmd, shell=True, cwd=self._testtmp,
+            proc = subprocess.Popen(_strpath(cmd), shell=True,
+                                    cwd=_strpath(self._testtmp),
                                     env=env)
             ret = proc.wait()
             return (ret, None)
@@ -1817,10 +1819,8 @@
                 pass
             elif self._options.view:
                 v = self._options.view
-                if PYTHON3:
-                    v = _bytespath(v)
-                os.system(b"%s %s %s" %
-                          (v, test.refpath, test.errpath))
+                os.system(r"%s %s %s" %
+                          (v, _strpath(test.refpath), _strpath(test.errpath)))
             else:
                 servefail, lines = getdiff(expected, got,
                                            test.refpath, test.errpath)
@@ -2888,7 +2888,10 @@
         """Configure the environment to use the appropriate Python in tests."""
         # Tests must use the same interpreter as us or bad things will happen.
         pyexename = sys.platform == 'win32' and b'python.exe' or b'python'
-        if getattr(os, 'symlink', None):
+
+        # os.symlink() is a thing with py3 on Windows, but it requires
+        # Administrator rights.
+        if getattr(os, 'symlink', None) and os.name != 'nt':
             vlog("# Making python executable in test path a symlink to '%s'" %
                  sys.executable)
             mypython = os.path.join(self._tmpbindir, pyexename)