From d3bda81f9e1a9b043deb62fc8b2c8b25062f2fc7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 29 Sep 2023 11:04:49 -0400 Subject: [PATCH] cleanup: Update codebase to expect Python 3.6 - Bump minimum version to Python 3.6. - Ran pyupgrade for Python 3.6, then again, then - ran black - fixed a lingering unused import, and - removed a duplicate exception. Change-Id: I2aa70197230fcec2eff8e7c8eb754f20c08075bb --- color.py | 4 +- command.py | 11 ++- editor.py | 6 +- event_log.py | 2 +- git_command.py | 14 ++-- git_config.py | 32 ++++----- git_refs.py | 6 +- git_superproject.py | 4 +- git_trace2_event_log_base.py | 4 +- hooks.py | 30 ++++---- main.py | 10 +-- manifest_xml.py | 64 +++++++++-------- platform_utils.py | 5 +- platform_utils_win32.py | 12 ++-- progress.py | 4 +- project.py | 107 +++++++++++++++-------------- release/util.py | 2 +- repo | 70 +++++++++++-------- repo_trace.py | 2 +- ssh.py | 2 +- subcmds/__init__.py | 4 +- subcmds/abandon.py | 4 +- subcmds/branches.py | 4 +- subcmds/checkout.py | 2 +- subcmds/diffmanifests.py | 8 +-- subcmds/help.py | 2 +- subcmds/info.py | 2 +- subcmds/init.py | 2 +- subcmds/list.py | 2 +- subcmds/prune.py | 4 +- subcmds/start.py | 2 +- subcmds/sync.py | 29 ++++---- subcmds/version.py | 4 +- tests/test_git_command.py | 4 +- tests/test_git_config.py | 2 +- tests/test_git_superproject.py | 10 +-- tests/test_git_trace2_event_log.py | 2 +- tests/test_manifest_xml.py | 6 +- tests/test_project.py | 4 +- tests/test_wrapper.py | 2 +- 40 files changed, 248 insertions(+), 242 deletions(-) diff --git a/color.py b/color.py index 0f637489..77517156 100644 --- a/color.py +++ b/color.py @@ -103,7 +103,7 @@ def SetDefaultColoring(state): DEFAULT = "never" -class Coloring(object): +class Coloring: def __init__(self, config, section_type): self._section = "color.%s" % section_type self._config = config @@ -194,7 +194,7 @@ class Coloring(object): if not opt: return _Color(fg, bg, attr) - v = self._config.GetString("%s.%s" % (self._section, opt)) + v = self._config.GetString(f"{self._section}.{opt}") if v is None: return _Color(fg, bg, attr) diff --git a/command.py b/command.py index 9d5d56ee..fa48264b 100644 --- a/command.py +++ b/command.py @@ -46,7 +46,7 @@ class UsageError(RepoExitError): """Exception thrown with invalid command usage.""" -class Command(object): +class Command: """Base class for any command line action in repo.""" # Singleton for all commands to track overall repo command execution and @@ -290,7 +290,7 @@ class Command(object): output.end() def _ResetPathToProjectMap(self, projects): - self._by_path = dict((p.worktree, p) for p in projects) + self._by_path = {p.worktree: p for p in projects} def _UpdatePathToProjectMap(self, project): self._by_path[project.worktree] = project @@ -476,8 +476,7 @@ class Command(object): top = self.manifest yield top if not opt.this_manifest_only: - for child in top.all_children: - yield child + yield from top.all_children class InteractiveCommand(Command): @@ -498,11 +497,11 @@ class PagedCommand(Command): return True -class MirrorSafeCommand(object): +class MirrorSafeCommand: """Command permits itself to run within a mirror, and does not require a working directory. """ -class GitcClientCommand(object): +class GitcClientCommand: """Command that requires the local client to be a GITC client.""" diff --git a/editor.py b/editor.py index 78311f1a..359cff93 100644 --- a/editor.py +++ b/editor.py @@ -22,7 +22,7 @@ from error import EditorError import platform_utils -class Editor(object): +class Editor: """Manages the user's preferred text editor.""" _editor = None @@ -104,9 +104,7 @@ least one of these before using this command.""", # noqa: E501 try: rc = subprocess.Popen(args, shell=shell).wait() except OSError as e: - raise EditorError( - "editor failed, %s: %s %s" % (str(e), editor, path) - ) + raise EditorError(f"editor failed, {str(e)}: {editor} {path}") if rc != 0: raise EditorError( "editor failed with exit status %d: %s %s" diff --git a/event_log.py b/event_log.py index 60c1a437..ef01394a 100644 --- a/event_log.py +++ b/event_log.py @@ -21,7 +21,7 @@ TASK_SYNC_NETWORK = "sync-network" TASK_SYNC_LOCAL = "sync-local" -class EventLog(object): +class EventLog: """Event log that records events that occurred during a repo invocation. Events are written to the log as a consecutive JSON entries, one per line. diff --git a/git_command.py b/git_command.py index 2e4974fa..c2a45174 100644 --- a/git_command.py +++ b/git_command.py @@ -58,7 +58,7 @@ INVALID_GIT_EXIT_CODE = 126 logger = RepoLogger(__file__) -class _GitCall(object): +class _GitCall: @functools.lru_cache(maxsize=None) def version_tuple(self): ret = Wrapper().ParseGitVersion() @@ -148,7 +148,7 @@ def GetEventTargetPath(): return path -class UserAgent(object): +class UserAgent: """Mange User-Agent settings when talking to external services We follow the style as documented here: @@ -196,7 +196,7 @@ class UserAgent(object): def git(self): """The UA when running git.""" if self._git_ua is None: - self._git_ua = "git/%s (%s) git-repo/%s" % ( + self._git_ua = "git/{} ({}) git-repo/{}".format( git.version_tuple().full, self.os, RepoSourceVersion(), @@ -216,7 +216,7 @@ def git_require(min_version, fail=False, msg=""): need = ".".join(map(str, min_version)) if msg: msg = " for " + msg - error_msg = "fatal: git %s or later required%s" % (need, msg) + error_msg = f"fatal: git {need} or later required{msg}" logger.error(error_msg) raise GitRequireError(error_msg) return False @@ -243,7 +243,7 @@ def _build_env( env["GIT_SSH"] = ssh_proxy.proxy env["GIT_SSH_VARIANT"] = "ssh" if "http_proxy" in env and "darwin" == sys.platform: - s = "'http.proxy=%s'" % (env["http_proxy"],) + s = "'http.proxy={}'".format(env["http_proxy"]) p = env.get("GIT_CONFIG_PARAMETERS") if p is not None: s = p + " " + s @@ -272,7 +272,7 @@ def _build_env( return env -class GitCommand(object): +class GitCommand: """Wrapper around a single git invocation.""" def __init__( @@ -468,7 +468,7 @@ class GitCommand(object): ) except Exception as e: raise GitPopenCommandError( - message="%s: %s" % (command[1], e), + message=f"{command[1]}: {e}", project=self.project.name if self.project else None, command_args=self.cmdv, ) diff --git a/git_config.py b/git_config.py index c19f7662..9fda1848 100644 --- a/git_config.py +++ b/git_config.py @@ -70,7 +70,7 @@ def _key(name): return ".".join(parts) -class GitConfig(object): +class GitConfig: _ForUser = None _ForSystem = None @@ -370,7 +370,7 @@ class GitConfig(object): with Trace(": parsing %s", self.file): with open(self._json) as fd: return json.load(fd) - except (IOError, ValueError): + except (OSError, ValueError): platform_utils.remove(self._json, missing_ok=True) return None @@ -378,7 +378,7 @@ class GitConfig(object): try: with open(self._json, "w") as fd: json.dump(cache, fd, indent=2) - except (IOError, TypeError): + except (OSError, TypeError): platform_utils.remove(self._json, missing_ok=True) def _ReadGit(self): @@ -418,7 +418,7 @@ class GitConfig(object): if p.Wait() == 0: return p.stdout else: - raise GitError("git config %s: %s" % (str(args), p.stderr)) + raise GitError(f"git config {str(args)}: {p.stderr}") class RepoConfig(GitConfig): @@ -430,7 +430,7 @@ class RepoConfig(GitConfig): return os.path.join(repo_config_dir, ".repoconfig/config") -class RefSpec(object): +class RefSpec: """A Git refspec line, split into its components: forced: True if the line starts with '+' @@ -541,7 +541,7 @@ def GetUrlCookieFile(url, quiet): yield cookiefile, None -class Remote(object): +class Remote: """Configuration options related to a remote.""" def __init__(self, config, name): @@ -651,13 +651,11 @@ class Remote(object): userEmail, host, port ) except urllib.error.HTTPError as e: - raise UploadError("%s: %s" % (self.review, str(e))) + raise UploadError(f"{self.review}: {str(e)}") except urllib.error.URLError as e: - raise UploadError("%s: %s" % (self.review, str(e))) + raise UploadError(f"{self.review}: {str(e)}") except http.client.HTTPException as e: - raise UploadError( - "%s: %s" % (self.review, e.__class__.__name__) - ) + raise UploadError(f"{self.review}: {e.__class__.__name__}") REVIEW_CACHE[u] = self._review_url return self._review_url + self.projectname @@ -666,7 +664,7 @@ class Remote(object): username = self._config.GetString("review.%s.username" % self.review) if username is None: username = userEmail.split("@")[0] - return "ssh://%s@%s:%s/" % (username, host, port) + return f"ssh://{username}@{host}:{port}/" def ToLocal(self, rev): """Convert a remote revision string to something we have locally.""" @@ -715,15 +713,15 @@ class Remote(object): self._Set("fetch", list(map(str, self.fetch))) def _Set(self, key, value): - key = "remote.%s.%s" % (self.name, key) + key = f"remote.{self.name}.{key}" return self._config.SetString(key, value) def _Get(self, key, all_keys=False): - key = "remote.%s.%s" % (self.name, key) + key = f"remote.{self.name}.{key}" return self._config.GetString(key, all_keys=all_keys) -class Branch(object): +class Branch: """Configuration options related to a single branch.""" def __init__(self, config, name): @@ -762,11 +760,11 @@ class Branch(object): fd.write("\tmerge = %s\n" % self.merge) def _Set(self, key, value): - key = "branch.%s.%s" % (self.name, key) + key = f"branch.{self.name}.{key}" return self._config.SetString(key, value) def _Get(self, key, all_keys=False): - key = "branch.%s.%s" % (self.name, key) + key = f"branch.{self.name}.{key}" return self._config.GetString(key, all_keys=all_keys) diff --git a/git_refs.py b/git_refs.py index 1f5eaab4..237c15ae 100644 --- a/git_refs.py +++ b/git_refs.py @@ -28,7 +28,7 @@ R_WORKTREE_M = R_WORKTREE + "m/" R_M = "refs/remotes/m/" -class GitRefs(object): +class GitRefs: def __init__(self, gitdir): self._gitdir = gitdir self._phyref = None @@ -105,10 +105,8 @@ class GitRefs(object): def _ReadPackedRefs(self): path = os.path.join(self._gitdir, "packed-refs") try: - fd = open(path, "r") + fd = open(path) mtime = os.path.getmtime(path) - except IOError: - return except OSError: return try: diff --git a/git_superproject.py b/git_superproject.py index 5d8c0d4e..b80f0130 100644 --- a/git_superproject.py +++ b/git_superproject.py @@ -66,7 +66,7 @@ class UpdateProjectsResult(NamedTuple): fatal: bool -class Superproject(object): +class Superproject: """Get commit ids from superproject. Initializes a local copy of a superproject for the manifest. This allows @@ -381,7 +381,7 @@ class Superproject(object): try: with open(manifest_path, "w", encoding="utf-8") as fp: fp.write(manifest_str) - except IOError as e: + except OSError as e: self._LogError("cannot write manifest to : {} {}", manifest_path, e) return None return manifest_path diff --git a/git_trace2_event_log_base.py b/git_trace2_event_log_base.py index d986b240..8f2fa79e 100644 --- a/git_trace2_event_log_base.py +++ b/git_trace2_event_log_base.py @@ -42,7 +42,7 @@ import threading p_init_count = 0 -class BaseEventLog(object): +class BaseEventLog: """Event log that records events that occurred during a repo invocation. Events are written to the log as a consecutive JSON entries, one per line. @@ -76,7 +76,7 @@ class BaseEventLog(object): # Save both our sid component and the complete sid. # We use our sid component (self._sid) as the unique filename prefix and # the full sid (self._full_sid) in the log itself. - self._sid = "repo-%s-P%08x" % ( + self._sid = "repo-{}-P{:08x}".format( self.start.strftime("%Y%m%dT%H%M%SZ"), os.getpid(), ) diff --git a/hooks.py b/hooks.py index decf0699..49ed10d1 100644 --- a/hooks.py +++ b/hooks.py @@ -25,7 +25,7 @@ from error import HookError from git_refs import HEAD -class RepoHook(object): +class RepoHook: """A RepoHook contains information about a script to run as a hook. Hooks are used to run a python script before running an upload (for @@ -183,7 +183,7 @@ class RepoHook(object): abort_if_user_denies was passed to the consturctor. """ hooks_config = self._hooks_project.config - git_approval_key = "repo.hooks.%s.%s" % (self._hook_type, subkey) + git_approval_key = f"repo.hooks.{self._hook_type}.{subkey}" # Get the last value that the user approved for this hook; may be None. old_val = hooks_config.GetString(git_approval_key) @@ -196,7 +196,7 @@ class RepoHook(object): else: # Give the user a reason why we're prompting, since they last # told us to "never ask again". - prompt = "WARNING: %s\n\n" % (changed_prompt,) + prompt = f"WARNING: {changed_prompt}\n\n" else: prompt = "" @@ -244,7 +244,7 @@ class RepoHook(object): return self._CheckForHookApprovalHelper( "approvedmanifest", self._manifest_url, - "Run hook scripts from %s" % (self._manifest_url,), + f"Run hook scripts from {self._manifest_url}", "Manifest URL has changed since %s was allowed." % (self._hook_type,), ) @@ -265,7 +265,9 @@ class RepoHook(object): "approvedhash", self._GetHash(), prompt % (self._GetMustVerb(), self._script_fullpath), - "Scripts have changed since %s was allowed." % (self._hook_type,), + "Scripts have changed since {} was allowed.".format( + self._hook_type + ), ) @staticmethod @@ -314,18 +316,18 @@ class RepoHook(object): # This logic needs to be kept in sync with _ExecuteHookViaImport below. script = """ import json, os, sys -path = '''%(path)s''' -kwargs = json.loads('''%(kwargs)s''') -context = json.loads('''%(context)s''') +path = '''{path}''' +kwargs = json.loads('''{kwargs}''') +context = json.loads('''{context}''') sys.path.insert(0, os.path.dirname(path)) data = open(path).read() exec(compile(data, path, 'exec'), context) context['main'](**kwargs) -""" % { - "path": self._script_fullpath, - "kwargs": json.dumps(kwargs), - "context": json.dumps(context), - } +""".format( + path=self._script_fullpath, + kwargs=json.dumps(kwargs), + context=json.dumps(context), + ) # We pass the script via stdin to avoid OS argv limits. It also makes # unhandled exception tracebacks less verbose/confusing for users. @@ -333,7 +335,7 @@ context['main'](**kwargs) proc = subprocess.Popen(cmd, stdin=subprocess.PIPE) proc.communicate(input=script.encode("utf-8")) if proc.returncode: - raise HookError("Failed to run %s hook." % (self._hook_type,)) + raise HookError(f"Failed to run {self._hook_type} hook.") def _ExecuteHookViaImport(self, data, context, **kwargs): """Execute the hook code in |data| directly. diff --git a/main.py b/main.py index bafa64df..3df4c944 100755 --- a/main.py +++ b/main.py @@ -194,7 +194,7 @@ global_options.add_option( ) -class _Repo(object): +class _Repo: def __init__(self, repodir): self.repodir = repodir self.commands = all_commands @@ -207,7 +207,9 @@ class _Repo(object): commands = " ".join(sorted(self.commands)) wrapped_commands = textwrap.wrap(commands, width=77) print( - "Available commands:\n %s" % ("\n ".join(wrapped_commands),) + "Available commands:\n {}".format( + "\n ".join(wrapped_commands) + ) ) print("\nRun `repo help ` for command-specific details.") print("Bug reports:", Wrapper().BUG_URL) @@ -244,7 +246,7 @@ class _Repo(object): if name in self.commands: return name, [] - key = "alias.%s" % (name,) + key = f"alias.{name}" alias = RepoConfig.ForRepository(self.repodir).GetString(key) if alias is None: alias = RepoConfig.ForUser().GetString(key) @@ -795,7 +797,7 @@ def init_http(): mgr.add_password(p[1], "https://%s/" % host, p[0], p[2]) except netrc.NetrcParseError: pass - except IOError: + except OSError: pass handlers.append(_BasicAuthHandler(mgr)) handlers.append(_DigestAuthHandler(mgr)) diff --git a/manifest_xml.py b/manifest_xml.py index 458dfb7d..77b3b8c8 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -114,12 +114,10 @@ def XmlInt(node, attr, default=None): try: return int(value) except ValueError: - raise ManifestParseError( - 'manifest: invalid %s="%s" integer' % (attr, value) - ) + raise ManifestParseError(f'manifest: invalid {attr}="{value}" integer') -class _Default(object): +class _Default: """Project defaults within the manifest.""" revisionExpr = None @@ -142,7 +140,7 @@ class _Default(object): return self.__dict__ != other.__dict__ -class _XmlRemote(object): +class _XmlRemote: def __init__( self, name, @@ -354,7 +352,7 @@ class SubmanifestSpec: self.groups = groups or [] -class XmlManifest(object): +class XmlManifest: """manages the repo configuration file""" def __init__( @@ -727,10 +725,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md self._output_manifest_project_extras(p, e) if p.subprojects: - subprojects = set(subp.name for subp in p.subprojects) + subprojects = {subp.name for subp in p.subprojects} output_projects(p, e, list(sorted(subprojects))) - projects = set(p.name for p in self._paths.values() if not p.parent) + projects = {p.name for p in self._paths.values() if not p.parent} output_projects(None, root, list(sorted(projects))) if self._repo_hooks_project: @@ -800,17 +798,17 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md for child in node.childNodes: if child.nodeType == xml.dom.Node.ELEMENT_NODE: attrs = child.attributes - element = dict( - (attrs.item(i).localName, attrs.item(i).value) + element = { + attrs.item(i).localName: attrs.item(i).value for i in range(attrs.length) - ) + } if child.nodeName in SINGLE_ELEMENTS: ret[child.nodeName] = element elif child.nodeName in MULTI_ELEMENTS: ret.setdefault(child.nodeName, []).append(element) else: raise ManifestParseError( - 'Unhandled element "%s"' % (child.nodeName,) + f'Unhandled element "{child.nodeName}"' ) append_children(element, child) @@ -857,8 +855,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md self._Load() outer = self._outer_client yield outer - for tree in outer.all_children: - yield tree + yield from outer.all_children @property def all_children(self): @@ -867,8 +864,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md for child in self._submanifests.values(): if child.repo_client: yield child.repo_client - for tree in child.repo_client.all_children: - yield tree + yield from child.repo_client.all_children @property def path_prefix(self): @@ -987,7 +983,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md @property def PartialCloneExclude(self): exclude = self.manifest.manifestProject.partial_clone_exclude or "" - return set(x.strip() for x in exclude.split(",")) + return {x.strip() for x in exclude.split(",")} def SetManifestOverride(self, path): """Override manifestFile. The caller must call Unload()""" @@ -1260,18 +1256,16 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md try: root = xml.dom.minidom.parse(path) except (OSError, xml.parsers.expat.ExpatError) as e: - raise ManifestParseError( - "error parsing manifest %s: %s" % (path, e) - ) + raise ManifestParseError(f"error parsing manifest {path}: {e}") if not root or not root.childNodes: - raise ManifestParseError("no root node in %s" % (path,)) + raise ManifestParseError(f"no root node in {path}") for manifest in root.childNodes: if manifest.nodeName == "manifest": break else: - raise ManifestParseError("no in %s" % (path,)) + raise ManifestParseError(f"no in {path}") nodes = [] for node in manifest.childNodes: @@ -1281,7 +1275,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md msg = self._CheckLocalPath(name) if msg: raise ManifestInvalidPathError( - ' invalid "name": %s: %s' % (name, msg) + f' invalid "name": {name}: {msg}' ) include_groups = "" if parent_groups: @@ -1313,7 +1307,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md raise except Exception as e: raise ManifestParseError( - "failed parsing included manifest %s: %s" % (name, e) + "failed parsing included manifest {}: {}".format( + name, e + ) ) else: if parent_groups and node.nodeName == "project": @@ -1764,13 +1760,13 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md msg = self._CheckLocalPath(name) if msg: raise ManifestInvalidPathError( - ' invalid "name": %s: %s' % (name, msg) + f' invalid "name": {name}: {msg}' ) else: msg = self._CheckLocalPath(path) if msg: raise ManifestInvalidPathError( - ' invalid "path": %s: %s' % (path, msg) + f' invalid "path": {path}: {msg}' ) submanifest = _XmlSubmanifest( @@ -1805,7 +1801,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md msg = self._CheckLocalPath(name, dir_ok=True) if msg: raise ManifestInvalidPathError( - ' invalid "name": %s: %s' % (name, msg) + f' invalid "name": {name}: {msg}' ) if parent: name = self._JoinName(parent.name, name) @@ -1815,7 +1811,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md remote = self._default.remote if remote is None: raise ManifestParseError( - "no remote for project %s within %s" % (name, self.manifestFile) + "no remote for project {} within {}".format( + name, self.manifestFile + ) ) revisionExpr = node.getAttribute("revision") or remote.revision @@ -1836,7 +1834,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md msg = self._CheckLocalPath(path, dir_ok=True, cwd_dot_ok=True) if msg: raise ManifestInvalidPathError( - ' invalid "path": %s: %s' % (path, msg) + f' invalid "path": {path}: {msg}' ) rebase = XmlBool(node, "rebase", True) @@ -2093,7 +2091,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md if not cwd_dot_ok or parts != ["."]: for part in set(parts): if part in {".", "..", ".git"} or part.startswith(".repo"): - return "bad component: %s" % (part,) + return f"bad component: {part}" if not dir_ok and resep.match(path[-1]): return "dirs not allowed" @@ -2129,7 +2127,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md msg = cls._CheckLocalPath(dest) if msg: raise ManifestInvalidPathError( - '<%s> invalid "dest": %s: %s' % (element, dest, msg) + f'<{element}> invalid "dest": {dest}: {msg}' ) # |src| is the file we read from or path we point to for symlinks. @@ -2140,7 +2138,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md ) if msg: raise ManifestInvalidPathError( - '<%s> invalid "src": %s: %s' % (element, src, msg) + f'<{element}> invalid "src": {src}: {msg}' ) def _ParseCopyFile(self, project, node): @@ -2184,7 +2182,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md v = self._remotes.get(name) if not v: raise ManifestParseError( - "remote %s not defined in %s" % (name, self.manifestFile) + f"remote {name} not defined in {self.manifestFile}" ) return v diff --git a/platform_utils.py b/platform_utils.py index 2c48e622..d720a07e 100644 --- a/platform_utils.py +++ b/platform_utils.py @@ -193,10 +193,9 @@ def _walk_windows_impl(top, topdown, onerror, followlinks): for name in dirs: new_path = os.path.join(top, name) if followlinks or not islink(new_path): - for x in _walk_windows_impl( + yield from _walk_windows_impl( new_path, topdown, onerror, followlinks - ): - yield x + ) if not topdown: yield top, dirs, nondirs diff --git a/platform_utils_win32.py b/platform_utils_win32.py index 80a52639..f10d9d0a 100644 --- a/platform_utils_win32.py +++ b/platform_utils_win32.py @@ -186,9 +186,7 @@ def _create_symlink(source, link_name, dwFlags): error_desc = FormatError(code).strip() if code == ERROR_PRIVILEGE_NOT_HELD: raise OSError(errno.EPERM, error_desc, link_name) - _raise_winerror( - code, 'Error creating symbolic link "{}"'.format(link_name) - ) + _raise_winerror(code, f'Error creating symbolic link "{link_name}"') def islink(path): @@ -210,7 +208,7 @@ def readlink(path): ) if reparse_point_handle == INVALID_HANDLE_VALUE: _raise_winerror( - get_last_error(), 'Error opening symbolic link "{}"'.format(path) + get_last_error(), f'Error opening symbolic link "{path}"' ) target_buffer = c_buffer(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) n_bytes_returned = DWORD() @@ -227,7 +225,7 @@ def readlink(path): CloseHandle(reparse_point_handle) if not io_result: _raise_winerror( - get_last_error(), 'Error reading symbolic link "{}"'.format(path) + get_last_error(), f'Error reading symbolic link "{path}"' ) rdb = REPARSE_DATA_BUFFER.from_buffer(target_buffer) if rdb.ReparseTag == IO_REPARSE_TAG_SYMLINK: @@ -236,11 +234,11 @@ def readlink(path): return rdb.MountPointReparseBuffer.PrintName # Unsupported reparse point type. _raise_winerror( - ERROR_NOT_SUPPORTED, 'Error reading symbolic link "{}"'.format(path) + ERROR_NOT_SUPPORTED, f'Error reading symbolic link "{path}"' ) def _raise_winerror(code, error_desc): win_error_desc = FormatError(code).strip() - error_desc = "{0}: {1}".format(error_desc, win_error_desc) + error_desc = f"{error_desc}: {win_error_desc}" raise WinError(code, error_desc) diff --git a/progress.py b/progress.py index 80bc9463..6ae53156 100644 --- a/progress.py +++ b/progress.py @@ -52,7 +52,7 @@ def duration_str(total): uses microsecond resolution. This makes for noisy output. """ hours, mins, secs = convert_to_hms(total) - ret = "%.3fs" % (secs,) + ret = f"{secs:.3f}s" if mins: ret = "%im%s" % (mins, ret) if hours: @@ -82,7 +82,7 @@ def jobs_str(total): return f"{total} job{'s' if total > 1 else ''}" -class Progress(object): +class Progress: def __init__( self, title, diff --git a/project.py b/project.py index 642c123f..d6695fc2 100644 --- a/project.py +++ b/project.py @@ -152,7 +152,7 @@ def _ProjectHooks(): return _project_hook_list -class DownloadedChange(object): +class DownloadedChange: _commit_cache = None def __init__(self, project, base, change_id, ps_id, commit): @@ -178,7 +178,7 @@ class DownloadedChange(object): return self._commit_cache -class ReviewableBranch(object): +class ReviewableBranch: _commit_cache = None _base_exists = None @@ -319,7 +319,7 @@ class DiffColoring(Coloring): self.fail = self.printer("fail", fg="red") -class Annotation(object): +class Annotation: def __init__(self, name, value, keep): self.name = name self.value = value @@ -365,19 +365,19 @@ def _SafeExpandPath(base, subpath, skipfinal=False): for part in components: if part in {".", ".."}: raise ManifestInvalidPathError( - '%s: "%s" not allowed in paths' % (subpath, part) + f'{subpath}: "{part}" not allowed in paths' ) path = os.path.join(path, part) if platform_utils.islink(path): raise ManifestInvalidPathError( - "%s: traversing symlinks not allow" % (path,) + f"{path}: traversing symlinks not allow" ) if os.path.exists(path): if not os.path.isfile(path) and not platform_utils.isdir(path): raise ManifestInvalidPathError( - "%s: only regular files & directories allowed" % (path,) + f"{path}: only regular files & directories allowed" ) if skipfinal: @@ -386,7 +386,7 @@ def _SafeExpandPath(base, subpath, skipfinal=False): return path -class _CopyFile(object): +class _CopyFile: """Container for manifest element.""" def __init__(self, git_worktree, src, topdir, dest): @@ -409,11 +409,11 @@ class _CopyFile(object): if platform_utils.isdir(src): raise ManifestInvalidPathError( - "%s: copying from directory not supported" % (self.src,) + f"{self.src}: copying from directory not supported" ) if platform_utils.isdir(dest): raise ManifestInvalidPathError( - "%s: copying to directory not allowed" % (self.dest,) + f"{self.dest}: copying to directory not allowed" ) # Copy file if it does not exist or is out of date. @@ -431,11 +431,11 @@ class _CopyFile(object): mode = os.stat(dest)[stat.ST_MODE] mode = mode & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) os.chmod(dest, mode) - except IOError: + except OSError: logger.error("error: Cannot copy file %s to %s", src, dest) -class _LinkFile(object): +class _LinkFile: """Container for manifest element.""" def __init__(self, git_worktree, src, topdir, dest): @@ -466,7 +466,7 @@ class _LinkFile(object): if not platform_utils.isdir(dest_dir): os.makedirs(dest_dir) platform_utils.symlink(relSrc, absDest) - except IOError: + except OSError: logger.error( "error: Cannot link file %s to %s", relSrc, absDest ) @@ -518,7 +518,7 @@ class _LinkFile(object): self.__linkIt(relSrc, absDest) -class RemoteSpec(object): +class RemoteSpec: def __init__( self, name, @@ -538,7 +538,7 @@ class RemoteSpec(object): self.fetchUrl = fetchUrl -class Project(object): +class Project: # These objects can be shared between several working trees. @property def shareable_dirs(self): @@ -957,7 +957,7 @@ class Project(object): f_status = "-" if i and i.src_path: - line = " %s%s\t%s => %s (%s%%)" % ( + line = " {}{}\t{} => {} ({}%)".format( i_status, f_status, i.src_path, @@ -965,7 +965,7 @@ class Project(object): i.level, ) else: - line = " %s%s\t%s" % (i_status, f_status, p) + line = f" {i_status}{f_status}\t{p}" if i and not f: out.added("%s", line) @@ -1157,7 +1157,7 @@ class Project(object): if dest_branch.startswith(R_HEADS): dest_branch = dest_branch[len(R_HEADS) :] - ref_spec = "%s:refs/for/%s" % (R_HEADS + branch.name, dest_branch) + ref_spec = f"{R_HEADS + branch.name}:refs/for/{dest_branch}" opts = [] if auto_topic: opts += ["topic=" + branch.name] @@ -1182,7 +1182,9 @@ class Project(object): GitCommand(self, cmd, bare=True, verify_command=True).Wait() if not dryrun: - msg = "posted to %s for %s" % (branch.remote.review, dest_branch) + msg = "posted to {} for {}".format( + branch.remote.review, dest_branch + ) self.bare_git.UpdateRef( R_PUB + branch.name, R_HEADS + branch.name, message=msg ) @@ -1198,7 +1200,7 @@ class Project(object): with tarfile.open(tarpath, "r") as tar: tar.extractall(path=path) return True - except (IOError, tarfile.TarError) as e: + except (OSError, tarfile.TarError) as e: logger.error("error: Cannot extract archive %s: %s", tarpath, e) return False @@ -1309,7 +1311,7 @@ class Project(object): alt_dir = os.path.join( self.objdir, "objects", fd.readline().rstrip() ) - except IOError: + except OSError: alt_dir = None else: alt_dir = None @@ -1444,7 +1446,9 @@ class Project(object): return self.bare_git.rev_list(self.revisionExpr, "-1")[0] except GitError: raise ManifestInvalidRevisionError( - "revision %s in %s not found" % (self.revisionExpr, self.name) + "revision {} in {} not found".format( + self.revisionExpr, self.name + ) ) def GetRevisionId(self, all_refs=None): @@ -1461,7 +1465,9 @@ class Project(object): return self.bare_git.rev_parse("--verify", "%s^0" % rev) except GitError: raise ManifestInvalidRevisionError( - "revision %s in %s not found" % (self.revisionExpr, self.name) + "revision {} in {} not found".format( + self.revisionExpr, self.name + ) ) def SetRevisionId(self, revisionId): @@ -1774,7 +1780,9 @@ class Project(object): if not quiet: print( - "%s: Deleting obsolete checkout." % (self.RelPath(local=False),) + "{}: Deleting obsolete checkout.".format( + self.RelPath(local=False) + ) ) # Unlock and delink from the main worktree. We don't use git's worktree @@ -1968,7 +1976,7 @@ class Project(object): # target branch, but otherwise take no other action. _lwrite( self.work_git.GetDotgitPath(subpath=HEAD), - "ref: %s%s\n" % (R_HEADS, name), + f"ref: {R_HEADS}{name}\n", ) return True @@ -2277,7 +2285,7 @@ class Project(object): self.config.SetString("core.repositoryFormatVersion", str(version)) # Enable the extension! - self.config.SetString("extensions.%s" % (key,), value) + self.config.SetString(f"extensions.{key}", value) def ResolveRemoteHead(self, name=None): """Find out what the default branch (HEAD) points to. @@ -2447,7 +2455,7 @@ class Project(object): old_packed_lines = [] for r in sorted(all_refs): - line = "%s %s\n" % (all_refs[r], r) + line = f"{all_refs[r]} {r}\n" tmp_packed_lines.append(line) if r not in tmp: old_packed_lines.append(line) @@ -2617,7 +2625,7 @@ class Project(object): # one. if not verbose and gitcmd.stdout: print( - "\n%s:\n%s" % (self.name, gitcmd.stdout), + f"\n{self.name}:\n{gitcmd.stdout}", end="", file=output_redir, ) @@ -2752,7 +2760,7 @@ class Project(object): proc = None with Trace("Fetching bundle: %s", " ".join(cmd)): if verbose: - print("%s: Downloading bundle: %s" % (self.name, srcUrl)) + print(f"{self.name}: Downloading bundle: {srcUrl}") stdout = None if verbose else subprocess.PIPE stderr = None if verbose else subprocess.STDOUT try: @@ -2810,7 +2818,7 @@ class Project(object): if GitCommand(self, cmd).Wait() != 0: if self._allrefs: raise GitError( - "%s checkout %s " % (self.name, rev), project=self.name + f"{self.name} checkout {rev} ", project=self.name ) def _CherryPick(self, rev, ffonly=False, record_origin=False): @@ -2824,7 +2832,8 @@ class Project(object): if GitCommand(self, cmd).Wait() != 0: if self._allrefs: raise GitError( - "%s cherry-pick %s " % (self.name, rev), project=self.name + f"{self.name} cherry-pick {rev} ", + project=self.name, ) def _LsRemote(self, refs): @@ -2841,9 +2850,7 @@ class Project(object): cmd.append("--") if GitCommand(self, cmd).Wait() != 0: if self._allrefs: - raise GitError( - "%s revert %s " % (self.name, rev), project=self.name - ) + raise GitError(f"{self.name} revert {rev} ", project=self.name) def _ResetHard(self, rev, quiet=True): cmd = ["reset", "--hard"] @@ -2852,7 +2859,7 @@ class Project(object): cmd.append(rev) if GitCommand(self, cmd).Wait() != 0: raise GitError( - "%s reset --hard %s " % (self.name, rev), project=self.name + f"{self.name} reset --hard {rev} ", project=self.name ) def _SyncSubmodules(self, quiet=True): @@ -2871,18 +2878,14 @@ class Project(object): cmd.extend(["--onto", onto]) cmd.append(upstream) if GitCommand(self, cmd).Wait() != 0: - raise GitError( - "%s rebase %s " % (self.name, upstream), project=self.name - ) + raise GitError(f"{self.name} rebase {upstream} ", project=self.name) def _FastForward(self, head, ffonly=False): cmd = ["merge", "--no-stat", head] if ffonly: cmd.append("--ff-only") if GitCommand(self, cmd).Wait() != 0: - raise GitError( - "%s merge %s " % (self.name, head), project=self.name - ) + raise GitError(f"{self.name} merge {head} ", project=self.name) def _InitGitDir(self, mirror_git=None, force_sync=False, quiet=False): init_git_dir = not os.path.exists(self.gitdir) @@ -3160,7 +3163,7 @@ class Project(object): "--force-sync not enabled; cannot overwrite a local " "work tree. If you're comfortable with the " "possibility of losing the work tree's git metadata," - " use `repo sync --force-sync {0}` to " + " use `repo sync --force-sync {}` to " "proceed.".format(self.RelPath(local=False)), project=self.name, ) @@ -3227,7 +3230,7 @@ class Project(object): # Rewrite the internal state files to use relative paths between the # checkouts & worktrees. dotgit = os.path.join(self.worktree, ".git") - with open(dotgit, "r") as fp: + with open(dotgit) as fp: # Figure out the checkout->worktree path. setting = fp.read() assert setting.startswith("gitdir:") @@ -3475,7 +3478,7 @@ class Project(object): ) return logs - class _GitGetByExec(object): + class _GitGetByExec: def __init__(self, project, bare, gitdir): self._project = project self._bare = bare @@ -3530,7 +3533,7 @@ class Project(object): except StopIteration: break - class _Info(object): + class _Info: def __init__(self, path, omode, nmode, oid, nid, state): self.path = path self.src_path = None @@ -3584,7 +3587,7 @@ class Project(object): try: with open(path) as fd: line = fd.readline() - except IOError as e: + except OSError as e: raise NoManifestException(path, str(e)) try: line = line.decode() @@ -3675,12 +3678,14 @@ class Project(object): config = kwargs.pop("config", None) for k in kwargs: raise TypeError( - "%s() got an unexpected keyword argument %r" % (name, k) + "{}() got an unexpected keyword argument {!r}".format( + name, k + ) ) if config is not None: for k, v in config.items(): cmdv.append("-c") - cmdv.append("%s=%s" % (k, v)) + cmdv.append(f"{k}={v}") cmdv.append(name) cmdv.extend(args) p = GitCommand( @@ -3716,7 +3721,7 @@ class _DirtyError(LocalSyncFail): return "contains uncommitted changes" -class _InfoMessage(object): +class _InfoMessage: def __init__(self, project, text): self.project = project self.text = text @@ -3728,7 +3733,7 @@ class _InfoMessage(object): syncbuf.out.nl() -class _Failure(object): +class _Failure: def __init__(self, project, why): self.project = project self.why = why @@ -3740,7 +3745,7 @@ class _Failure(object): syncbuf.out.nl() -class _Later(object): +class _Later: def __init__(self, project, action): self.project = project self.action = action @@ -3766,7 +3771,7 @@ class _SyncColoring(Coloring): self.fail = self.printer("fail", fg="red") -class SyncBuffer(object): +class SyncBuffer: def __init__(self, config, detach_head=False): self._messages = [] self._failures = [] diff --git a/release/util.py b/release/util.py index df7a5638..4fa66c6d 100644 --- a/release/util.py +++ b/release/util.py @@ -75,5 +75,5 @@ def import_release_key(opts): run( opts, ["gpg", "--import-ownertrust"], - input=f"{KEYID_DSA}:6:\n".encode("utf-8"), + input=f"{KEYID_DSA}:6:\n".encode(), ) diff --git a/repo b/repo index 7f24ff1e..4e0a6193 100755 --- a/repo +++ b/repo @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding:utf-8 -*- # # Copyright (C) 2008 The Android Open Source Project # @@ -22,7 +21,6 @@ It is used to get an initial repo client checkout, and after that it runs the copy of repo in the checkout. """ -from __future__ import print_function import datetime import os @@ -36,11 +34,11 @@ import sys # bit more flexible with older systems. See that file for more details on the # versions we select. MIN_PYTHON_VERSION_SOFT = (3, 6) -MIN_PYTHON_VERSION_HARD = (3, 5) +MIN_PYTHON_VERSION_HARD = (3, 6) # Keep basic logic in sync with repo_trace.py. -class Trace(object): +class Trace: """Trace helper logic.""" REPO_TRACE = "REPO_TRACE" @@ -99,7 +97,7 @@ def check_python_version(): # bridge the gap. This is the fallback anyways so perf isn't critical. min_major, min_minor = MIN_PYTHON_VERSION_SOFT for inc in range(0, 10): - reexec("python{}.{}".format(min_major, min_minor + inc)) + reexec(f"python{min_major}.{min_minor + inc}") # Fallback to older versions if possible. for inc in range( @@ -108,7 +106,7 @@ def check_python_version(): # Don't downgrade, and don't reexec ourselves (which would infinite loop). if (min_major, min_minor - inc) <= (major, minor): break - reexec("python{}.{}".format(min_major, min_minor - inc)) + reexec(f"python{min_major}.{min_minor - inc}") # Try the generic Python 3 wrapper, but only if it's new enough. If it # isn't, we want to just give up below and make the user resolve things. @@ -598,7 +596,9 @@ def run_command(cmd, **kwargs): file=sys.stderr, ) print( - " cwd: %s\n cmd: %r" % (kwargs.get("cwd", os.getcwd()), cmd), + " cwd: {}\n cmd: {!r}".format( + kwargs.get("cwd", os.getcwd()), cmd + ), file=sys.stderr, ) @@ -625,12 +625,12 @@ def get_gitc_manifest_dir(): if _gitc_manifest_dir is None: _gitc_manifest_dir = "" try: - with open(GITC_CONFIG_FILE, "r") as gitc_config: + with open(GITC_CONFIG_FILE) as gitc_config: for line in gitc_config: match = re.match("gitc_dir=(?P.*)", line) if match: _gitc_manifest_dir = match.group("gitc_manifest_dir") - except IOError: + except OSError: pass return _gitc_manifest_dir @@ -722,7 +722,9 @@ def _Init(args, gitc_init=False): except OSError as e: if e.errno != errno.EEXIST: print( - "fatal: cannot make %s directory: %s" % (repodir, e.strerror), + "fatal: cannot make {} directory: {}".format( + repodir, e.strerror + ), file=sys.stderr, ) # Don't raise CloneFailure; that would delete the @@ -820,7 +822,9 @@ def _CheckGitVersion(): if ver_act < MIN_GIT_VERSION: need = ".".join(map(str, MIN_GIT_VERSION)) print( - "fatal: git %s or later required; found %s" % (need, ver_act.full), + "fatal: git {} or later required; found {}".format( + need, ver_act.full + ), file=sys.stderr, ) raise CloneFailure() @@ -839,7 +843,9 @@ def SetGitTrace2ParentSid(env=None): KEY = "GIT_TRACE2_PARENT_SID" now = datetime.datetime.now(datetime.timezone.utc) - value = "repo-%s-P%08x" % (now.strftime("%Y%m%dT%H%M%SZ"), os.getpid()) + value = "repo-{}-P{:08x}".format( + now.strftime("%Y%m%dT%H%M%SZ"), os.getpid() + ) # If it's already set, then append ourselves. if KEY in env: @@ -894,7 +900,9 @@ def SetupGnuPG(quiet): except OSError as e: if e.errno != errno.EEXIST: print( - "fatal: cannot make %s directory: %s" % (gpg_dir, e.strerror), + "fatal: cannot make {} directory: {}".format( + gpg_dir, e.strerror + ), file=sys.stderr, ) sys.exit(1) @@ -954,7 +962,7 @@ def _GetRepoConfig(name): return None else: print( - "repo: error: git %s failed:\n%s" % (" ".join(cmd), ret.stderr), + "repo: error: git {} failed:\n{}".format(" ".join(cmd), ret.stderr), file=sys.stderr, ) raise RunError() @@ -1067,7 +1075,7 @@ def _Clone(url, cwd, clone_bundle, quiet, verbose): os.mkdir(cwd) except OSError as e: print( - "fatal: cannot make %s directory: %s" % (cwd, e.strerror), + "fatal: cannot make {} directory: {}".format(cwd, e.strerror), file=sys.stderr, ) raise CloneFailure() @@ -1107,7 +1115,7 @@ def resolve_repo_rev(cwd, committish): ret = run_git( "rev-parse", "--verify", - "%s^{commit}" % (committish,), + "{}^{{commit}}".format(committish), cwd=cwd, check=False, ) @@ -1120,7 +1128,7 @@ def resolve_repo_rev(cwd, committish): rev = resolve("refs/remotes/origin/%s" % committish) if rev is None: print( - 'repo: error: unknown branch "%s"' % (committish,), + 'repo: error: unknown branch "{}"'.format(committish), file=sys.stderr, ) raise CloneFailure() @@ -1133,7 +1141,8 @@ def resolve_repo_rev(cwd, committish): rev = resolve(remote_ref) if rev is None: print( - 'repo: error: unknown tag "%s"' % (committish,), file=sys.stderr + 'repo: error: unknown tag "{}"'.format(committish), + file=sys.stderr, ) raise CloneFailure() return (remote_ref, rev) @@ -1141,12 +1150,12 @@ def resolve_repo_rev(cwd, committish): # See if it's a short branch name. rev = resolve("refs/remotes/origin/%s" % committish) if rev: - return ("refs/heads/%s" % (committish,), rev) + return ("refs/heads/{}".format(committish), rev) # See if it's a tag. rev = resolve("refs/tags/%s" % committish) if rev: - return ("refs/tags/%s" % (committish,), rev) + return ("refs/tags/{}".format(committish), rev) # See if it's a commit. rev = resolve(committish) @@ -1155,7 +1164,8 @@ def resolve_repo_rev(cwd, committish): # Give up! print( - 'repo: error: unable to resolve "%s"' % (committish,), file=sys.stderr + 'repo: error: unable to resolve "{}"'.format(committish), + file=sys.stderr, ) raise CloneFailure() @@ -1214,7 +1224,7 @@ def _FindRepo(): return (repo, os.path.join(curdir, repodir)) -class _Options(object): +class _Options: help = False version = False @@ -1225,7 +1235,7 @@ def _ExpandAlias(name): if name in {"gitc-init", "help", "init"}: return name, [] - alias = _GetRepoConfig("alias.%s" % (name,)) + alias = _GetRepoConfig("alias.{}".format(name)) if alias is None: return name, [] @@ -1258,7 +1268,7 @@ def _ParseArguments(args): return cmd, opt, arg -class Requirements(object): +class Requirements: """Helper for checking repo's system requirements.""" REQUIREMENTS_NAME = "requirements.json" @@ -1280,7 +1290,7 @@ class Requirements(object): try: with open(path, "rb") as f: data = f.read() - except EnvironmentError: + except OSError: # NB: EnvironmentError is used for Python 2 & 3 compatibility. # If we couldn't open the file, assume it's an old source tree. return None @@ -1393,16 +1403,18 @@ def _Help(args): def _Version(): """Show version information.""" print("") - print("repo launcher version %s" % (".".join(str(x) for x in VERSION),)) - print(" (from %s)" % (__file__,)) - print("git %s" % (ParseGitVersion().full,)) + print("repo launcher version {}".format(".".join(str(x) for x in VERSION))) + print(" (from {})".format(__file__)) + print("git {}".format(ParseGitVersion().full)) print("Python %s" % sys.version) uname = platform.uname() if sys.version_info.major < 3: # Python 3 returns a named tuple, but Python 2 is simpler. print(uname) else: - print("OS %s %s (%s)" % (uname.system, uname.release, uname.version)) + print( + "OS {} {} ({})".format(uname.system, uname.release, uname.version) + ) print( "CPU %s (%s)" % (uname.machine, uname.processor if uname.processor else "unknown") diff --git a/repo_trace.py b/repo_trace.py index d243ce6c..ee224ea7 100644 --- a/repo_trace.py +++ b/repo_trace.py @@ -142,7 +142,7 @@ def _GetTraceFile(quiet): def _ClearOldTraces(): """Clear the oldest commands if trace file is too big.""" try: - with open(_TRACE_FILE, "r", errors="ignore") as f: + with open(_TRACE_FILE, errors="ignore") as f: if os.path.getsize(f.name) / (1024 * 1024) <= _MAX_SIZE: return trace_lines = f.readlines() diff --git a/ssh.py b/ssh.py index bb89fa1f..a8242790 100644 --- a/ssh.py +++ b/ssh.py @@ -165,7 +165,7 @@ class ProxyManager: # Check to see whether we already think that the master is running; if # we think it's already running, return right away. if port is not None: - key = "%s:%s" % (host, port) + key = f"{host}:{port}" else: key = host diff --git a/subcmds/__init__.py b/subcmds/__init__.py index 965ad0bb..83ec8470 100644 --- a/subcmds/__init__.py +++ b/subcmds/__init__.py @@ -37,9 +37,7 @@ for py in os.listdir(my_dir): try: cmd = getattr(mod, clsn) except AttributeError: - raise SyntaxError( - "%s/%s does not define class %s" % (__name__, py, clsn) - ) + raise SyntaxError(f"{__name__}/{py} does not define class {clsn}") name = name.replace("_", "-") cmd.NAME = name diff --git a/subcmds/abandon.py b/subcmds/abandon.py index f6c0c66c..acba8523 100644 --- a/subcmds/abandon.py +++ b/subcmds/abandon.py @@ -117,7 +117,7 @@ It is equivalent to "git branch -D ". all_projects, callback=_ProcessResults, output=Progress( - "Abandon %s" % (nb,), len(all_projects), quiet=opt.quiet + f"Abandon {nb}", len(all_projects), quiet=opt.quiet ), ) @@ -152,4 +152,4 @@ It is equivalent to "git branch -D ". _RelPath(p) for p in success[br] ) ) - print("%s%s| %s\n" % (br, " " * (width - len(br)), result)) + print("{}{}| {}\n".format(br, " " * (width - len(br)), result)) diff --git a/subcmds/branches.py b/subcmds/branches.py index 33523c38..404f738f 100644 --- a/subcmds/branches.py +++ b/subcmds/branches.py @@ -28,7 +28,7 @@ class BranchColoring(Coloring): self.notinproject = self.printer("notinproject", fg="red") -class BranchInfo(object): +class BranchInfo: def __init__(self, name): self.name = name self.current = 0 @@ -174,7 +174,7 @@ is shown, then the branch appears in all projects. if _RelPath(p) not in have: paths.append(_RelPath(p)) - s = " %s %s" % (in_type, ", ".join(paths)) + s = " {} {}".format(in_type, ", ".join(paths)) if not i.IsSplitCurrent and (width + 7 + len(s) < 80): fmt = out.current if i.IsCurrent else fmt fmt(s) diff --git a/subcmds/checkout.py b/subcmds/checkout.py index ea48263e..379bfa18 100644 --- a/subcmds/checkout.py +++ b/subcmds/checkout.py @@ -96,7 +96,7 @@ The command is equivalent to: all_projects, callback=_ProcessResults, output=Progress( - "Checkout %s" % (nb,), len(all_projects), quiet=opt.quiet + f"Checkout {nb}", len(all_projects), quiet=opt.quiet ), ) diff --git a/subcmds/diffmanifests.py b/subcmds/diffmanifests.py index b446dbd8..873d5b92 100644 --- a/subcmds/diffmanifests.py +++ b/subcmds/diffmanifests.py @@ -87,15 +87,11 @@ synced and their revisions won't be found. def _printRawDiff(self, diff, pretty_format=None, local=False): _RelPath = lambda p: p.RelPath(local=local) for project in diff["added"]: - self.printText( - "A %s %s" % (_RelPath(project), project.revisionExpr) - ) + self.printText(f"A {_RelPath(project)} {project.revisionExpr}") self.out.nl() for project in diff["removed"]: - self.printText( - "R %s %s" % (_RelPath(project), project.revisionExpr) - ) + self.printText(f"R {_RelPath(project)} {project.revisionExpr}") self.out.nl() for project, otherProject in diff["changed"]: diff --git a/subcmds/help.py b/subcmds/help.py index a839131b..80040711 100644 --- a/subcmds/help.py +++ b/subcmds/help.py @@ -150,7 +150,7 @@ Displays detailed usage information about a command. def _PrintAllCommandHelp(self): for name in sorted(all_commands): cmd = all_commands[name](manifest=self.manifest) - self._PrintCommandHelp(cmd, header_prefix="[%s] " % (name,)) + self._PrintCommandHelp(cmd, header_prefix=f"[{name}] ") def _Options(self, p): p.add_option( diff --git a/subcmds/info.py b/subcmds/info.py index c24682c7..e24d0a8b 100644 --- a/subcmds/info.py +++ b/subcmds/info.py @@ -248,7 +248,7 @@ class Info(PagedCommand): for commit in commits: split = commit.split() - self.text("{0:38}{1} ".format("", "-")) + self.text("{:38}{} ".format("", "-")) self.sha(split[0] + " ") self.text(" ".join(split[1:])) self.out.nl() diff --git a/subcmds/init.py b/subcmds/init.py index 9ac42d8e..44517877 100644 --- a/subcmds/init.py +++ b/subcmds/init.py @@ -215,7 +215,7 @@ to update the working directory files. if not opt.quiet: print() - print("Your identity is: %s <%s>" % (name, email)) + print(f"Your identity is: {name} <{email}>") print("is this correct [y/N]? ", end="", flush=True) a = sys.stdin.readline().strip().lower() if a in ("yes", "y", "t", "true"): diff --git a/subcmds/list.py b/subcmds/list.py index fba6a4dc..4338e1c9 100644 --- a/subcmds/list.py +++ b/subcmds/list.py @@ -131,7 +131,7 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'. elif opt.path_only and not opt.name_only: lines.append("%s" % (_getpath(project))) else: - lines.append("%s : %s" % (_getpath(project), project.name)) + lines.append(f"{_getpath(project)} : {project.name}") if lines: lines.sort() diff --git a/subcmds/prune.py b/subcmds/prune.py index f18471f3..b4ea40e8 100644 --- a/subcmds/prune.py +++ b/subcmds/prune.py @@ -84,7 +84,9 @@ class Prune(PagedCommand): if not branch.base_exists: print( - "(ignoring: tracking branch is gone: %s)" % (branch.base,) + "(ignoring: tracking branch is gone: {})".format( + branch.base + ) ) else: commits = branch.commits diff --git a/subcmds/start.py b/subcmds/start.py index fd177f9e..56008f42 100644 --- a/subcmds/start.py +++ b/subcmds/start.py @@ -130,7 +130,7 @@ revision specified in the manifest. all_projects, callback=_ProcessResults, output=Progress( - "Starting %s" % (nb,), len(all_projects), quiet=opt.quiet + f"Starting {nb}", len(all_projects), quiet=opt.quiet ), ) diff --git a/subcmds/sync.py b/subcmds/sync.py index 85428b18..0338b433 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -21,7 +21,6 @@ import multiprocessing import netrc import optparse import os -import socket import sys import tempfile import time @@ -943,7 +942,7 @@ later is required to fix a server side protocol bug. break # Stop us from non-stopped fetching actually-missing repos: If set # of missing repos has not been changed from last fetch, we break. - missing_set = set(p.name for p in missing) + missing_set = {p.name for p in missing} if previously_missing_set == missing_set: break previously_missing_set = missing_set @@ -1265,7 +1264,7 @@ later is required to fix a server side protocol bug. old_project_paths = [] if os.path.exists(file_path): - with open(file_path, "r") as fd: + with open(file_path) as fd: old_project_paths = fd.read().split("\n") # In reversed order, so subfolders are deleted before parent folder. for path in sorted(old_project_paths, reverse=True): @@ -1376,7 +1375,7 @@ later is required to fix a server side protocol bug. else: try: info = netrc.netrc() - except IOError: + except OSError: # .netrc file does not exist or could not be opened. pass else: @@ -1396,7 +1395,7 @@ later is required to fix a server side protocol bug. if username and password: manifest_server = manifest_server.replace( - "://", "://%s:%s@" % (username, password), 1 + "://", f"://{username}:{password}@", 1 ) transport = PersistentTransport(manifest_server) @@ -1417,7 +1416,7 @@ later is required to fix a server side protocol bug. "TARGET_PRODUCT" in os.environ and "TARGET_BUILD_VARIANT" in os.environ ): - target = "%s-%s" % ( + target = "{}-{}".format( os.environ["TARGET_PRODUCT"], os.environ["TARGET_BUILD_VARIANT"], ) @@ -1435,7 +1434,7 @@ later is required to fix a server side protocol bug. try: with open(smart_sync_manifest_path, "w") as f: f.write(manifest_str) - except IOError as e: + except OSError as e: raise SmartSyncError( "error: cannot write manifest to %s:\n%s" % (smart_sync_manifest_path, e), @@ -1446,7 +1445,7 @@ later is required to fix a server side protocol bug. raise SmartSyncError( "error: manifest server RPC call failed: %s" % manifest_str ) - except (socket.error, IOError, xmlrpc.client.Fault) as e: + except (OSError, xmlrpc.client.Fault) as e: raise SmartSyncError( "error: cannot connect to manifest server %s:\n%s" % (manifest.manifest_server, e), @@ -1908,7 +1907,7 @@ def _PostRepoFetch(rp, repo_verify=True, verbose=False): print("repo version %s is current" % rp.work_git.describe(HEAD)) -class _FetchTimes(object): +class _FetchTimes: _ALPHA = 0.5 def __init__(self, manifest): @@ -1931,7 +1930,7 @@ class _FetchTimes(object): try: with open(self._path) as f: self._saved = json.load(f) - except (IOError, ValueError): + except (OSError, ValueError): platform_utils.remove(self._path, missing_ok=True) self._saved = {} @@ -1947,11 +1946,11 @@ class _FetchTimes(object): try: with open(self._path, "w") as f: json.dump(self._seen, f, indent=2) - except (IOError, TypeError): + except (OSError, TypeError): platform_utils.remove(self._path, missing_ok=True) -class LocalSyncState(object): +class LocalSyncState: _LAST_FETCH = "last_fetch" _LAST_CHECKOUT = "last_checkout" @@ -1994,7 +1993,7 @@ class LocalSyncState(object): try: with open(self._path) as f: self._state = json.load(f) - except (IOError, ValueError): + except (OSError, ValueError): platform_utils.remove(self._path, missing_ok=True) self._state = {} @@ -2004,7 +2003,7 @@ class LocalSyncState(object): try: with open(self._path, "w") as f: json.dump(self._state, f, indent=2) - except (IOError, TypeError): + except (OSError, TypeError): platform_utils.remove(self._path, missing_ok=True) def PruneRemovedProjects(self): @@ -2137,7 +2136,7 @@ class PersistentTransport(xmlrpc.client.Transport): try: p.feed(data) except xml.parsers.expat.ExpatError as e: - raise IOError( + raise OSError( f"Parsing the manifest failed: {e}\n" f"Please report this to your manifest server admin.\n" f'Here is the full response:\n{data.decode("utf-8")}' diff --git a/subcmds/version.py b/subcmds/version.py index 71a03608..cf108f75 100644 --- a/subcmds/version.py +++ b/subcmds/version.py @@ -64,7 +64,9 @@ class Version(Command, MirrorSafeCommand): print(uname) else: print( - "OS %s %s (%s)" % (uname.system, uname.release, uname.version) + "OS {} {} ({})".format( + uname.system, uname.release, uname.version + ) ) print( "CPU %s (%s)" diff --git a/tests/test_git_command.py b/tests/test_git_command.py index 881cccb8..58df06d1 100644 --- a/tests/test_git_command.py +++ b/tests/test_git_command.py @@ -24,7 +24,7 @@ import unittest try: from unittest import mock except ImportError: - import mock + from unittest import mock import git_command import wrapper @@ -72,7 +72,7 @@ class GitCommandWaitTest(unittest.TestCase): """Tests the GitCommand class .Wait()""" def setUp(self): - class MockPopen(object): + class MockPopen: rc = 0 def __init__(self): diff --git a/tests/test_git_config.py b/tests/test_git_config.py index a44dca0f..cf6e7793 100644 --- a/tests/test_git_config.py +++ b/tests/test_git_config.py @@ -100,7 +100,7 @@ class GitConfigReadOnlyTests(unittest.TestCase): ("intg", 10737418240), ) for key, value in TESTS: - self.assertEqual(value, self.config.GetInt("section.%s" % (key,))) + self.assertEqual(value, self.config.GetInt(f"section.{key}")) class GitConfigReadWriteTests(unittest.TestCase): diff --git a/tests/test_git_superproject.py b/tests/test_git_superproject.py index 600b069f..4e66521b 100644 --- a/tests/test_git_superproject.py +++ b/tests/test_git_superproject.py @@ -34,7 +34,7 @@ class SuperprojectTestCase(unittest.TestCase): PARENT_SID_KEY = "GIT_TRACE2_PARENT_SID" PARENT_SID_VALUE = "parent_sid" SELF_SID_REGEX = r"repo-\d+T\d+Z-.*" - FULL_SID_REGEX = r"^%s/%s" % (PARENT_SID_VALUE, SELF_SID_REGEX) + FULL_SID_REGEX = rf"^{PARENT_SID_VALUE}/{SELF_SID_REGEX}" def setUp(self): """Set up superproject every time.""" @@ -249,7 +249,7 @@ class SuperprojectTestCase(unittest.TestCase): os.mkdir(self._superproject._superproject_path) manifest_path = self._superproject._WriteManifestFile() self.assertIsNotNone(manifest_path) - with open(manifest_path, "r") as fp: + with open(manifest_path) as fp: manifest_xml_data = fp.read() self.assertEqual( sort_attributes(manifest_xml_data), @@ -284,7 +284,7 @@ class SuperprojectTestCase(unittest.TestCase): ) self.assertIsNotNone(update_result.manifest_path) self.assertFalse(update_result.fatal) - with open(update_result.manifest_path, "r") as fp: + with open(update_result.manifest_path) as fp: manifest_xml_data = fp.read() self.assertEqual( sort_attributes(manifest_xml_data), @@ -371,7 +371,7 @@ class SuperprojectTestCase(unittest.TestCase): ) self.assertIsNotNone(update_result.manifest_path) self.assertFalse(update_result.fatal) - with open(update_result.manifest_path, "r") as fp: + with open(update_result.manifest_path) as fp: manifest_xml_data = fp.read() # Verify platform/vendor/x's project revision hasn't # changed. @@ -436,7 +436,7 @@ class SuperprojectTestCase(unittest.TestCase): ) self.assertIsNotNone(update_result.manifest_path) self.assertFalse(update_result.fatal) - with open(update_result.manifest_path, "r") as fp: + with open(update_result.manifest_path) as fp: manifest_xml_data = fp.read() # Verify platform/vendor/x's project revision hasn't # changed. diff --git a/tests/test_git_trace2_event_log.py b/tests/test_git_trace2_event_log.py index d8e963dd..4658a793 100644 --- a/tests/test_git_trace2_event_log.py +++ b/tests/test_git_trace2_event_log.py @@ -61,7 +61,7 @@ class EventLogTestCase(unittest.TestCase): PARENT_SID_KEY = "GIT_TRACE2_PARENT_SID" PARENT_SID_VALUE = "parent_sid" SELF_SID_REGEX = r"repo-\d+T\d+Z-.*" - FULL_SID_REGEX = r"^%s/%s" % (PARENT_SID_VALUE, SELF_SID_REGEX) + FULL_SID_REGEX = rf"^{PARENT_SID_VALUE}/{SELF_SID_REGEX}" def setUp(self): """Load the event_log module every time.""" diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index 1015e114..6d02809f 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py @@ -198,13 +198,13 @@ class ValueTests(unittest.TestCase): def test_bool_true(self): """Check XmlBool true values.""" for value in ("yes", "true", "1"): - node = self._get_node('' % (value,)) + node = self._get_node(f'') self.assertTrue(manifest_xml.XmlBool(node, "a")) def test_bool_false(self): """Check XmlBool false values.""" for value in ("no", "false", "0"): - node = self._get_node('' % (value,)) + node = self._get_node(f'') self.assertFalse(manifest_xml.XmlBool(node, "a")) def test_int_default(self): @@ -220,7 +220,7 @@ class ValueTests(unittest.TestCase): def test_int_good(self): """Check XmlInt numeric handling.""" for value in (-1, 0, 1, 50000): - node = self._get_node('' % (value,)) + node = self._get_node(f'') self.assertEqual(value, manifest_xml.XmlInt(node, "a")) def test_int_invalid(self): diff --git a/tests/test_project.py b/tests/test_project.py index 79728d70..1ffc220a 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -48,7 +48,7 @@ def TempGitTree(): yield tempdir -class FakeProject(object): +class FakeProject: """A fake for Project for basic functionality.""" def __init__(self, worktree): @@ -151,7 +151,7 @@ class CopyLinkTestCase(unittest.TestCase): # "". break result = os.path.exists(path) - msg.append("\tos.path.exists(%s): %s" % (path, result)) + msg.append(f"\tos.path.exists({path}): {result}") if result: msg.append("\tcontents: %r" % os.listdir(path)) break diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index ef4dce10..ea7a8b4d 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py @@ -418,7 +418,7 @@ class SetupGnuPG(RepoWrapperTestCase): self.wrapper.home_dot_repo, "gnupg" ) self.assertTrue(self.wrapper.SetupGnuPG(True)) - with open(os.path.join(tempdir, "keyring-version"), "r") as fp: + with open(os.path.join(tempdir, "keyring-version")) as fp: data = fp.read() self.assertEqual( ".".join(str(x) for x in self.wrapper.KEYRING_VERSION),