Make our Python scripts Python-3-compatible.

They still need to be Python-2-compatible until I figure out how to
switch the version used in the CI.

I've left out make_curve25519_tables.py because it's some bytes vs
unicode mess I don't care to figure out. We should just rewrite that in
Go which should also be much faster anyway.

Change-Id: I4446641815315a84c2979b1be1e1949f88cbacf8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46884
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/hpke/translate_test_vectors.py b/crypto/hpke/translate_test_vectors.py
index 1fa6cbc..edc86c3 100755
--- a/crypto/hpke/translate_test_vectors.py
+++ b/crypto/hpke/translate_test_vectors.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # coding=utf-8
 # Copyright (c) 2020, Google Inc.
 #
diff --git a/util/bot/go/env.py b/util/bot/go/env.py
index 91eace0..b9c33e2 100755
--- a/util/bot/go/env.py
+++ b/util/bot/go/env.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
diff --git a/util/bot/update_clang.py b/util/bot/update_clang.py
index f959280..5e9c0c2 100644
--- a/util/bot/update_clang.py
+++ b/util/bot/update_clang.py
@@ -1,10 +1,13 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
 """This script is used to download prebuilt clang binaries."""
 
+from __future__ import division
+from __future__ import print_function
+
 import os
 import shutil
 import subprocess
@@ -13,7 +16,13 @@
 import tarfile
 import tempfile
 import time
-import urllib2
+
+try:
+  # Python 3.0 or later
+  from urllib.error import HTTPError, URLError
+  from urllib.request import urlopen
+except ImportError:
+  from urllib2 import urlopen, HTTPError, URLError
 
 
 # CLANG_REVISION and CLANG_SUB_REVISION determine the build of clang
@@ -45,8 +54,8 @@
     try:
       sys.stdout.write('Downloading %s ' % url)
       sys.stdout.flush()
-      response = urllib2.urlopen(url)
-      total_size = int(response.info().getheader('Content-Length').strip())
+      response = urlopen(url)
+      total_size = int(response.headers.get('Content-Length').strip())
       bytes_done = 0
       dots_printed = 0
       while True:
@@ -55,29 +64,28 @@
           break
         output_file.write(chunk)
         bytes_done += len(chunk)
-        num_dots = TOTAL_DOTS * bytes_done / total_size
+        num_dots = TOTAL_DOTS * bytes_done // total_size
         sys.stdout.write('.' * (num_dots - dots_printed))
         sys.stdout.flush()
         dots_printed = num_dots
       if bytes_done != total_size:
-        raise urllib2.URLError("only got %d of %d bytes" %
-                               (bytes_done, total_size))
-      print ' Done.'
+        raise URLError("only got %d of %d bytes" % (bytes_done, total_size))
+      print(' Done.')
       return
-    except urllib2.URLError as e:
+    except URLError as e:
       sys.stdout.write('\n')
-      print e
-      if num_retries == 0 or isinstance(e, urllib2.HTTPError) and e.code == 404:
+      print(e)
+      if num_retries == 0 or isinstance(e, HTTPError) and e.code == 404:
         raise e
       num_retries -= 1
-      print 'Retrying in %d s ...' % retry_wait_s
+      print('Retrying in %d s ...' % retry_wait_s)
       time.sleep(retry_wait_s)
       retry_wait_s *= 2
 
 
 def EnsureDirExists(path):
   if not os.path.exists(path):
-    print "Creating directory %s" % path
+    print("Creating directory %s" % path)
     os.makedirs(path)
 
 
@@ -120,7 +128,7 @@
 
 def CopyFile(src, dst):
   """Copy a file from src to dst."""
-  print "Copying %s to %s" % (src, dst)
+  print("Copying %s to %s" % (src, dst))
   shutil.copy(src, dst)
 
 
@@ -133,32 +141,30 @@
   else:
     return 0
 
-  print 'Updating Clang to %s...' % PACKAGE_VERSION
+  print('Updating Clang to %s...' % PACKAGE_VERSION)
 
   if ReadStampFile() == PACKAGE_VERSION:
-    print 'Clang is already up to date.'
+    print('Clang is already up to date.')
     return 0
 
   # Reset the stamp file in case the build is unsuccessful.
   WriteStampFile('')
 
-  print 'Downloading prebuilt clang'
+  print('Downloading prebuilt clang')
   if os.path.exists(LLVM_BUILD_DIR):
     RmTree(LLVM_BUILD_DIR)
   try:
     DownloadAndUnpack(cds_full_url, LLVM_BUILD_DIR)
-    print 'clang %s unpacked' % PACKAGE_VERSION
+    print('clang %s unpacked' % PACKAGE_VERSION)
     WriteStampFile(PACKAGE_VERSION)
     return 0
-  except urllib2.URLError:
-    print 'Failed to download prebuilt clang %s' % cds_file
-    print 'Exiting.'
+  except URLError:
+    print('Failed to download prebuilt clang %s' % cds_file)
+    print('Exiting.')
     return 1
 
 
 def main():
-  # Don't buffer stdout, so that print statements are immediately flushed.
-  sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
   return UpdateClang()
 
 
diff --git a/util/bot/vs_env.py b/util/bot/vs_env.py
index 13217ca..cbbdd43 100644
--- a/util/bot/vs_env.py
+++ b/util/bot/vs_env.py
@@ -12,13 +12,15 @@
 # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
+from __future__ import print_function
+
 import subprocess
 import sys
 
 import vs_toolchain
 
 if len(sys.argv) < 2:
-  print >>sys.stderr, "Usage: vs_env.py TARGET_ARCH CMD..."
+  print("Usage: vs_env.py TARGET_ARCH CMD...", file=sys.stderr)
   sys.exit(1)
 
 target_arch = sys.argv[1]
diff --git a/util/bot/vs_toolchain.py b/util/bot/vs_toolchain.py
index 954b670..051d78b 100644
--- a/util/bot/vs_toolchain.py
+++ b/util/bot/vs_toolchain.py
@@ -2,6 +2,8 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from __future__ import print_function
+
 import json
 import os
 import os.path
@@ -96,7 +98,7 @@
       'update': Update,
   }
   if len(sys.argv) < 2 or sys.argv[1] not in commands:
-    print >>sys.stderr, 'Expected one of: %s' % ', '.join(commands)
+    print('Expected one of: %s' % ', '.join(commands), file=sys.stderr)
     return 1
   return commands[sys.argv[1]](*sys.argv[2:])