Commit 11f53d69 authored by Gavin Mak's avatar Gavin Mak Committed by LUCI CQ

Reland "Add python3 support to bot_update recipe module"

This is a reland of edb6e8c5

Original change's description:
> Add python3 support to bot_update recipe module
>
> Bug: 1227140
> Change-Id: Id4938c966da54957f84f59d0aef0c68c381ad5f6
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3016032
> Reviewed-by: Josip Sokcevic <sokcevic@google.com>
> Commit-Queue: Gavin Mak <gavinmak@google.com>

Bug: 1227140
Change-Id: I2d35d29f87236ce10ecabca41712cf1c90de8136
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3022310Reviewed-by: 's avatarAnthony Polito <apolito@google.com>
Reviewed-by: 's avatarEdward Lesmes <ehmaldonado@chromium.org>
Commit-Queue: Gavin Mak <gavinmak@google.com>
parent b2283a3d
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
# TODO(hinoka): Use logging. # TODO(hinoka): Use logging.
from __future__ import division
from __future__ import print_function from __future__ import print_function
import cStringIO
import codecs import codecs
from contextlib import contextmanager from contextlib import contextmanager
import copy import copy
...@@ -18,19 +18,23 @@ import json ...@@ -18,19 +18,23 @@ import json
import optparse import optparse
import os import os
import pprint import pprint
import random
import re import re
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
import threading import threading
import time import time
import urllib2
import urlparse
import uuid import uuid
import os.path as path import os.path as path
# TODO(crbug.com/1227140): Clean up when py2 is no longer supported.
from io import BytesIO
try:
import urlparse
except ImportError: # pragma: no cover
import urllib.parse as urlparse
# How many bytes at a time to read from pipes. # How many bytes at a time to read from pipes.
BUF_SIZE = 256 BUF_SIZE = 256
...@@ -94,7 +98,7 @@ GCLIENT_PATH = path.join(DEPOT_TOOLS_DIR, 'gclient.py') ...@@ -94,7 +98,7 @@ GCLIENT_PATH = path.join(DEPOT_TOOLS_DIR, 'gclient.py')
class SubprocessFailed(Exception): class SubprocessFailed(Exception):
def __init__(self, message, code, output): def __init__(self, message, code, output):
Exception.__init__(self, message) self.message = message
self.code = code self.code = code
self.output = output self.output = output
...@@ -161,6 +165,14 @@ def _terminate_process(proc): ...@@ -161,6 +165,14 @@ def _terminate_process(proc):
proc.terminate() proc.terminate()
# TODO(crbug.com/1227140): Clean up when py2 is no longer supported.
def _stdout_write(buf):
try:
sys.stdout.buffer.write(buf)
except AttributeError:
sys.stdout.write(buf)
def call(*args, **kwargs): # pragma: no cover def call(*args, **kwargs): # pragma: no cover
"""Interactive subprocess call.""" """Interactive subprocess call."""
kwargs['stdout'] = subprocess.PIPE kwargs['stdout'] = subprocess.PIPE
...@@ -170,7 +182,7 @@ def call(*args, **kwargs): # pragma: no cover ...@@ -170,7 +182,7 @@ def call(*args, **kwargs): # pragma: no cover
stdin_data = kwargs.pop('stdin_data', None) stdin_data = kwargs.pop('stdin_data', None)
if stdin_data: if stdin_data:
kwargs['stdin'] = subprocess.PIPE kwargs['stdin'] = subprocess.PIPE
out = cStringIO.StringIO() out = BytesIO()
new_env = kwargs.get('env', {}) new_env = kwargs.get('env', {})
env = os.environ.copy() env = os.environ.copy()
env.update(new_env) env.update(new_env)
...@@ -209,17 +221,17 @@ def call(*args, **kwargs): # pragma: no cover ...@@ -209,17 +221,17 @@ def call(*args, **kwargs): # pragma: no cover
if hanging_cr: if hanging_cr:
buf = buf[:-1] buf = buf[:-1]
buf = buf.replace('\r\n', '\n').replace('\r', '\n') buf = buf.replace('\r\n', '\n').replace('\r', '\n')
sys.stdout.write(buf) _stdout_write(buf)
out.write(buf) out.write(buf)
if hanging_cr: if hanging_cr:
sys.stdout.write('\n') _stdout_write('\n')
out.write('\n') out.write('\n')
for observer in observers: for observer in observers:
observer.shutdown() observer.shutdown()
code = proc.wait() code = proc.wait()
elapsed_time = ((time.time() - start_time) / 60.0) elapsed_time = ((time.time() - start_time) / 60.0)
outval = out.getvalue() outval = out.getvalue().decode('utf-8')
if code: if code:
print('%s ===Failed in %.1f mins of %s ===' % print('%s ===Failed in %.1f mins of %s ===' %
(datetime.now(), elapsed_time, ' '.join(args))) (datetime.now(), elapsed_time, ' '.join(args)))
...@@ -455,7 +467,7 @@ def create_manifest(): ...@@ -455,7 +467,7 @@ def create_manifest():
for path, info in json.load(f).items() for path, info in json.load(f).items()
if info['rev'] is not None if info['rev'] is not None
} }
except ValueError, SubprocessFailed: except (ValueError, SubprocessFailed):
return {} return {}
finally: finally:
os.remove(fname) os.remove(fname)
...@@ -598,7 +610,7 @@ def _maybe_break_locks(checkout_path, tries=3): ...@@ -598,7 +610,7 @@ def _maybe_break_locks(checkout_path, tries=3):
print('FAILED to break lock: %s: %s' % (to_break, ex)) print('FAILED to break lock: %s: %s' % (to_break, ex))
raise raise
for _ in xrange(tries): for _ in range(tries):
try: try:
attempt() attempt()
return return
...@@ -816,7 +828,7 @@ def emit_json(out_file, did_run, **kwargs): ...@@ -816,7 +828,7 @@ def emit_json(out_file, did_run, **kwargs):
output.update({'did_run': did_run}) output.update({'did_run': did_run})
output.update(kwargs) output.update(kwargs)
with open(out_file, 'wb') as f: with open(out_file, 'wb') as f:
f.write(json.dumps(output, sort_keys=True)) f.write(json.dumps(output, sort_keys=True).encode('utf-8'))
@_set_git_config @_set_git_config
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment