From c2f74c1698a8e75f9474b92dcd69c73178d240b8 Mon Sep 17 00:00:00 2001 From: Raul Tambre Date: Tue, 19 Mar 2019 05:55:53 +0000 Subject: [PATCH] Make fetch compatible with Python 3 The scripts still work with Python 2. There are no intended behaviour changes. Bug: 939847 Change-Id: Icada60c5b2cf351d62aead26b7364fcef2c2a3e5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/1524486 Reviewed-by: Dirk Pranke Commit-Queue: Raul Tambre --- fetch.py | 37 +++++++++++++++++++----------------- fetch_configs/config_util.py | 6 ++++-- gclient_scm.py | 3 ++- gclient_utils.py | 2 +- git_common.py | 15 +++++++++------ 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/fetch.py b/fetch.py index d911c0668..da4741dd0 100755 --- a/fetch.py +++ b/fetch.py @@ -18,6 +18,8 @@ Optional arguments may be passed on the command line in key-value pairs. These parameters will be passed through to the config's main method. """ +from __future__ import print_function + import json import optparse import os @@ -62,7 +64,7 @@ class Checkout(object): pass def run(self, cmd, return_stdout=False, **kwargs): - print 'Running: %s' % (' '.join(pipes.quote(x) for x in cmd)) + print('Running: %s' % (' '.join(pipes.quote(x) for x in cmd))) if self.options.dry_run: return '' if return_stdout: @@ -94,7 +96,7 @@ class GclientCheckout(Checkout): class GitCheckout(Checkout): def run_git(self, *cmd, **kwargs): - print 'Running: git %s' % (' '.join(pipes.quote(x) for x in cmd)) + print('Running: git %s' % (' '.join(pipes.quote(x) for x in cmd))) if self.options.dry_run: return '' return git_common.run(*cmd, **kwargs) @@ -108,15 +110,16 @@ class GclientGitCheckout(GclientCheckout, GitCheckout): def _format_spec(self): def _format_literal(lit): - if isinstance(lit, basestring): + if isinstance(lit, str) or (sys.version_info.major == 2 and + isinstance(lit, unicode)): return '"%s"' % lit if isinstance(lit, list): return '[%s]' % ', '.join(_format_literal(i) for i in lit) return '%r' % lit soln_strings = [] for soln in self.spec['solutions']: - soln_string= '\n'.join(' "%s": %s,' % (key, _format_literal(value)) - for key, value in soln.iteritems()) + soln_string = '\n'.join(' "%s": %s,' % (key, _format_literal(value)) + for key, value in soln.items()) soln_strings.append(' {\n%s\n },' % soln_string) gclient_spec = 'solutions = [\n%s\n]\n' % '\n'.join(soln_strings) extra_keys = ['target_os', 'target_os_only', 'cache_dir'] @@ -139,7 +142,7 @@ class GclientGitCheckout(GclientCheckout, GitCheckout): # Configure git. wd = os.path.join(self.base, self.root) if self.options.dry_run: - print 'cd %s' % wd + print('cd %s' % wd) self.run_git( 'submodule', 'foreach', 'git config -f $toplevel/.git/config submodule.$name.ignore all', @@ -172,9 +175,9 @@ def CheckoutFactory(type_name, options, spec, root): def usage(msg=None): """Print help and exit.""" if msg: - print 'Error:', msg + print('Error:', msg) - print textwrap.dedent("""\ + print(textwrap.dedent("""\ usage: %s [options] [--property=value [--property2=value2 ...]] This script can be used to download the Chromium sources. See @@ -188,13 +191,13 @@ def usage(msg=None): -n, --dry-run Don't run commands, only print them. --no-history Perform shallow clones, don't fetch the full git history. - Valid fetch configs:""") % os.path.basename(sys.argv[0]) + Valid fetch configs:""") % os.path.basename(sys.argv[0])) configs_dir = os.path.join(SCRIPT_PATH, 'fetch_configs') configs = [f[:-3] for f in os.listdir(configs_dir) if f.endswith('.py')] configs.sort() for fname in configs: - print ' ' + fname + print(' ' + fname) sys.exit(bool(msg)) @@ -251,7 +254,7 @@ def run_config_fetch(config, props, aliased=False): config_path = os.path.abspath( os.path.join(SCRIPT_PATH, 'fetch_configs', config)) if not os.path.exists(config_path + '.py'): - print "Could not find a config for %s" % config + print("Could not find a config for %s" % config) sys.exit(1) cmd = [sys.executable, config_path + '.py', 'fetch'] + props @@ -285,12 +288,12 @@ def run(options, spec, root): except KeyError: return 1 if not options.force and checkout.exists(): - print 'Your current directory appears to already contain, or be part of, ' - print 'a checkout. "fetch" is used only to get new checkouts. Use ' - print '"gclient sync" to update existing checkouts.' - print - print 'Fetch also does not yet deal with partial checkouts, so if fetch' - print 'failed, delete the checkout and start over (crbug.com/230691).' + print('Your current directory appears to already contain, or be part of, ') + print('a checkout. "fetch" is used only to get new checkouts. Use ') + print('"gclient sync" to update existing checkouts.') + print() + print('Fetch also does not yet deal with partial checkouts, so if fetch') + print('failed, delete the checkout and start over (crbug.com/230691).') return 1 return checkout.init() diff --git a/fetch_configs/config_util.py b/fetch_configs/config_util.py index 9207d39a2..072b1636f 100644 --- a/fetch_configs/config_util.py +++ b/fetch_configs/config_util.py @@ -4,6 +4,8 @@ """This module holds utilities which make writing configs easier.""" +from __future__ import print_function + import json @@ -29,7 +31,7 @@ class Config(object): methods = {'fetch': self.fetch_spec, 'root': self.expected_root} if len(argv) <= 1 or argv[1] not in methods: - print 'Must specify a a fetch/root action' + print('Must specify a a fetch/root action') return 1 def looks_like_arg(arg): @@ -37,7 +39,7 @@ class Config(object): bad_parms = [x for x in argv[2:] if not looks_like_arg(x)] if bad_parms: - print 'Got bad arguments %s' % bad_parms + print('Got bad arguments %s' % bad_parms) return 1 method = methods[argv[1]] diff --git a/gclient_scm.py b/gclient_scm.py index a95bdab83..69faa6cbc 100644 --- a/gclient_scm.py +++ b/gclient_scm.py @@ -556,7 +556,8 @@ class GitWrapper(SCMWrapper): if file_list is not None: files = self._Capture( ['-c', 'core.quotePath=false', 'ls-files']).splitlines() - file_list.extend([os.path.join(self.checkout_path, f) for f in files]) + file_list.extend( + [os.path.join(self.checkout_path, f.decode()) for f in files]) if mirror: self._Capture( ['remote', 'set-url', '--push', 'origin', mirror.url]) diff --git a/gclient_utils.py b/gclient_utils.py index 91692f8fa..48c023fdd 100644 --- a/gclient_utils.py +++ b/gclient_utils.py @@ -225,7 +225,7 @@ def rmtree(path): if sys.platform == 'win32': # Give up and use cmd.exe's rd command. path = os.path.normcase(path) - for _ in xrange(3): + for _ in range(3): exitcode = subprocess.call(['cmd.exe', '/c', 'rd', '/q', '/s', path]) if exitcode == 0: return diff --git a/git_common.py b/git_common.py index e837519c6..f5edfb167 100644 --- a/git_common.py +++ b/git_common.py @@ -4,6 +4,9 @@ # Monkeypatch IMapIterator so that Ctrl-C can kill everything properly. # Derived from https://gist.github.com/aljungberg/626518 + +from __future__ import print_function + import multiprocessing.pool from multiprocessing.pool import IMapIterator def wrapper(func): @@ -32,7 +35,7 @@ import threading import subprocess2 -from StringIO import StringIO +from io import BytesIO ROOT = os.path.abspath(os.path.dirname(__file__)) @@ -310,7 +313,7 @@ def once(function): ## Git functions def die(message, *args): - print >> sys.stderr, textwrap.dedent(message % args) + print(textwrap.dedent(message % args), file=sys.stderr) sys.exit(1) @@ -805,14 +808,14 @@ def status(): stat_entry = collections.namedtuple('stat_entry', 'lstat rstat src') def tokenizer(stream): - acc = StringIO() + acc = BytesIO() c = None while c != '': c = stream.read(1) if c in (None, '', '\0'): - if acc.len: + if len(acc.getvalue()): yield acc.getvalue() - acc = StringIO() + acc = BytesIO() else: acc.write(c) @@ -843,7 +846,7 @@ def squash_current_branch(header=None, merge_base=None): if not get_dirty_files(): # Sometimes the squash can result in the same tree, meaning that there is # nothing to commit at this point. - print 'Nothing to commit; squashed branch is empty' + print('Nothing to commit; squashed branch is empty') return False run('commit', '--no-verify', '-a', '-F', '-', indata=log_msg) return True