From b8aa8ad9511762c94c539680ab917f86ddc24569 Mon Sep 17 00:00:00 2001 From: Saugat Pachhai Date: Fri, 15 May 2020 13:48:02 +0000 Subject: [PATCH] pyupgrade: 3.6+ (#3805) * pyupgrade: 3.6+ * tests: pyupgrade 3.6+ --- dvc/analytics.py | 8 +-- dvc/api.py | 2 +- dvc/cache.py | 4 +- dvc/command/base.py | 4 +- dvc/command/get_url.py | 2 +- dvc/command/ls/__init__.py | 2 +- dvc/command/ls/ls_colors.py | 4 +- dvc/command/metrics.py | 10 +-- dvc/command/pipeline.py | 2 +- dvc/command/remote.py | 8 +-- dvc/command/remove.py | 2 +- dvc/command/run.py | 2 +- dvc/command/status.py | 4 +- dvc/command/unprotect.py | 2 +- dvc/command/version.py | 18 ++--- dvc/config.py | 8 +-- dvc/daemon.py | 4 +- dvc/dagascii.py | 14 ++-- dvc/data_cloud.py | 2 +- dvc/dependency/base.py | 10 ++- dvc/dependency/param.py | 2 +- dvc/dvcfile.py | 6 +- dvc/exceptions.py | 27 +++----- dvc/ignore.py | 4 +- dvc/lock.py | 2 +- dvc/output/base.py | 22 +++--- dvc/path_info.py | 14 ++-- dvc/prompt.py | 4 +- dvc/remote/azure.py | 8 +-- dvc/remote/base.py | 27 ++++---- dvc/remote/gdrive.py | 14 ++-- dvc/remote/gs.py | 9 ++- dvc/remote/hdfs.py | 10 +-- dvc/remote/http.py | 2 +- dvc/remote/index.py | 10 ++- dvc/remote/local.py | 16 ++--- dvc/remote/oss.py | 8 +-- dvc/remote/pool.py | 2 +- dvc/remote/s3.py | 10 +-- dvc/remote/ssh/__init__.py | 2 +- dvc/remote/ssh/connection.py | 26 ++++--- dvc/repo/__init__.py | 8 +-- dvc/repo/gc.py | 2 +- dvc/repo/metrics/__init__.py | 2 +- dvc/repo/params/__init__.py | 2 +- dvc/repo/plots/__init__.py | 2 +- dvc/repo/plots/data.py | 12 ++-- dvc/repo/plots/template.py | 6 +- dvc/repo/tree.py | 2 +- dvc/rwlock.py | 2 +- dvc/scm/base.py | 4 +- dvc/scm/git/__init__.py | 20 +++--- dvc/scm/git/tree.py | 8 +-- dvc/scm/tree.py | 2 +- dvc/stage/__init__.py | 10 +-- dvc/stage/cache.py | 2 +- dvc/stage/exceptions.py | 18 ++--- dvc/state.py | 6 +- dvc/system.py | 6 +- dvc/updater.py | 6 +- dvc/utils/fs.py | 2 +- dvc/utils/http.py | 4 +- dvc/utils/stage.py | 2 +- tests/basic_env.py | 8 +-- tests/conftest.py | 2 +- tests/dir_helpers.py | 8 +-- tests/func/remote/test_gdrive.py | 2 +- tests/func/test_add.py | 6 +- tests/func/test_api.py | 8 +-- tests/func/test_checkout.py | 2 +- tests/func/test_cli.py | 2 +- tests/func/test_config.py | 2 +- tests/func/test_data_cloud.py | 12 ++-- tests/func/test_external_repo.py | 4 +- tests/func/test_ignore.py | 1 - tests/func/test_import.py | 4 +- tests/func/test_install.py | 2 +- tests/func/test_ls.py | 12 ++-- tests/func/test_move.py | 2 +- tests/func/test_remote.py | 2 +- tests/func/test_repo.py | 6 +- tests/func/test_repro.py | 88 +++++++++++------------- tests/func/test_repro_multistage.py | 2 +- tests/func/test_run_multistage.py | 4 +- tests/func/test_run_single_stage.py | 57 +++++++-------- tests/func/test_stage.py | 4 +- tests/func/test_status.py | 2 +- tests/func/test_tree.py | 6 +- tests/func/test_utils.py | 2 - tests/remotes.py | 12 ++-- tests/unit/remote/ssh/test_connection.py | 2 +- tests/unit/remote/ssh/test_ssh.py | 14 ++-- tests/unit/remote/test_azure.py | 2 +- tests/unit/remote/test_base.py | 6 +- tests/unit/remote/test_gdrive.py | 2 +- tests/unit/remote/test_gs.py | 2 +- tests/unit/remote/test_http.py | 2 +- tests/unit/remote/test_oss.py | 2 +- tests/unit/remote/test_remote.py | 2 +- tests/unit/remote/test_remote_dir.py | 1 - tests/unit/remote/test_s3.py | 2 +- tests/unit/test_updater.py | 2 +- tests/unit/utils/test_http.py | 2 +- tests/utils/__init__.py | 2 +- tests/utils/httpd.py | 2 +- 105 files changed, 355 insertions(+), 417 deletions(-) diff --git a/dvc/analytics.py b/dvc/analytics.py index 623ed634d..b38e856d7 100644 --- a/dvc/analytics.py +++ b/dvc/analytics.py @@ -72,7 +72,7 @@ def send(path): url = "https://analytics.dvc.org" headers = {"content-type": "application/json"} - with open(path, "r") as fobj: + with open(path) as fobj: report = json.load(fobj) report.update(_runtime_info()) @@ -158,7 +158,7 @@ def _find_or_create_user_id(): try: with Lock(lockfile): try: - with open(fname, "r") as fobj: + with open(fname) as fobj: user_id = json.load(fobj)["user_id"] except (FileNotFoundError, ValueError, KeyError): @@ -170,6 +170,4 @@ def _find_or_create_user_id(): return user_id except LockError: - logger.debug( - "Failed to acquire '{lockfile}'".format(lockfile=lockfile) - ) + logger.debug(f"Failed to acquire '{lockfile}'") diff --git a/dvc/api.py b/dvc/api.py index 410a2686e..4b5e84687 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -11,7 +11,7 @@ class UrlNotDvcRepoError(DvcException): """Thrown if the given URL is not a DVC repository.""" def __init__(self, url): - super().__init__("'{}' is not a DVC repository.".format(url)) + super().__init__(f"'{url}' is not a DVC repository.") def get_url(path, repo=None, rev=None, remote=None): diff --git a/dvc/cache.py b/dvc/cache.py index bb56d6c08..80a566b91 100644 --- a/dvc/cache.py +++ b/dvc/cache.py @@ -40,7 +40,7 @@ def _make_remote_property(name): return cached_property(getter) -class Cache(object): +class Cache: """Class that manages cache locations of a DVC repo. Args: @@ -101,7 +101,7 @@ class NamedCacheItem: self.children[checksum].update(child_item) -class NamedCache(object): +class NamedCache: def __init__(self): self._items = defaultdict(lambda: defaultdict(NamedCacheItem)) self.external = defaultdict(set) diff --git a/dvc/command/base.py b/dvc/command/base.py index addd268e7..3e661835e 100644 --- a/dvc/command/base.py +++ b/dvc/command/base.py @@ -26,7 +26,7 @@ def append_doc_link(help_message, path): ) -class CmdBase(object): +class CmdBase: def __init__(self, args): from dvc.repo import Repo from dvc.updater import Updater @@ -43,7 +43,7 @@ class CmdBase(object): """Default targets for `dvc repro`.""" from dvc.dvcfile import PIPELINE_FILE - msg = "assuming default target '{}'.".format(PIPELINE_FILE) + msg = f"assuming default target '{PIPELINE_FILE}'." logger.warning(msg) return [PIPELINE_FILE] diff --git a/dvc/command/get_url.py b/dvc/command/get_url.py index dae67d4cb..3a31e1987 100644 --- a/dvc/command/get_url.py +++ b/dvc/command/get_url.py @@ -16,7 +16,7 @@ class CmdGetUrl(CmdBaseNoRepo): Repo.get_url(self.args.url, out=self.args.out) return 0 except DvcException: - logger.exception("failed to get '{}'".format(self.args.url)) + logger.exception(f"failed to get '{self.args.url}'") return 1 diff --git a/dvc/command/ls/__init__.py b/dvc/command/ls/__init__.py index e72b8556d..31da618d8 100644 --- a/dvc/command/ls/__init__.py +++ b/dvc/command/ls/__init__.py @@ -38,7 +38,7 @@ class CmdList(CmdBaseNoRepo): logger.info("\n".join(entries)) return 0 except DvcException: - logger.exception("failed to list '{}'".format(self.args.url)) + logger.exception(f"failed to list '{self.args.url}'") return 1 diff --git a/dvc/command/ls/ls_colors.py b/dvc/command/ls/ls_colors.py index 765cea782..92e6f7a10 100644 --- a/dvc/command/ls/ls_colors.py +++ b/dvc/command/ls/ls_colors.py @@ -1,7 +1,7 @@ import os -class LsColors(object): +class LsColors: default = "rs=0:di=01;34:ex=01;32" def __init__(self, lscolors=None): @@ -45,4 +45,4 @@ class LsColors(object): if not val: return text rs = self._codes.get("rs", 0) - return "\033[{}m{}\033[{}m".format(val, text, rs) + return f"\033[{val}m{text}\033[{rs}m" diff --git a/dvc/command/metrics.py b/dvc/command/metrics.py index 6a4e50ad0..8cd9befd6 100644 --- a/dvc/command/metrics.py +++ b/dvc/command/metrics.py @@ -19,16 +19,16 @@ def show_metrics( for branch, val in metrics.items(): if all_branches or all_tags or all_commits: - logger.info("{branch}:".format(branch=branch)) + logger.info(f"{branch}:") for fname, metric in val.items(): if not isinstance(metric, dict): logger.info("\t{}: {}".format(fname, str(metric))) continue - logger.info("\t{}:".format(fname)) + logger.info(f"\t{fname}:") for key, value in flatten(format_dict(metric), ".").items(): - logger.info("\t\t{}: {}".format(key, value)) + logger.info(f"\t\t{key}: {value}") if missing: raise BadMetricError(missing) @@ -68,7 +68,7 @@ class CmdMetricsAdd(CmdBase): try: self.repo.metrics.add(self.args.path) except DvcException: - msg = "failed to add metric file '{}'".format(self.args.path) + msg = f"failed to add metric file '{self.args.path}'" logger.exception(msg) return 1 @@ -80,7 +80,7 @@ class CmdMetricsRemove(CmdBase): try: self.repo.metrics.remove(self.args.path) except DvcException: - msg = "failed to remove metric file '{}'".format(self.args.path) + msg = f"failed to remove metric file '{self.args.path}'" logger.exception(msg) return 1 diff --git a/dvc/command/pipeline.py b/dvc/command/pipeline.py index f18e17781..a7c82dadd 100644 --- a/dvc/command/pipeline.py +++ b/dvc/command/pipeline.py @@ -164,7 +164,7 @@ class CmdPipelineShow(CmdBase): self.args.locked, ) except DvcException: - msg = "failed to show pipeline for '{}'".format(target) + msg = f"failed to show pipeline for '{target}'" logger.exception(msg) return 1 return 0 diff --git a/dvc/command/remote.py b/dvc/command/remote.py index c5f46a1a0..74fa2b677 100644 --- a/dvc/command/remote.py +++ b/dvc/command/remote.py @@ -18,17 +18,13 @@ class CmdRemote(CmdConfig): def _check_exists(self, conf): if self.args.name not in conf["remote"]: - raise ConfigError( - "remote '{}' doesn't exists.".format(self.args.name) - ) + raise ConfigError(f"remote '{self.args.name}' doesn't exists.") class CmdRemoteAdd(CmdRemote): def run(self): if self.args.default: - logger.info( - "Setting '{}' as a default remote.".format(self.args.name) - ) + logger.info(f"Setting '{self.args.name}' as a default remote.") with self.config.edit(self.args.level) as conf: if self.args.name in conf["remote"] and not self.args.force: diff --git a/dvc/command/remove.py b/dvc/command/remove.py index 37420b516..855180912 100644 --- a/dvc/command/remove.py +++ b/dvc/command/remove.py @@ -34,7 +34,7 @@ class CmdRemove(CmdBase): outs_only = self._is_outs_only(target) self.repo.remove(target, outs_only=outs_only) except DvcException: - logger.exception("failed to remove '{}'".format(target)) + logger.exception(f"failed to remove '{target}'") return 1 return 0 diff --git a/dvc/command/run.py b/dvc/command/run.py index 9dbad5d50..a7a495091 100644 --- a/dvc/command/run.py +++ b/dvc/command/run.py @@ -75,7 +75,7 @@ class CmdRun(CmdBase): if " " not in argument or '"' in argument: return argument - return '"{}"'.format(argument) + return f'"{argument}"' def add_parser(subparsers, parent_parser): diff --git a/dvc/command/status.py b/dvc/command/status.py index b4282ad1e..08d921bd6 100644 --- a/dvc/command/status.py +++ b/dvc/command/status.py @@ -19,7 +19,7 @@ class CmdDataStatus(CmdDataBase): ind = indent * self.STATUS_INDENT if isinstance(status, str): - logger.info("{}{}".format(ind, status)) + logger.info(f"{ind}{status}") return if isinstance(status, list): @@ -33,7 +33,7 @@ class CmdDataStatus(CmdDataBase): if isinstance(value, str): logger.info("{}{}{}".format(ind, self._normalize(value), key)) elif value: - logger.info("{}{}:".format(ind, key)) + logger.info(f"{ind}{key}:") self._show(value, indent + 1) def run(self): diff --git a/dvc/command/unprotect.py b/dvc/command/unprotect.py index 990e42c09..896e97861 100644 --- a/dvc/command/unprotect.py +++ b/dvc/command/unprotect.py @@ -13,7 +13,7 @@ class CmdUnprotect(CmdBase): try: self.repo.unprotect(target) except DvcException: - msg = "failed to unprotect '{}'".format(target) + msg = f"failed to unprotect '{target}'" logger.exception(msg) return 1 return 0 diff --git a/dvc/command/version.py b/dvc/command/version.py index 4dd2122b1..e53e36d57 100644 --- a/dvc/command/version.py +++ b/dvc/command/version.py @@ -28,12 +28,12 @@ class CmdVersion(CmdBaseNoRepo): from dvc.repo import Repo info = [ - "DVC version: {}".format(__version__), - "Python version: {}".format(platform.python_version()), - "Platform: {}".format(platform.platform()), - "Binary: {}".format(is_binary()), - "Package: {}".format(PKG), - "Supported remotes: {}".format(self.get_supported_remotes()), + f"DVC version: {__version__}", + f"Python version: {platform.python_version()}", + f"Platform: {platform.platform()}", + f"Binary: {is_binary()}", + f"Package: {PKG}", + f"Supported remotes: {self.get_supported_remotes()}", ] try: @@ -51,7 +51,7 @@ class CmdVersion(CmdBaseNoRepo): if psutil: fs_type = self.get_fs_type(repo.cache.local.cache_dir) info.append( - "Filesystem type (cache directory): {}".format(fs_type) + f"Filesystem type (cache directory): {fs_type}" ) else: logger.warning( @@ -72,7 +72,7 @@ class CmdVersion(CmdBaseNoRepo): if psutil: fs_root = self.get_fs_type(os.path.abspath(root_directory)) - info.append("Filesystem type (workspace): {}".format(fs_root)) + info.append(f"Filesystem type (workspace): {fs_root}") logger.info("\n".join(info)) return 0 @@ -115,7 +115,7 @@ class CmdVersion(CmdBaseNoRepo): os.unlink(dst) except DvcException: status = "not supported" - cache.append("{name} - {status}".format(name=name, status=status)) + cache.append(f"{name} - {status}") os.remove(src) return ", ".join(cache) diff --git a/dvc/config.py b/dvc/config.py index 1d96d7555..3326e8194 100644 --- a/dvc/config.py +++ b/dvc/config.py @@ -31,7 +31,7 @@ class ConfigError(DvcException): """DVC config exception.""" def __init__(self, msg): - super().__init__("config file error: {}".format(msg)) + super().__init__(f"config file error: {msg}") class NoRemoteError(ConfigError): @@ -89,7 +89,7 @@ def ByUrl(mapping): if os.name == "nt" and len(parsed.scheme) == 1 and parsed.netloc == "": return schemas[""](data) if parsed.scheme not in schemas: - raise Invalid("Unsupported URL type {}://".format(parsed.scheme)) + raise Invalid(f"Unsupported URL type {parsed.scheme}://") return schemas[parsed.scheme](data) @@ -390,7 +390,7 @@ def _load_config(filename): def _save_config(filename, conf_dict): - logger.debug("Writing '{}'.".format(filename)) + logger.debug(f"Writing '{filename}'.") os.makedirs(os.path.dirname(filename), exist_ok=True) config = configobj.ConfigObj(_pack_remotes(conf_dict)) @@ -417,7 +417,7 @@ def _pack_remotes(conf): # Transform remote.name -> 'remote "name"' for name, val in conf["remote"].items(): - result['remote "{}"'.format(name)] = val + result[f'remote "{name}"'] = val result.pop("remote", None) return result diff --git a/dvc/daemon.py b/dvc/daemon.py index 9307a570d..e6b5e0130 100644 --- a/dvc/daemon.py +++ b/dvc/daemon.py @@ -66,7 +66,7 @@ def _spawn_posix(cmd, env): def _spawn(cmd, env): - logger.debug("Trying to spawn '{}'".format(cmd)) + logger.debug(f"Trying to spawn '{cmd}'") if os.name == "nt": _spawn_windows(cmd, env) @@ -75,7 +75,7 @@ def _spawn(cmd, env): else: raise NotImplementedError - logger.debug("Spawned '{}'".format(cmd)) + logger.debug(f"Spawned '{cmd}'") def daemon(args): diff --git a/dvc/dagascii.py b/dvc/dagascii.py index c37a513a9..f1728ae13 100644 --- a/dvc/dagascii.py +++ b/dvc/dagascii.py @@ -37,7 +37,7 @@ def find_pager(): if env_pager: return make_pager(env_pager) - if os.system("({}) 2>{}".format(DEFAULT_PAGER, os.devnull)) == 0: + if os.system(f"({DEFAULT_PAGER}) 2>{os.devnull}") == 0: return make_pager(DEFAULT_PAGER_FORMATTED) logger.warning( @@ -49,7 +49,7 @@ def find_pager(): return pydoc.plainpager -class VertexViewer(object): +class VertexViewer: """Class to define vertex box boundaries that will be accounted for during graph building by grandalf. @@ -75,7 +75,7 @@ class VertexViewer(object): return self._w -class AsciiCanvas(object): +class AsciiCanvas: """Class for drawing in ASCII. Args: @@ -145,21 +145,21 @@ class AsciiCanvas(object): if dx == 0: y = y0 else: - y = y0 + int(round((x - x0) * dy / float((dx)))) + y = y0 + int(round((x - x0) * dy / float(dx))) self.point(x, y, char) elif y0 < y1: for y in range(y0, y1 + 1): if dy == 0: x = x0 else: - x = x0 + int(round((y - y0) * dx / float((dy)))) + x = x0 + int(round((y - y0) * dx / float(dy))) self.point(x, y, char) else: for y in range(y1, y0 + 1): if dy == 0: x = x0 else: - x = x1 + int(round((y - y1) * dx / float((dy)))) + x = x1 + int(round((y - y1) * dx / float(dy))) self.point(x, y, char) def text(self, x, y, text): @@ -213,7 +213,7 @@ def _build_sugiyama_layout(vertexes, edges): # Y # - vertexes = {v: Vertex(" {} ".format(v)) for v in vertexes} + vertexes = {v: Vertex(f" {v} ") for v in vertexes} # NOTE: reverting edges to correctly orientate the graph edges = [Edge(vertexes[e], vertexes[s]) for s, e in edges] vertexes = vertexes.values() diff --git a/dvc/data_cloud.py b/dvc/data_cloud.py index 0b594f182..4e8f5a8f1 100644 --- a/dvc/data_cloud.py +++ b/dvc/data_cloud.py @@ -8,7 +8,7 @@ from dvc.remote import Remote logger = logging.getLogger(__name__) -class DataCloud(object): +class DataCloud: """Class that manages dvc remotes. Args: diff --git a/dvc/dependency/base.py b/dvc/dependency/base.py index 1aabea173..a78c9e389 100644 --- a/dvc/dependency/base.py +++ b/dvc/dependency/base.py @@ -3,24 +3,22 @@ from dvc.exceptions import DvcException class DependencyDoesNotExistError(DvcException): def __init__(self, path): - msg = "dependency '{}' does not exist".format(path) + msg = f"dependency '{path}' does not exist" super().__init__(msg) class DependencyIsNotFileOrDirError(DvcException): def __init__(self, path): - msg = "dependency '{}' is not a file or directory".format(path) + msg = f"dependency '{path}' is not a file or directory" super().__init__(msg) class DependencyIsStageFileError(DvcException): def __init__(self, path): - super().__init__( - "Stage file '{}' cannot be a dependency.".format(path) - ) + super().__init__(f"Stage file '{path}' cannot be a dependency.") -class BaseDependency(object): +class BaseDependency: IS_DEPENDENCY = True DoesNotExistError = DependencyDoesNotExistError diff --git a/dvc/dependency/param.py b/dvc/dependency/param.py index 4657964be..9add46457 100644 --- a/dvc/dependency/param.py +++ b/dvc/dependency/param.py @@ -91,7 +91,7 @@ class ParamsDependency(LocalDependency): config = yaml.safe_load(fobj) except yaml.YAMLError as exc: raise BadParamFileError( - "Unable to read parameters from '{}'".format(self) + f"Unable to read parameters from '{self}'" ) from exc ret = {} diff --git a/dvc/dvcfile.py b/dvc/dvcfile.py index 1f0e35d51..513ec76d4 100644 --- a/dvc/dvcfile.py +++ b/dvc/dvcfile.py @@ -33,7 +33,7 @@ PIPELINE_LOCK = "dvc.lock" class LockfileCorruptedError(DvcException): def __init__(self, path): - super().__init__("Lockfile '{}' is corrupted.".format(path)) + super().__init__(f"Lockfile '{path}' is corrupted.") def is_valid_filename(path): @@ -80,7 +80,7 @@ class FileMixin: ) == os.path.abspath(other.path) def __str__(self): - return "{}: {}".format(self.__class__.__name__, self.relpath) + return f"{self.__class__.__name__}: {self.relpath}" @property def relpath(self): @@ -192,7 +192,7 @@ class PipelineFile(FileMixin): def _dump_pipeline_file(self, stage): data = {} if self.exists(): - with open(self.path, "r") as fd: + with open(self.path) as fd: data = parse_stage_for_update(fd.read(), self.path) else: open(self.path, "w+").close() diff --git a/dvc/exceptions.py b/dvc/exceptions.py index 2a2b9bceb..c9cce4879 100644 --- a/dvc/exceptions.py +++ b/dvc/exceptions.py @@ -34,8 +34,7 @@ class OutputDuplicationError(DvcException): ) else: msg = "output '{}' is already specified in stages:\n{}".format( - output, - "\n".join("\t- {}".format(s.addressing) for s in stages), + output, "\n".join(f"\t- {s.addressing}" for s in stages), ) super().__init__(msg) self.stages = stages @@ -102,7 +101,7 @@ class ArgumentDuplicationError(DvcException): def __init__(self, path): assert isinstance(path, str) - super().__init__("file '{}' is specified more than once.".format(path)) + super().__init__(f"file '{path}' is specified more than once.") class MoveNotDataSourceError(DvcException): @@ -158,7 +157,7 @@ class InitError(DvcException): class ReproductionError(DvcException): def __init__(self, dvc_file_name): self.path = dvc_file_name - super().__init__("failed to reproduce '{}'".format(dvc_file_name)) + super().__init__(f"failed to reproduce '{dvc_file_name}'") class BadMetricError(DvcException): @@ -166,7 +165,7 @@ class BadMetricError(DvcException): super().__init__( "the following metrics do not exist, " "are not metric files or are malformed: {paths}".format( - paths=", ".join("'{}'".format(path) for path in paths) + paths=", ".join(f"'{path}'" for path in paths) ) ) @@ -204,7 +203,7 @@ class OverlappingOutputPathsError(DvcException): class CheckoutErrorSuggestGit(DvcException): def __init__(self, target): - super().__init__("Did you mean `git checkout {}`?".format(target)) + super().__init__(f"Did you mean `git checkout {target}`?") class ETagMismatchError(DvcException): @@ -218,9 +217,7 @@ class ETagMismatchError(DvcException): class FileMissingError(DvcException): def __init__(self, path): self.path = path - super().__init__( - "Can't find '{}' neither locally nor on remote".format(path) - ) + super().__init__(f"Can't find '{path}' neither locally nor on remote") class DvcIgnoreInCollectedDirError(DvcException): @@ -245,18 +242,14 @@ class DownloadError(DvcException): def __init__(self, amount): self.amount = amount - super().__init__( - "{amount} files failed to download".format(amount=amount) - ) + super().__init__(f"{amount} files failed to download") class UploadError(DvcException): def __init__(self, amount): self.amount = amount - super().__init__( - "{amount} files failed to upload".format(amount=amount) - ) + super().__init__(f"{amount} files failed to upload") class CheckoutError(DvcException): @@ -278,7 +271,7 @@ class CollectCacheError(DvcException): class NoRemoteInExternalRepoError(DvcException): def __init__(self, url): super().__init__( - "No DVC remote is specified in target repository '{}'.".format(url) + f"No DVC remote is specified in target repository '{url}'." ) @@ -293,7 +286,7 @@ class NoOutputInExternalRepoError(DvcException): class HTTPError(DvcException): def __init__(self, code, reason): - super().__init__("'{} {}'".format(code, reason)) + super().__init__(f"'{code} {reason}'") class PathMissingError(DvcException): diff --git a/dvc/ignore.py b/dvc/ignore.py index 481327e82..94a72b72b 100644 --- a/dvc/ignore.py +++ b/dvc/ignore.py @@ -11,7 +11,7 @@ from dvc.utils import relpath logger = logging.getLogger(__name__) -class DvcIgnore(object): +class DvcIgnore: DVCIGNORE_FILE = ".dvcignore" def __call__(self, root, dirs, files): @@ -83,7 +83,7 @@ class DvcIgnoreRepo(DvcIgnore): return dirs, files -class DvcIgnoreFilter(object): +class DvcIgnoreFilter: def __init__(self, tree): self.tree = tree self.ignores = { diff --git a/dvc/lock.py b/dvc/lock.py index fe1eea5eb..d3b5376a2 100644 --- a/dvc/lock.py +++ b/dvc/lock.py @@ -25,7 +25,7 @@ class LockError(DvcException): """Thrown when unable to acquire the lock for DVC repo.""" -class Lock(object): +class Lock: """Class for DVC repo lock. Uses zc.lockfile as backend. diff --git a/dvc/output/base.py b/dvc/output/base.py index 21fa4156c..7b083432e 100644 --- a/dvc/output/base.py +++ b/dvc/output/base.py @@ -19,28 +19,28 @@ logger = logging.getLogger(__name__) class OutputDoesNotExistError(DvcException): def __init__(self, path): - msg = "output '{}' does not exist".format(path) + msg = f"output '{path}' does not exist" super().__init__(msg) class OutputIsNotFileOrDirError(DvcException): def __init__(self, path): - msg = "output '{}' is not a file or directory".format(path) + msg = f"output '{path}' is not a file or directory" super().__init__(msg) class OutputAlreadyTrackedError(DvcException): def __init__(self, path): - msg = "output '{}' is already tracked by SCM (e.g. Git)".format(path) + msg = f"output '{path}' is already tracked by SCM (e.g. Git)" super().__init__(msg) class OutputIsStageFileError(DvcException): def __init__(self, path): - super().__init__("Stage file '{}' cannot be an output.".format(path)) + super().__init__(f"Stage file '{path}' cannot be an output.") -class BaseOutput(object): +class BaseOutput: IS_DEPENDENCY = False REMOTE = BaseRemote @@ -228,7 +228,7 @@ class BaseOutput(object): raise self.IsNotFileOrDirError(self) if self.is_empty: - logger.warning("'{}' is empty.".format(self)) + logger.warning(f"'{self}' is empty.") self.ignore() @@ -247,9 +247,7 @@ class BaseOutput(object): assert not self.IS_DEPENDENCY if not self.changed(): - logger.info( - "Output '{}' didn't change. Skipping saving.".format(self) - ) + logger.info(f"Output '{self}' didn't change. Skipping saving.") return self.info = self.save_info() @@ -280,9 +278,7 @@ class BaseOutput(object): return ret def verify_metric(self): - raise DvcException( - "verify metric is not supported for {}".format(self.scheme) - ) + raise DvcException(f"verify metric is not supported for {self.scheme}") def download(self, to): self.remote.download(self.path_info, to.path_info) @@ -376,7 +372,7 @@ class BaseOutput(object): show_checksums=False, ) except DvcException: - logger.debug("failed to pull cache for '{}'".format(self)) + logger.debug(f"failed to pull cache for '{self}'") if self.cache.changed_cache_file(self.checksum): msg = ( diff --git a/dvc/path_info.py b/dvc/path_info.py index e0d9c9040..aa506d142 100644 --- a/dvc/path_info.py +++ b/dvc/path_info.py @@ -8,7 +8,7 @@ from funcy import cached_property from dvc.utils import relpath -class _BasePath(object): +class _BasePath: def overlaps(self, other): if isinstance(other, (str, bytes)): other = self.__class__(other) @@ -87,7 +87,7 @@ class _URLPathInfo(PosixPathInfo): __unicode__ = __str__ -class _URLPathParents(object): +class _URLPathParents: def __init__(self, src): self.src = src self._parents = self.src._path.parents @@ -99,7 +99,7 @@ class _URLPathParents(object): return self.src.replace(path=self._parents[idx]) def __repr__(self): - return "<{}.parents>".format(self.src) + return f"<{self.src}.parents>" class URLInfo(_BasePath): @@ -119,7 +119,7 @@ class URLInfo(_BasePath): assert bool(host) ^ bool(netloc) if netloc is not None: - return cls("{}://{}{}".format(scheme, netloc, path)) + return cls(f"{scheme}://{netloc}{path}") obj = cls.__new__(cls) obj._fill_parts(scheme, host, user, port, path) @@ -153,7 +153,7 @@ class URLInfo(_BasePath): @cached_property def url(self): - return "{}://{}{}".format(self.scheme, self.netloc, self._spath) + return f"{self.scheme}://{self.netloc}{self._spath}" def __str__(self): return self.url @@ -215,10 +215,10 @@ class URLInfo(_BasePath): if isinstance(other, (str, bytes)): other = self.__class__(other) if self.__class__ != other.__class__: - msg = "'{}' has incompatible class with '{}'".format(self, other) + msg = f"'{self}' has incompatible class with '{other}'" raise ValueError(msg) if self._base_parts != other._base_parts: - msg = "'{}' does not start with '{}'".format(self, other) + msg = f"'{self}' does not start with '{other}'" raise ValueError(msg) return self._path.relative_to(other._path) diff --git a/dvc/prompt.py b/dvc/prompt.py index e71aa6e67..285f6f62d 100644 --- a/dvc/prompt.py +++ b/dvc/prompt.py @@ -38,7 +38,7 @@ def confirm(statement): Returns: bool: whether or not specified statement was confirmed. """ - prompt = "{statement} [y/n]".format(statement=statement) + prompt = f"{statement} [y/n]" answer = _ask(prompt, limited_to=["yes", "no", "y", "n"]) return answer and answer.startswith("y") @@ -52,5 +52,5 @@ def password(statement): Returns: str: password entered by the user. """ - logger.info("{statement}: ".format(statement=statement)) + logger.info(f"{statement}: ") return getpass("") diff --git a/dvc/remote/azure.py b/dvc/remote/azure.py index dbff54ebb..e39ba2a06 100644 --- a/dvc/remote/azure.py +++ b/dvc/remote/azure.py @@ -67,12 +67,12 @@ class AzureRemote(BaseRemote): from azure.storage.blob import BlockBlobService from azure.common import AzureMissingResourceHttpError - logger.debug("URL {}".format(self.path_info)) - logger.debug("Connection string {}".format(self.connection_string)) + logger.debug(f"URL {self.path_info}") + logger.debug(f"Connection string {self.connection_string}") blob_service = BlockBlobService( connection_string=self.connection_string ) - logger.debug("Container name {}".format(self.path_info.bucket)) + logger.debug(f"Container name {self.path_info.bucket}") try: # verify that container exists blob_service.list_blobs( self.path_info.bucket, delimiter="/", num_results=1 @@ -85,7 +85,7 @@ class AzureRemote(BaseRemote): if path_info.scheme != self.scheme: raise NotImplementedError - logger.debug("Removing {}".format(path_info)) + logger.debug(f"Removing {path_info}") self.blob_service.delete_blob(path_info.bucket, path_info.path) def _list_paths(self, bucket, prefix, progress_callback=None): diff --git a/dvc/remote/base.py b/dvc/remote/base.py index 0750b3e6a..039339100 100644 --- a/dvc/remote/base.py +++ b/dvc/remote/base.py @@ -57,7 +57,7 @@ class RemoteCmdError(DvcException): class RemoteActionNotImplemented(DvcException): def __init__(self, action, scheme): - m = "{} is not supported for {} remotes".format(action, scheme) + m = f"{action} is not supported for {scheme} remotes" super().__init__(m) @@ -68,7 +68,7 @@ class RemoteMissingDepsError(DvcException): class DirCacheError(DvcException): def __init__(self, checksum): super().__init__( - "Failed to load dir cache for hash value: '{}'.".format(checksum) + f"Failed to load dir cache for hash value: '{checksum}'." ) @@ -82,7 +82,7 @@ def index_locked(f): return wrapper -class BaseRemote(object): +class BaseRemote: scheme = "base" path_cls = URLInfo REQUIRES = {} @@ -151,7 +151,7 @@ class BaseRemote(object): if not missing: return - url = config.get("url", "{}://".format(self.scheme)) + url = config.get("url", f"{self.scheme}://") msg = ( "URL '{}' is supported but requires these missing " "dependencies: {}. If you have installed dvc using pip, " @@ -418,10 +418,10 @@ class BaseRemote(object): if self.cache_type_confirmed: return - is_link = getattr(self, "is_{}".format(link_type), None) + is_link = getattr(self, f"is_{link_type}", None) if is_link and not is_link(path_info): self.remove(path_info) - raise DvcException("failed to verify {}".format(link_type)) + raise DvcException(f"failed to verify {link_type}") self.cache_type_confirmed = True @@ -444,7 +444,7 @@ class BaseRemote(object): def _do_link(self, from_info, to_info, link_method): if self.exists(to_info): - raise DvcException("Link '{}' already exists!".format(to_info)) + raise DvcException(f"Link '{to_info}' already exists!") link_method(from_info, to_info) @@ -544,8 +544,7 @@ class BaseRemote(object): def save(self, path_info, checksum_info, save_link=True): if path_info.scheme != self.scheme: raise RemoteActionNotImplemented( - "save {} -> {}".format(path_info.scheme, self.scheme), - self.scheme, + f"save {path_info.scheme} -> {self.scheme}", self.scheme, ) checksum = checksum_info[self.PARAM_CHECKSUM] @@ -712,7 +711,7 @@ class BaseRemote(object): parts = self.path_cls(path).parts[-2:] if not (len(parts) == 2 and parts[0] and len(parts[0]) == 2): - raise ValueError("Bad cache file path '{}'".format(path)) + raise ValueError(f"Bad cache file path '{path}'") return "".join(parts) @@ -991,7 +990,7 @@ class BaseRemote(object): with Tqdm( desc="Estimating size of " - + ("cache in '{}'".format(name) if name else "remote cache"), + + (f"cache in '{name}'" if name else "remote cache"), unit="file", ) as pbar: @@ -1010,7 +1009,7 @@ class BaseRemote(object): remote_size = total_prefixes * len(remote_checksums) else: remote_size = total_prefixes - logger.debug("Estimated remote size: {} files".format(remote_size)) + logger.debug(f"Estimated remote size: {remote_size} files") return remote_size, remote_checksums def _cache_checksums_traverse( @@ -1043,7 +1042,7 @@ class BaseRemote(object): else: yield from remote_checksums initial = len(remote_checksums) - traverse_prefixes = ["{:02x}".format(i) for i in range(1, 256)] + traverse_prefixes = [f"{i:02x}" for i in range(1, 256)] if self.TRAVERSE_PREFIX_LEN > 2: traverse_prefixes += [ "{0:0{1}x}".format(i, self.TRAVERSE_PREFIX_LEN) @@ -1051,7 +1050,7 @@ class BaseRemote(object): ] with Tqdm( desc="Querying " - + ("cache in '{}'".format(name) if name else "remote cache"), + + (f"cache in '{name}'" if name else "remote cache"), total=remote_size, initial=initial, unit="file", diff --git a/dvc/remote/gdrive.py b/dvc/remote/gdrive.py index 2a17494e8..947c37ffb 100644 --- a/dvc/remote/gdrive.py +++ b/dvc/remote/gdrive.py @@ -22,10 +22,8 @@ FOLDER_MIME_TYPE = "application/vnd.google-apps.folder" class GDrivePathNotFound(DvcException): def __init__(self, path_info, hint): - hint = "" if hint is None else " {}".format(hint) - super().__init__( - "GDrive path '{}' not found.{}".format(path_info, hint) - ) + hint = "" if hint is None else f" {hint}" + super().__init__(f"GDrive path '{path_info}' not found.{hint}") class GDriveAuthError(DvcException): @@ -62,7 +60,7 @@ def _gdrive_retry(func): "rateLimitExceeded", ] if result: - logger.debug("Retrying GDrive API call, error: {}.".format(exc)) + logger.debug(f"Retrying GDrive API call, error: {exc}.") return result @@ -465,7 +463,7 @@ class GDriveRemote(BaseRemote): return None query = "trashed=false and ({})".format( " or ".join( - "'{}' in parents".format(parent_id) for parent_id in parent_ids + f"'{parent_id}' in parents" for parent_id in parent_ids ) ) query += " and title='{}'".format(title.replace("'", "\\'")) @@ -542,9 +540,9 @@ class GDriveRemote(BaseRemote): else: dir_ids = self._ids_cache["ids"] parents_query = " or ".join( - "'{}' in parents".format(dir_id) for dir_id in dir_ids + f"'{dir_id}' in parents" for dir_id in dir_ids ) - query = "({}) and trashed=false".format(parents_query) + query = f"({parents_query}) and trashed=false" for item in self._gdrive_list(query): if progress_callback: diff --git a/dvc/remote/gs.py b/dvc/remote/gs.py index 65124c957..ffafee240 100644 --- a/dvc/remote/gs.py +++ b/dvc/remote/gs.py @@ -1,4 +1,3 @@ -import io import logging import os.path import posixpath @@ -55,7 +54,7 @@ def _upload_to_bucket( no_progress_bar=False, ): blob = bucket.blob(to_info.path, chunk_size=chunk_size) - with io.open(from_file, mode="rb") as fobj: + with open(from_file, mode="rb") as fobj: with Tqdm.wrapattr( fobj, "read", @@ -110,7 +109,7 @@ class GSRemote(BaseRemote): from_bucket = self.gs.bucket(from_info.bucket) blob = from_bucket.get_blob(from_info.path) if not blob: - msg = "'{}' doesn't exist in the cloud".format(from_info.path) + msg = f"'{from_info.path}' doesn't exist in the cloud" raise DvcException(msg) to_bucket = self.gs.bucket(to_info.bucket) @@ -120,7 +119,7 @@ class GSRemote(BaseRemote): if path_info.scheme != "gs": raise NotImplementedError - logger.debug("Removing gs://{}".format(path_info)) + logger.debug(f"Removing gs://{path_info}") blob = self.gs.bucket(path_info.bucket).get_blob(path_info.path) if not blob: return @@ -193,7 +192,7 @@ class GSRemote(BaseRemote): def _download(self, from_info, to_file, name=None, no_progress_bar=False): bucket = self.gs.bucket(from_info.bucket) blob = bucket.get_blob(from_info.path) - with io.open(to_file, mode="wb") as fobj: + with open(to_file, mode="wb") as fobj: with Tqdm.wrapattr( fobj, "write", diff --git a/dvc/remote/hdfs.py b/dvc/remote/hdfs.py index d6a61c123..728dbffff 100644 --- a/dvc/remote/hdfs.py +++ b/dvc/remote/hdfs.py @@ -55,7 +55,7 @@ class HDFSRemote(BaseRemote): def hadoop_fs(self, cmd, user=None): cmd = "hadoop fs -" + cmd if user: - cmd = "HADOOP_USER_NAME={} ".format(user) + cmd + cmd = f"HADOOP_USER_NAME={user} " + cmd # NOTE: close_fds doesn't work with redirected stdin/stdout/stderr. # See https://github.com/iterative/dvc/issues/1197. @@ -87,7 +87,7 @@ class HDFSRemote(BaseRemote): # NOTE: pyarrow doesn't support checksum, so we need to use hadoop regex = r".*\t.*\t(?P.*)" stdout = self.hadoop_fs( - "checksum {}".format(path_info.path), user=path_info.user + f"checksum {path_info.path}", user=path_info.user ) return self._group(regex, stdout, "checksum") @@ -112,7 +112,7 @@ class HDFSRemote(BaseRemote): raise NotImplementedError if self.exists(path_info): - logger.debug("Removing {}".format(path_info.path)) + logger.debug(f"Removing {path_info.path}") with self.hdfs(path_info) as hdfs: hdfs.rm(path_info.path) @@ -147,7 +147,7 @@ class HDFSRemote(BaseRemote): yield fd else: yield io.TextIOWrapper(fd, encoding=encoding) - except IOError as e: + except OSError as e: # Empty .errno and not specific enough error class in pyarrow, # see https://issues.apache.org/jira/browse/ARROW-6248 if "file does not exist" in str(e): @@ -175,7 +175,7 @@ class HDFSRemote(BaseRemote): if progress_callback: progress_callback() yield urlparse(entry["name"]).path - except IOError as e: + except OSError as e: # When searching for a specific prefix pyarrow raises an # exception if the specified cache dir does not exist if not prefix: diff --git a/dvc/remote/http.py b/dvc/remote/http.py index 230ccb92b..a056c2843 100644 --- a/dvc/remote/http.py +++ b/dvc/remote/http.py @@ -185,7 +185,7 @@ class HTTPRemote(BaseRemote): return res except requests.exceptions.RequestException: - raise DvcException("could not perform a {} request".format(method)) + raise DvcException(f"could not perform a {method} request") def gc(self): raise NotImplementedError diff --git a/dvc/remote/index.py b/dvc/remote/index.py index e56a9f99b..2bd191e98 100644 --- a/dvc/remote/index.py +++ b/dvc/remote/index.py @@ -69,9 +69,7 @@ class RemoteIndex: INDEX_TABLE_LAYOUT = "checksum TEXT PRIMARY KEY, " "dir INTEGER NOT NULL" def __init__(self, repo, name, dir_suffix=".dir"): - self.path = os.path.join( - repo.index_dir, "{}{}".format(name, self.INDEX_SUFFIX) - ) + self.path = os.path.join(repo.index_dir, f"{name}{self.INDEX_SUFFIX}") self.dir_suffix = dir_suffix self.database = None @@ -80,7 +78,7 @@ class RemoteIndex: self.lock = threading.Lock() def __iter__(self): - cmd = "SELECT checksum FROM {}".format(self.INDEX_TABLE) + cmd = f"SELECT checksum FROM {self.INDEX_TABLE}" for (checksum,) in self._execute(cmd): yield checksum @@ -105,7 +103,7 @@ class RemoteIndex: def dir_checksums(self): """Iterate over .dir checksums stored in the index.""" - cmd = "SELECT checksum FROM {} WHERE dir = 1".format(self.INDEX_TABLE) + cmd = f"SELECT checksum FROM {self.INDEX_TABLE} WHERE dir = 1" for (checksum,) in self._execute(cmd): yield checksum @@ -184,7 +182,7 @@ class RemoteIndex: Changes to the index will not committed until dump() is called. """ - cmd = "DELETE FROM {}".format(self.INDEX_TABLE) + cmd = f"DELETE FROM {self.INDEX_TABLE}" self._execute(cmd) def update(self, dir_checksums, file_checksums): diff --git a/dvc/remote/local.py b/dvc/remote/local.py index 28bd0dfd0..d29b6bca9 100644 --- a/dvc/remote/local.py +++ b/dvc/remote/local.py @@ -301,9 +301,7 @@ class LocalRemote(BaseRemote): {dir_checksum: set(file_checksum, ...)} which can be used to map a .dir file to its file contents. """ - logger.debug( - "Preparing to collect status from {}".format(remote.path_info) - ) + logger.debug(f"Preparing to collect status from {remote.path_info}") md5s = set(named_cache.scheme_keys(self.scheme)) logger.debug("Collecting information from local cache...") @@ -549,9 +547,7 @@ class LocalRemote(BaseRemote): "failed to upload full contents of '{}', " "aborting .dir file upload".format(name) ) - logger.error( - "failed to upload '{}' to '{}'".format(from_info, to_info) - ) + logger.error(f"failed to upload '{from_info}' to '{to_info}'") return 1 return func(from_info, to_info, name) @@ -595,7 +591,7 @@ class LocalRemote(BaseRemote): def _unprotect_file(self, path): if System.is_symlink(path) or System.is_hardlink(path): - logger.debug("Unprotecting '{}'".format(path)) + logger.debug(f"Unprotecting '{path}'") tmp = os.path.join(os.path.dirname(path), "." + uuid()) # The operations order is important here - if some application @@ -624,9 +620,7 @@ class LocalRemote(BaseRemote): def unprotect(self, path_info): path = path_info.fspath if not os.path.exists(path): - raise DvcException( - "can't unprotect non-existing data '{}'".format(path) - ) + raise DvcException(f"can't unprotect non-existing data '{path}'") if os.path.isdir(path): self._unprotect_dir(path) @@ -678,7 +672,7 @@ class LocalRemote(BaseRemote): dir_info = self.get_dir_cache(checksum) self._create_unpacked_dir(checksum, dir_info, unpacked_dir_info) except DvcException: - logger.warning("Could not create '{}'".format(unpacked_dir_info)) + logger.warning(f"Could not create '{unpacked_dir_info}'") self.remove(unpacked_dir_info) diff --git a/dvc/remote/oss.py b/dvc/remote/oss.py index 442762736..7575a7e38 100644 --- a/dvc/remote/oss.py +++ b/dvc/remote/oss.py @@ -64,9 +64,9 @@ class OSSRemote(BaseRemote): def oss_service(self): import oss2 - logger.debug("URL: {}".format(self.path_info)) - logger.debug("key id: {}".format(self.key_id)) - logger.debug("key secret: {}".format(self.key_secret)) + logger.debug(f"URL: {self.path_info}") + logger.debug(f"key id: {self.key_id}") + logger.debug(f"key secret: {self.key_secret}") auth = oss2.Auth(self.key_id, self.key_secret) bucket = oss2.Bucket(auth, self.endpoint, self.path_info.bucket) @@ -87,7 +87,7 @@ class OSSRemote(BaseRemote): if path_info.scheme != self.scheme: raise NotImplementedError - logger.debug("Removing oss://{}".format(path_info)) + logger.debug(f"Removing oss://{path_info}") self.oss_service.delete_object(path_info.path) def _list_paths(self, prefix, progress_callback=None): diff --git a/dvc/remote/pool.py b/dvc/remote/pool.py index 667a5e3de..0b223373e 100644 --- a/dvc/remote/pool.py +++ b/dvc/remote/pool.py @@ -30,7 +30,7 @@ def close_pools(): get_pool.memory.clear() -class Pool(object): +class Pool: def __init__(self, conn_func, *conn_args, **conn_kwargs): self._conn_func = conn_func self._conn_args = conn_args diff --git a/dvc/remote/s3.py b/dvc/remote/s3.py index 8d92642e9..62924e3e4 100644 --- a/dvc/remote/s3.py +++ b/dvc/remote/s3.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging import os import posixpath @@ -88,9 +86,7 @@ class S3Remote(BaseRemote): try: obj = s3.head_object(Bucket=bucket, Key=path, *args, **kwargs) except Exception as exc: - raise DvcException( - "s3://{}/{} does not exist".format(bucket, path) - ) from exc + raise DvcException(f"s3://{bucket}/{path} does not exist") from exc return obj @classmethod @@ -113,7 +109,7 @@ class S3Remote(BaseRemote): if lastbyte > size: lastbyte = size - 1 - srange = "bytes={}-{}".format(byte_position, lastbyte) + srange = f"bytes={byte_position}-{lastbyte}" part = s3.upload_part_copy( Bucket=to_info.bucket, @@ -191,7 +187,7 @@ class S3Remote(BaseRemote): if path_info.scheme != "s3": raise NotImplementedError - logger.debug("Removing {}".format(path_info)) + logger.debug(f"Removing {path_info}") self.s3.delete_object(Bucket=path_info.bucket, Key=path_info.path) def _list_objects( diff --git a/dvc/remote/ssh/__init__.py b/dvc/remote/ssh/__init__.py index 60774fdfe..a6d98ead3 100644 --- a/dvc/remote/ssh/__init__.py +++ b/dvc/remote/ssh/__init__.py @@ -290,7 +290,7 @@ class SSHRemote(BaseRemote): try: channel.stat(path) ret.append(True) - except IOError as exc: + except OSError as exc: if exc.errno != errno.ENOENT: raise ret.append(False) diff --git a/dvc/remote/ssh/connection.py b/dvc/remote/ssh/connection.py index bd445ad61..c68334c2c 100644 --- a/dvc/remote/ssh/connection.py +++ b/dvc/remote/ssh/connection.py @@ -25,9 +25,9 @@ def sizeof_fmt(num, suffix="B"): """ Convert number of bytes to human-readable string """ for unit in ["", "K", "M", "G", "T", "P", "E", "Z"]: if abs(num) < 1024.0: - return "%3.1f%s%s" % (num, unit, suffix) + return f"{num:3.1f}{unit}{suffix}" num /= 1024.0 - return "%.1f%s%s" % (num, "Y", suffix) + return "{:.1f}{}{}".format(num, "Y", suffix) class SSHConnection: @@ -100,7 +100,7 @@ class SSHConnection: if stat.S_ISREG(st_mode) or stat.S_ISLNK(st_mode): raise DvcException( - "a file with the same name '{}' already exists".format(path) + f"a file with the same name '{path}' already exists" ) head, tail = posixpath.split(path) @@ -111,12 +111,12 @@ class SSHConnection: if tail: try: self.sftp.mkdir(path) - except IOError as exc: + except OSError as exc: # Since paramiko errors are very vague we need to recheck # whether it's because path already exists or something else if exc.errno == errno.EACCES or not self.exists(path): raise DvcException( - "unable to create remote directory '{}'".format(path) + f"unable to create remote directory '{path}'" ) from exc def walk(self, directory, topdown=True): @@ -126,7 +126,7 @@ class SSHConnection: # [1] https://github.com/python/cpython/blob/master/Lib/os.py try: dir_entries = self.sftp.listdir_attr(directory) - except IOError as exc: + except OSError as exc: raise DvcException( "couldn't get the '{}' remote directory files list".format( directory @@ -292,14 +292,14 @@ class SSHConnection: md5 = self.execute("md5 " + path).split()[-1] else: raise DvcException( - "'{}' is not supported as a SSH remote".format(self.uname) + f"'{self.uname}' is not supported as a SSH remote" ) assert len(md5) == 32 return md5 def copy(self, src, dest): - self.execute("cp {} {}".format(src, dest)) + self.execute(f"cp {src} {dest}") def open_max_sftp_channels(self): # If there are more than 1 it means we've already opened max amount @@ -321,14 +321,12 @@ class SSHConnection: def reflink(self, src, dest): if self.uname == "Linux": - return self.execute("cp --reflink {} {}".format(src, dest)) + return self.execute(f"cp --reflink {src} {dest}") if self.uname == "Darwin": - return self.execute("cp -c {} {}".format(src, dest)) + return self.execute(f"cp -c {src} {dest}") - raise DvcException( - "'{}' is not supported as a SSH remote".format(self.uname) - ) + raise DvcException(f"'{self.uname}' is not supported as a SSH remote") def hardlink(self, src, dest): - self.execute("ln {} {}".format(src, dest)) + self.execute(f"ln {src} {dest}") diff --git a/dvc/repo/__init__.py b/dvc/repo/__init__.py index c0daad963..12d2de04f 100644 --- a/dvc/repo/__init__.py +++ b/dvc/repo/__init__.py @@ -33,7 +33,7 @@ def locked(f): return wrapper -class Repo(object): +class Repo: DVC_DIR = ".dvc" from dvc.repo.destroy import destroy @@ -123,14 +123,14 @@ class Repo(object): self._reset() def __repr__(self): - return "{}: '{}'".format(self.__class__.__name__, self.root_dir) + return f"{self.__class__.__name__}: '{self.root_dir}'" @classmethod def find_root(cls, root=None): root_dir = os.path.realpath(root or os.curdir) if not os.path.isdir(root_dir): - raise NotDvcRepoError("directory '{}' does not exist".format(root)) + raise NotDvcRepoError(f"directory '{root}' does not exist") while True: dvc_dir = os.path.join(root_dir, cls.DVC_DIR) @@ -281,7 +281,7 @@ class Repo(object): for target in targets ) - suffix = "({})".format(branch) if branch else "" + suffix = f"({branch})" if branch else "" for stage, filter_info in pairs: used_cache = stage.get_used_cache( remote=remote, diff --git a/dvc/repo/gc.py b/dvc/repo/gc.py index bfaf448d3..086d248ab 100644 --- a/dvc/repo/gc.py +++ b/dvc/repo/gc.py @@ -11,7 +11,7 @@ logger = logging.getLogger(__name__) def _do_gc(typ, func, clist, jobs=None): removed = func(clist, jobs=jobs) if not removed: - logger.info("No unused '{}' cache to remove.".format(typ)) + logger.info(f"No unused '{typ}' cache to remove.") def _raise_error_if_all_disabled(**kwargs): diff --git a/dvc/repo/metrics/__init__.py b/dvc/repo/metrics/__init__.py index 5e05ae7b2..28468b40c 100644 --- a/dvc/repo/metrics/__init__.py +++ b/dvc/repo/metrics/__init__.py @@ -1,4 +1,4 @@ -class Metrics(object): +class Metrics: def __init__(self, repo): self.repo = repo diff --git a/dvc/repo/params/__init__.py b/dvc/repo/params/__init__.py index 3f7bc4797..ed5dc2fc3 100644 --- a/dvc/repo/params/__init__.py +++ b/dvc/repo/params/__init__.py @@ -1,4 +1,4 @@ -class Params(object): +class Params: def __init__(self, repo): self.repo = repo diff --git a/dvc/repo/plots/__init__.py b/dvc/repo/plots/__init__.py index ea350a826..11219d801 100644 --- a/dvc/repo/plots/__init__.py +++ b/dvc/repo/plots/__init__.py @@ -148,7 +148,7 @@ def plot( def _parse_template(template_path, priority_datafile): - with open(template_path, "r") as fobj: + with open(template_path) as fobj: tempalte_content = fobj.read() template_datafiles = Template.parse_data_anchors(tempalte_content) diff --git a/dvc/repo/plots/data.py b/dvc/repo/plots/data.py index 4c9d736d1..4994aea33 100644 --- a/dvc/repo/plots/data.py +++ b/dvc/repo/plots/data.py @@ -45,14 +45,12 @@ class NoMetricOnRevisionError(DvcException): def __init__(self, path, revision): self.path = path self.revision = revision - super().__init__( - "Could not find '{}' on revision '{}'".format(path, revision) - ) + super().__init__(f"Could not find '{path}' on revision '{revision}'") class NoMetricInHistoryError(DvcException): def __init__(self, path): - super().__init__("Could not find '{}'.".format(path)) + super().__init__(f"Could not find '{path}'.") def plot_data(filename, revision, content): @@ -194,13 +192,13 @@ class JSONPlotData(PlotData): return json.loads(self.content, object_pairs_hook=OrderedDict) def _processors(self): - parent_processors = super(JSONPlotData, self)._processors() + parent_processors = super()._processors() return [_apply_path, _find_data] + parent_processors class CSVPlotData(PlotData): def __init__(self, filename, revision, content, delimiter=","): - super(CSVPlotData, self).__init__(filename, revision, content) + super().__init__(filename, revision, content) self.delimiter = delimiter def raw(self, csv_header=True, **kwargs): @@ -277,7 +275,7 @@ def _load_from_revisions(repo, datafile, revisions): except PlotMetricTypeError: raise except (yaml.error.YAMLError, json.decoder.JSONDecodeError, csv.Error): - logger.error("Failed to parse '{}' at '{}'.".format(datafile, rev)) + logger.error(f"Failed to parse '{datafile}' at '{rev}'.") raise if not data and exceptions: diff --git a/dvc/repo/plots/template.py b/dvc/repo/plots/template.py index 882becca3..e8f7fd6c2 100644 --- a/dvc/repo/plots/template.py +++ b/dvc/repo/plots/template.py @@ -13,7 +13,7 @@ logger = logging.getLogger(__name__) class TemplateNotFoundError(DvcException): def __init__(self, path): - super().__init__("Template '{}' not found.".format(path)) + super().__init__(f"Template '{path}' not found.") class NoDataForTemplateError(DvcException): @@ -26,7 +26,7 @@ class NoDataForTemplateError(DvcException): class NoFieldInDataError(DvcException): def __init__(self, field_name): super().__init__( - "Field '{}' does not exist in provided data.".format(field_name) + f"Field '{field_name}' does not exist in provided data." ) @@ -94,7 +94,7 @@ class Template: x_title=None, y_title=None, ): - with open(template_path, "r") as fobj: + with open(template_path) as fobj: result_content = fobj.read() if x_field: diff --git a/dvc/repo/tree.py b/dvc/repo/tree.py index ce8990b21..560f1cfd4 100644 --- a/dvc/repo/tree.py +++ b/dvc/repo/tree.py @@ -29,7 +29,7 @@ class DvcTree(BaseTree): raise FileNotFoundError from exc if len(outs) != 1 or outs[0].is_dir_checksum: - raise IOError(errno.EISDIR) + raise OSError(errno.EISDIR) out = outs[0] # temporary hack to make cache use WorkingTree and not GitTree, because diff --git a/dvc/rwlock.py b/dvc/rwlock.py index 613dded48..278b72ebf 100644 --- a/dvc/rwlock.py +++ b/dvc/rwlock.py @@ -38,7 +38,7 @@ class RWLockFileFormatError(DvcException): def _edit_rwlock(lock_dir): path = os.path.join(lock_dir, "rwlock") try: - with open(path, "r") as fobj: + with open(path) as fobj: lock = SCHEMA(json.load(fobj)) except FileNotFoundError: lock = SCHEMA({}) diff --git a/dvc/scm/base.py b/dvc/scm/base.py index e1bedc242..1bde8f744 100644 --- a/dvc/scm/base.py +++ b/dvc/scm/base.py @@ -17,7 +17,7 @@ class FileNotInRepoError(SCMError): class CloneError(SCMError): def __init__(self, url, path): - super().__init__("Failed to clone repo '{}' to '{}'".format(url, path)) + super().__init__(f"Failed to clone repo '{url}' to '{path}'") class RevError(SCMError): @@ -34,7 +34,7 @@ class NoSCMError(SCMError): super().__init__(msg) -class Base(object): +class Base: """Base class for source control management driver implementations.""" def __init__(self, root_dir=os.curdir): diff --git a/dvc/scm/git/__init__.py b/dvc/scm/git/__init__.py index 7429ae47c..0cacd1f1c 100644 --- a/dvc/scm/git/__init__.py +++ b/dvc/scm/git/__init__.py @@ -30,7 +30,7 @@ class TqdmGit(Tqdm): if op_code: message = (op_code + " | " + message) if message else op_code if message: - self.postfix["info"] = " {} | ".format(message) + self.postfix["info"] = f" {message} | " self.update_to(cur_count, max_count) @staticmethod @@ -211,7 +211,7 @@ class Git(Base): fobj.seek(fobj.tell() - 1, os.SEEK_SET) last = fobj.read(1) prefix = "" if last == "\n" else "\n" - fobj.write("{}{}\n".format(prefix, entry)) + fobj.write(f"{prefix}{entry}\n") def ignore_remove(self, path): entry, gitignore = self._get_gitignore(path) @@ -219,7 +219,7 @@ class Git(Base): if not os.path.exists(gitignore): return - with open(gitignore, "r") as fobj: + with open(gitignore) as fobj: lines = fobj.readlines() filtered = list(filter(lambda x: x.strip() != entry.strip(), lines)) @@ -257,13 +257,13 @@ class Git(Base): infos = self.repo.remote().pull() for info in infos: if info.flags & info.ERROR: - raise SCMError("pull failed: {}".format(info.note)) + raise SCMError(f"pull failed: {info.note}") def push(self): infos = self.repo.remote().push() for info in infos: if info.flags & info.ERROR: - raise SCMError("push failed: {}".format(info.summary)) + raise SCMError(f"push failed: {info.summary}") def branch(self, branch): self.repo.git.branch(branch) @@ -296,7 +296,7 @@ class Git(Base): def _install_hook(self, name): hook = self._hook_path(name) with open(hook, "w+") as fobj: - fobj.write("#!/bin/sh\nexec dvc git-hook {} $@\n".format(name)) + fobj.write(f"#!/bin/sh\nexec dvc git-hook {name} $@\n") os.chmod(hook, 0o777) @@ -312,7 +312,7 @@ class Git(Base): config = {} if os.path.exists(config_path): - with open(config_path, "r") as fobj: + with open(config_path) as fobj: config = yaml.safe_load(fobj) entry = { @@ -404,15 +404,15 @@ class Git(Base): # Try all the remotes and if it resolves unambiguously then take it if not Git.is_sha(rev): shas = { - _resolve_rev("{}/{}".format(remote.name, rev)) + _resolve_rev(f"{remote.name}/{rev}") for remote in self.repo.remotes } - {None} if len(shas) > 1: - raise RevError("ambiguous Git revision '{}'".format(rev)) + raise RevError(f"ambiguous Git revision '{rev}'") if len(shas) == 1: return shas.pop() - raise RevError("unknown Git revision '{}'".format(rev)) + raise RevError(f"unknown Git revision '{rev}'") def has_rev(self, rev): try: diff --git a/dvc/scm/git/tree.py b/dvc/scm/git/tree.py index b1cff91c8..316204a2d 100644 --- a/dvc/scm/git/tree.py +++ b/dvc/scm/git/tree.py @@ -42,10 +42,10 @@ class GitTree(BaseTree): obj = self.git_object_by_path(path) if obj is None: - msg = "No such file in branch '{}'".format(self.rev) - raise IOError(errno.ENOENT, msg, relative_path) + msg = f"No such file in branch '{self.rev}'" + raise OSError(errno.ENOENT, msg, relative_path) if obj.mode == GIT_MODE_DIR: - raise IOError(errno.EISDIR, "Is a directory", relative_path) + raise OSError(errno.EISDIR, "Is a directory", relative_path) # GitPython's obj.data_stream is a fragile thing, it is better to # read it immediately, also it needs to be to decoded if we follow @@ -135,6 +135,6 @@ class GitTree(BaseTree): tree = self.git_object_by_path(top) if tree is None: - raise IOError(errno.ENOENT, "No such file") + raise OSError(errno.ENOENT, "No such file") yield from self._walk(tree, topdown=topdown) diff --git a/dvc/scm/tree.py b/dvc/scm/tree.py index 4fa4aecc1..ea4967ccc 100644 --- a/dvc/scm/tree.py +++ b/dvc/scm/tree.py @@ -2,7 +2,7 @@ import os import stat -class BaseTree(object): +class BaseTree: """Abstract class to represent access to files""" @property diff --git a/dvc/stage/__init__.py b/dvc/stage/__init__.py index 0456c7948..3729b86d5 100644 --- a/dvc/stage/__init__.py +++ b/dvc/stage/__init__.py @@ -277,7 +277,7 @@ class Stage(params.StageParams): out.unprotect() continue - logger.debug("Removing output '{}' of {}.".format(out, self)) + logger.debug(f"Removing output '{out}' of {self}.") out.remove(ignore_remove=ignore_remove) def unprotect_outs(self): @@ -308,7 +308,7 @@ class Stage(params.StageParams): self.run(**kwargs) - logger.debug("{stage} was reproduced".format(stage=self)) + logger.debug(f"{self} was reproduced") return self @@ -357,7 +357,7 @@ class Stage(params.StageParams): def compute_md5(self): m = compute_md5(self) - logger.debug("Computed {} md5: '{}'".format(self, m)) + logger.debug(f"Computed {self} md5: '{m}'") return m def save(self): @@ -384,7 +384,7 @@ class Stage(params.StageParams): ] def _changed_stage_entry(self): - return "'md5' of {} changed.".format(self) + return f"'md5' of {self} changed." def changed_entries(self): changed_deps = self._changed_entries(self.deps) @@ -558,4 +558,4 @@ class PipelineStage(Stage): return self.cmd_changed def _changed_stage_entry(self): - return "'cmd' of {} has changed.".format(self) + return f"'cmd' of {self} has changed." diff --git a/dvc/stage/cache.py b/dvc/stage/cache.py index 18c2cb2f5..7a9bd216b 100644 --- a/dvc/stage/cache.py +++ b/dvc/stage/cache.py @@ -52,7 +52,7 @@ class StageCache: path = self._get_cache_path(key, value) try: - with open(path, "r") as fobj: + with open(path) as fobj: return COMPILED_LOCK_FILE_STAGE_SCHEMA(yaml.safe_load(fobj)) except FileNotFoundError: return None diff --git a/dvc/stage/exceptions.py b/dvc/stage/exceptions.py index 7ba9e37e5..6c267a832 100644 --- a/dvc/stage/exceptions.py +++ b/dvc/stage/exceptions.py @@ -3,9 +3,9 @@ from dvc.exceptions import DvcException class StageCmdFailedError(DvcException): def __init__(self, cmd, status=None): - msg = "failed to run: {}".format(cmd) + msg = f"failed to run: {cmd}" if status is not None: - msg += ", exited with {}".format(status) + msg += f", exited with {status}" super().__init__(msg) @@ -19,18 +19,18 @@ class StageFileDoesNotExistError(DvcException): def __init__(self, fname): from dvc.dvcfile import DVC_FILE_SUFFIX, is_dvc_file - msg = "'{}' does not exist.".format(fname) + msg = f"'{fname}' does not exist." sname = fname + DVC_FILE_SUFFIX if is_dvc_file(sname): - msg += " Do you mean '{}'?".format(sname) + msg += f" Do you mean '{sname}'?" super().__init__(msg) class StageFileAlreadyExistsError(DvcException): def __init__(self, relpath): - msg = "not overwriting '{}'".format(relpath) + msg = f"not overwriting '{relpath}'" super().__init__(msg) @@ -38,11 +38,11 @@ class StageFileIsNotDvcFileError(DvcException): def __init__(self, fname): from dvc.dvcfile import DVC_FILE_SUFFIX, is_dvc_file - msg = "'{}' is not a DVC-file".format(fname) + msg = f"'{fname}' is not a DVC-file" sname = fname + DVC_FILE_SUFFIX if is_dvc_file(sname): - msg += " Do you mean '{}'?".format(sname) + msg += f" Do you mean '{sname}'?" super().__init__(msg) @@ -90,7 +90,7 @@ class MissingDataSource(DvcException): class StageNotFound(KeyError, DvcException): def __init__(self, file, name): super().__init__( - "Stage '{}' not found inside '{}' file".format(name, file.relpath) + f"Stage '{name}' not found inside '{file.relpath}' file" ) @@ -98,7 +98,7 @@ class StageNameUnspecified(DvcException): def __init__(self, file): super().__init__( "Stage name not provided." - "Please specify the name as: `{0}:stage_name`".format(file.relpath) + "Please specify the name as: `{}:stage_name`".format(file.relpath) ) diff --git a/dvc/state.py b/dvc/state.py index 72e74b7b7..928c7cad9 100644 --- a/dvc/state.py +++ b/dvc/state.py @@ -29,7 +29,7 @@ class StateVersionTooNewError(DvcException): ) -class StateNoop(object): +class StateNoop: files = [] def save(self, path_info, checksum): @@ -48,7 +48,7 @@ class StateNoop(object): pass -class State(object): # pylint: disable=too-many-instance-attributes +class State: # pylint: disable=too-many-instance-attributes """Class for the state database. Args: @@ -440,7 +440,7 @@ class State(object): # pylint: disable=too-many-instance-attributes """ unused = [] - self._execute("SELECT * FROM {}".format(self.LINK_STATE_TABLE)) + self._execute(f"SELECT * FROM {self.LINK_STATE_TABLE}") for row in self.cursor: relpath, inode, mtime = row inode = self._from_sqlite(inode) diff --git a/dvc/system.py b/dvc/system.py index def0f5ebc..1f6b4d08a 100644 --- a/dvc/system.py +++ b/dvc/system.py @@ -22,7 +22,7 @@ if ( pass -class System(object): +class System: @staticmethod def is_unix(): return os.name != "nt" @@ -89,7 +89,7 @@ class System(object): try: ret = 255 - with open(src, "r") as s, open(dst, "w+") as d: + with open(src) as s, open(dst, "w+") as d: ret = fcntl.ioctl(d.fileno(), FICLONE, s.fileno()) finally: if ret != 0: @@ -111,7 +111,7 @@ class System(object): ret = System._reflink_linux(source, link_name) else: ret = -1 - except IOError: + except OSError: ret = -1 if ret != 0: diff --git a/dvc/updater.py b/dvc/updater.py index e2704b57d..3c6a28597 100644 --- a/dvc/updater.py +++ b/dvc/updater.py @@ -14,7 +14,7 @@ from dvc.utils.pkg import PKG logger = logging.getLogger(__name__) -class Updater(object): # pragma: no cover +class Updater: # pragma: no cover URL = "https://updater.dvc.org" UPDATER_FILE = "updater" TIMEOUT = 24 * 60 * 60 # every day @@ -34,7 +34,7 @@ class Updater(object): # pragma: no cover ctime = os.path.getmtime(self.updater_file) outdated = time.time() - ctime >= self.TIMEOUT if outdated: - logger.debug("'{}' is outdated(".format(self.updater_file)) + logger.debug(f"'{self.updater_file}' is outdated(") return outdated def _with_lock(self, func, action): @@ -56,7 +56,7 @@ class Updater(object): # pragma: no cover self.fetch() return - with open(self.updater_file, "r") as fobj: + with open(self.updater_file) as fobj: import json try: diff --git a/dvc/utils/fs.py b/dvc/utils/fs.py index 41ee4cac2..57a8864d5 100644 --- a/dvc/utils/fs.py +++ b/dvc/utils/fs.py @@ -96,7 +96,7 @@ def move(src, dst, mode=None): """ dst = os.path.abspath(dst) - tmp = "{}.{}".format(dst, uuid()) + tmp = f"{dst}.{uuid()}" if os.path.islink(src): # readlink does not accept path-like obj for Windows in Python <3.8 diff --git a/dvc/utils/http.py b/dvc/utils/http.py index c64bfdfda..b1fb13cb7 100644 --- a/dvc/utils/http.py +++ b/dvc/utils/http.py @@ -30,7 +30,7 @@ def iter_url(url, chunk_size=io.DEFAULT_BUFFER_SIZE): the_url = url() if callable(url) else url response = requests.get(the_url, stream=True, headers=headers) if response.status_code == 404: - raise FileNotFoundError("Can't open {}".format(the_url)) + raise FileNotFoundError(f"Can't open {the_url}") response.raise_for_status() return response @@ -49,7 +49,7 @@ def iter_url(url, chunk_size=io.DEFAULT_BUFFER_SIZE): raise # Reopen request from where we stopped - headers = {"Range": "bytes={}-".format(pos)} + headers = {"Range": f"bytes={pos}-"} response = request(headers) finally: response.close() diff --git a/dvc/utils/stage.py b/dvc/utils/stage.py index 0592400cd..759b78667 100644 --- a/dvc/utils/stage.py +++ b/dvc/utils/stage.py @@ -13,7 +13,7 @@ except ImportError: def load_stage_file(path): - with open(path, "r", encoding="utf-8") as fd: + with open(path, encoding="utf-8") as fd: return parse_stage(fd.read(), path) diff --git a/tests/basic_env.py b/tests/basic_env.py index 6ee53e6bd..1f87a9501 100644 --- a/tests/basic_env.py +++ b/tests/basic_env.py @@ -1,5 +1,3 @@ -# encoding: utf-8 - import logging import os import tempfile @@ -17,7 +15,7 @@ from dvc.utils.fs import remove logger = logging.getLogger("dvc") -class TestDirFixture(object): +class TestDirFixture: DATA_DIR = "data_dir" DATA_SUB_DIR = os.path.join(DATA_DIR, "data_sub_dir") DATA = os.path.join(DATA_DIR, "data") @@ -76,8 +74,8 @@ class TestDirFixture(object): @staticmethod def mkdtemp(base_directory=None): - prefix = "dvc-test.{}.".format(os.getpid()) - suffix = ".{}".format(shortuuid.uuid()) + prefix = f"dvc-test.{os.getpid()}." + suffix = f".{shortuuid.uuid()}" return tempfile.mkdtemp( prefix=prefix, suffix=suffix, dir=base_directory ) diff --git a/tests/conftest.py b/tests/conftest.py index 7e9e99628..4fe798381 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -31,7 +31,7 @@ def reset_loglevel(request, caplog): here = os.path.abspath(os.path.dirname(__file__)) user = "user" -key_path = os.path.join(here, "{0}.key".format(user)) +key_path = os.path.join(here, f"{user}.key") @pytest.fixture diff --git a/tests/dir_helpers.py b/tests/dir_helpers.py index 136c5c383..e54f31ab7 100644 --- a/tests/dir_helpers.py +++ b/tests/dir_helpers.py @@ -79,7 +79,7 @@ class TmpDir(pathlib.Path): self = cls._from_parts(args, init=False) if not self._flavour.is_supported: raise NotImplementedError( - "cannot instantiate %r on your system" % (cls.__name__,) + f"cannot instantiate {cls.__name__!r} on your system" ) self._init() return self @@ -263,10 +263,10 @@ def run_copy(tmp_dir, dvc): def run_copy(src, dst, **run_kwargs): return dvc.run( - cmd="python copy.py {} {}".format(src, dst), + cmd=f"python copy.py {src} {dst}", outs=[dst], deps=[src, "copy.py"], - **run_kwargs + **run_kwargs, ) return run_copy @@ -328,7 +328,7 @@ def setup_remote(make_tmp_dir): conf["core"]["remote"] = name repo.scm.add(repo.config.files["repo"]) - repo.scm.commit("add '{}' remote".format(name)) + repo.scm.commit(f"add '{name}' remote") return url return create diff --git a/tests/func/remote/test_gdrive.py b/tests/func/remote/test_gdrive.py index 885d344e7..77aacc903 100644 --- a/tests/func/remote/test_gdrive.py +++ b/tests/func/remote/test_gdrive.py @@ -44,7 +44,7 @@ def test_relative_user_credentials_file_config_setting(tmp_dir, dvc): # Check that in config we got the path relative to the config file itself # Also, we store posix path even on Windows config = configobj.ConfigObj(repo.config.files["repo"]) - assert config['remote "{}"'.format(remote_name)][ + assert config[f'remote "{remote_name}"'][ "gdrive_user_credentials_file" ] == posixpath.join("..", "secrets", "credentials.json") diff --git a/tests/func/test_add.py b/tests/func/test_add.py index 27ebc0437..11879f410 100644 --- a/tests/func/test_add.py +++ b/tests/func/test_add.py @@ -49,7 +49,7 @@ def test_add(tmp_dir, dvc): def test_add_unicode(tmp_dir, dvc): with open("\xe1", "wb") as fd: - fd.write("something".encode("utf-8")) + fd.write(b"something") (stage,) = dvc.add("\xe1") @@ -206,7 +206,7 @@ class TestAddLocalRemoteFile(TestDvc): self.dvc = DvcRepo() - foo = "remote://{}/{}".format(remote, self.FOO) + foo = f"remote://{remote}/{self.FOO}" ret = main(["add", foo]) self.assertEqual(ret, 0) @@ -525,7 +525,7 @@ def temporary_windows_drive(tmp_path_factory): new_drive_name = [ letter for letter in string.ascii_uppercase if letter not in drives ][0] - new_drive = "{}:".format(new_drive_name) + new_drive = f"{new_drive_name}:" target_path = tmp_path_factory.mktemp("tmp_windows_drive") diff --git a/tests/func/test_api.py b/tests/func/test_api.py index ca798fc18..9e7605560 100644 --- a/tests/func/test_api.py +++ b/tests/func/test_api.py @@ -41,7 +41,7 @@ def test_get_url_external(erepo_dir, remote_url, setup_remote): erepo_dir.dvc_gen("foo", "foo", commit="add foo") # Using file url to force clone to tmp repo - repo_url = "file://{}".format(erepo_dir) + repo_url = f"file://{erepo_dir}" expected_url = URLInfo(remote_url) / "ac/bd18db4cc2f85cedef654fccc4a4d8" assert api.get_url("foo", repo=repo_url) == expected_url @@ -53,7 +53,7 @@ def test_get_url_requires_dvc(tmp_dir, scm): api.get_url("foo", repo=os.fspath(tmp_dir)) with pytest.raises(UrlNotDvcRepoError): - api.get_url("foo", repo="file://{}".format(tmp_dir)) + api.get_url("foo", repo=f"file://{tmp_dir}") @pytest.mark.parametrize("remote_url", all_remote_params, indirect=True) @@ -86,7 +86,7 @@ def test_open_external(remote_url, erepo_dir, setup_remote): remove(erepo_dir.dvc.cache.local.cache_dir) # Using file url to force clone to tmp repo - repo_url = "file://{}".format(erepo_dir) + repo_url = f"file://{erepo_dir}" with api.open("version", repo=repo_url) as fd: assert fd.read() == "master" @@ -121,7 +121,7 @@ def test_open_not_cached(dvc): dvc.run( single_stage=True, metrics_no_cache=[metric_file], - cmd=('python -c "{}"'.format(metric_code)), + cmd=(f'python -c "{metric_code}"'), ) with api.open(metric_file) as fd: diff --git a/tests/func/test_checkout.py b/tests/func/test_checkout.py index 24d9b06d0..171f16c93 100644 --- a/tests/func/test_checkout.py +++ b/tests/func/test_checkout.py @@ -257,7 +257,7 @@ class TestGitIgnoreBasic(CheckoutBase): self.commit_data_file(fname2) self.dvc.run( single_stage=True, - cmd="python {} {} {}".format(self.CODE, self.FOO, fname3), + cmd=f"python {self.CODE} {self.FOO} {fname3}", deps=[self.CODE, self.FOO], outs_no_cache=[fname3], ) diff --git a/tests/func/test_cli.py b/tests/func/test_cli.py index 1d89d3fef..bd19836c5 100644 --- a/tests/func/test_cli.py +++ b/tests/func/test_cli.py @@ -164,7 +164,7 @@ class TestFindRoot(TestDvc): def test(self): os.chdir("..") - class A(object): + class A: quiet = False verbose = True diff --git a/tests/func/test_config.py b/tests/func/test_config.py index e306e3242..0efd4acea 100644 --- a/tests/func/test_config.py +++ b/tests/func/test_config.py @@ -34,7 +34,7 @@ class TestConfigCLI(TestDvc): def _do_test(self, local=False): section = "core" field = "analytics" - section_field = "{}.{}".format(section, field) + section_field = f"{section}.{field}" value = "True" newvalue = "False" diff --git a/tests/func/test_data_cloud.py b/tests/func/test_data_cloud.py index bca698bc4..9a55eae81 100644 --- a/tests/func/test_data_cloud.py +++ b/tests/func/test_data_cloud.py @@ -87,9 +87,7 @@ class TestDataCloudBase(TestDvc): def _ensure_should_run(self): if not self.should_test(): - raise SkipTest( - "Test {} is disabled".format(self.__class__.__name__) - ) + raise SkipTest(f"Test {self.__class__.__name__} is disabled") def _setup_cloud(self): self._ensure_should_run() @@ -167,7 +165,7 @@ class TestDataCloudBase(TestDvc): self.cloud.pull(info) self.assertTrue(os.path.exists(cache)) self.assertTrue(os.path.isfile(cache)) - with open(cache, "r") as fd: + with open(cache) as fd: self.assertEqual(fd.read(), self.FOO_CONTENTS) self.cloud.pull(info_dir) @@ -366,7 +364,7 @@ class TestDataCloudCLIBase(TestDvc): self.assertTrue(os.path.isfile(self.FOO)) self.assertTrue(os.path.isdir(self.DATA_DIR)) - with open(cache, "r") as fd: + with open(cache) as fd: self.assertEqual(fd.read(), self.FOO_CONTENTS) self.assertTrue(os.path.isfile(cache_dir)) @@ -391,9 +389,7 @@ class TestDataCloudCLIBase(TestDvc): def test(self): if not self.should_test(): - raise SkipTest( - "Test {} is disabled".format(self.__class__.__name__) - ) + raise SkipTest(f"Test {self.__class__.__name__} is disabled") self._test() diff --git a/tests/func/test_external_repo.py b/tests/func/test_external_repo.py index a36848455..3adefbb30 100644 --- a/tests/func/test_external_repo.py +++ b/tests/func/test_external_repo.py @@ -51,7 +51,7 @@ def test_cache_reused(erepo_dir, mocker, setup_remote): download_spy = mocker.spy(LocalRemote, "download") # Use URL to prevent any fishy optimizations - url = "file://{}".format(erepo_dir) + url = f"file://{erepo_dir}" with external_repo(url) as repo: repo.fetch() assert download_spy.mock.call_count == 1 @@ -66,7 +66,7 @@ def test_cache_reused(erepo_dir, mocker, setup_remote): def test_known_sha(erepo_dir): erepo_dir.scm.commit("init") - url = "file://{}".format(erepo_dir) + url = f"file://{erepo_dir}" with external_repo(url) as repo: rev = repo.scm.get_rev() prev_rev = repo.scm.resolve_rev("HEAD^") diff --git a/tests/func/test_ignore.py b/tests/func/test_ignore.py index 821cb72fc..65ad950c4 100644 --- a/tests/func/test_ignore.py +++ b/tests/func/test_ignore.py @@ -1,4 +1,3 @@ -# encoding: utf-8 import os import shutil diff --git a/tests/func/test_import.py b/tests/func/test_import.py index 14e44f70b..6ab037c8b 100644 --- a/tests/func/test_import.py +++ b/tests/func/test_import.py @@ -141,9 +141,7 @@ def test_import_non_cached(erepo_dir, tmp_dir, dvc, scm): with erepo_dir.chdir(): erepo_dir.dvc.run( - cmd="echo hello > {}".format(src), - outs_no_cache=[src], - single_stage=True, + cmd=f"echo hello > {src}", outs_no_cache=[src], single_stage=True, ) erepo_dir.scm_add( diff --git a/tests/func/test_install.py b/tests/func/test_install.py index 514bdee61..d71f26dcf 100644 --- a/tests/func/test_install.py +++ b/tests/func/test_install.py @@ -11,7 +11,7 @@ from dvc.utils import file_md5 @pytest.mark.skipif( sys.platform == "win32", reason="Git hooks aren't supported on Windows" ) -class TestInstall(object): +class TestInstall: def _hook(self, name): return pathlib.Path(".git") / "hooks" / name diff --git a/tests/func/test_ls.py b/tests/func/test_ls.py index b1f71e6aa..aa8383cdd 100644 --- a/tests/func/test_ls.py +++ b/tests/func/test_ls.py @@ -298,7 +298,7 @@ def test_ls_remote_repo(erepo_dir): erepo_dir.scm_gen(FS_STRUCTURE, commit="init") erepo_dir.dvc_gen(DVC_STRUCTURE, commit="dvc") - url = "file://{}".format(erepo_dir) + url = f"file://{erepo_dir}" files = Repo.ls(url) match_files( files, @@ -318,7 +318,7 @@ def test_ls_remote_repo_recursive(erepo_dir): erepo_dir.scm_gen(FS_STRUCTURE, commit="init") erepo_dir.dvc_gen(DVC_STRUCTURE, commit="dvc") - url = "file://{}".format(erepo_dir) + url = f"file://{erepo_dir}" files = Repo.ls(url, recursive=True) match_files( files, @@ -346,7 +346,7 @@ def test_ls_remote_git_only_repo_recursive(git_dir): with git_dir.chdir(): git_dir.scm_gen(FS_STRUCTURE, commit="init") - url = "file://{}".format(git_dir) + url = f"file://{git_dir}" files = Repo.ls(url, recursive=True) match_files( files, @@ -364,7 +364,7 @@ def test_ls_remote_repo_with_path_dir(erepo_dir): erepo_dir.scm_gen(FS_STRUCTURE, commit="init") erepo_dir.dvc_gen(DVC_STRUCTURE, commit="dvc") - url = "file://{}".format(erepo_dir) + url = f"file://{erepo_dir}" path = "model" files = Repo.ls(url, path) match_files( @@ -385,7 +385,7 @@ def test_ls_remote_repo_with_rev(erepo_dir): erepo_dir.dvc_gen(DVC_STRUCTURE, commit="dvc") rev = erepo_dir.scm.list_all_commits()[1] - url = "file://{}".format(erepo_dir) + url = f"file://{erepo_dir}" files = Repo.ls(url, rev=rev) match_files( files, @@ -403,7 +403,7 @@ def test_ls_remote_repo_with_rev_recursive(erepo_dir): erepo_dir.scm_gen(FS_STRUCTURE, commit="init") rev = erepo_dir.scm.list_all_commits()[1] - url = "file://{}".format(erepo_dir) + url = f"file://{erepo_dir}" files = Repo.ls(url, rev=rev, recursive=True) match_files( files, diff --git a/tests/func/test_move.py b/tests/func/test_move.py index c8ce7a3c2..53c8b920d 100644 --- a/tests/func/test_move.py +++ b/tests/func/test_move.py @@ -140,7 +140,7 @@ class TestMoveDirectoryShouldNotOverwriteExisting(TestDvcGit): self.assertTrue(os.path.exists(dir_name)) self.assertEqual( set(os.listdir(dir_name)), - set([".gitignore", data_dir_stage, self.DATA_DIR]), + {".gitignore", data_dir_stage, self.DATA_DIR}, ) self.assertTrue(os.path.exists(new_dir_name)) diff --git a/tests/func/test_remote.py b/tests/func/test_remote.py index 68dcf5cd2..d8217eda0 100644 --- a/tests/func/test_remote.py +++ b/tests/func/test_remote.py @@ -265,7 +265,7 @@ def test_remote_modify_validation(dvc): == 251 ) config = configobj.ConfigObj(dvc.config.files["repo"]) - assert unsupported_config not in config['remote "{}"'.format(remote_name)] + assert unsupported_config not in config[f'remote "{remote_name}"'] def test_remote_modify_default(dvc): diff --git a/tests/func/test_repo.py b/tests/func/test_repo.py index ebcf69a96..5fc55c119 100644 --- a/tests/func/test_repo.py +++ b/tests/func/test_repo.py @@ -58,11 +58,11 @@ def test_destroy(tmp_dir, dvc, run_copy): def test_collect(tmp_dir, scm, dvc, run_copy): def collect_outs(*args, **kwargs): - return set( + return { str(out) for stage in dvc.collect(*args, **kwargs) for out in stage.outs - ) + } tmp_dir.dvc_gen("foo", "foo") run_copy("foo", "bar", single_stage=True) @@ -100,7 +100,7 @@ def test_collect(tmp_dir, scm, dvc, run_copy): def test_stages(tmp_dir, dvc): def stages(): - return set(stage.relpath for stage in Repo(os.fspath(tmp_dir)).stages) + return {stage.relpath for stage in Repo(os.fspath(tmp_dir)).stages} tmp_dir.dvc_gen({"file": "a", "dir/file": "b", "dir/subdir/file": "c"}) diff --git a/tests/func/test_repro.py b/tests/func/test_repro.py index 0c4b3b124..319af0dbe 100644 --- a/tests/func/test_repro.py +++ b/tests/func/test_repro.py @@ -74,7 +74,7 @@ class TestRepro(SingleStageRun, TestDvc): fname=self.file1_stage, outs=[self.file1], deps=[self.FOO, self.CODE], - cmd="python {} {} {}".format(self.CODE, self.FOO, self.file1), + cmd=f"python {self.CODE} {self.FOO} {self.file1}", name="run1", ) @@ -146,7 +146,7 @@ class TestReproWorkingDirectoryAsOutput(TestDvc): output = os.path.join("..", "something") stage_dump = { - "cmd": "echo something > {}".format(output), + "cmd": f"echo something > {output}", "outs": [{"path": output}], } dump_stage_file(faulty_stage_path, stage_dump) @@ -175,7 +175,7 @@ class TestReproWorkingDirectoryAsOutput(TestDvc): fname=os.path.join(dir1, "b.dvc"), wdir=dir1, outs=[out_dir], # ../a/nested - cmd="mkdir {path}".format(path=out_dir), + cmd=f"mkdir {out_dir}", single_stage=True, ) @@ -185,7 +185,7 @@ class TestReproWorkingDirectoryAsOutput(TestDvc): output = os.path.join("..", "..", "something") stage_dump = { - "cmd": "echo something > {}".format(output), + "cmd": f"echo something > {output}", "outs": [{"path": output}], } dump_stage_file(error_stage_path, stage_dump) @@ -240,7 +240,7 @@ class TestReproDepUnderDir(SingleStageRun, TestDvc): fname=self.file1 + ".dvc", outs=[self.file1], deps=[self.DATA, self.CODE], - cmd="python {} {} {}".format(self.CODE, self.DATA, self.file1), + cmd=f"python {self.CODE} {self.DATA} {self.file1}", name="copy-data-file1", ) @@ -277,7 +277,7 @@ class TestReproDepDirWithOutputsUnderIt(SingleStageRun, TestDvc): fname=file1_stage, deps=[self.DATA_DIR], outs=[file1], - cmd="python {} {} {}".format(self.CODE, self.DATA, file1), + cmd=f"python {self.CODE} {self.DATA} {file1}", name="copy-data-file1", ) self.assertTrue(stage is not None) @@ -303,7 +303,7 @@ class TestReproNoDeps(TestRepro): stage = self._run( fname=stage_file, outs=[out], - cmd="python {}".format(code_file), + cmd=f"python {code_file}", name="uuid", ) @@ -377,8 +377,8 @@ class TestReproDryNoExec(TestDvc): def test(self): deps = [] for d in range(3): - idir = "idir{}".format(d) - odir = "odir{}".format(d) + idir = f"idir{d}" + odir = f"odir{d}" deps.append("-d") deps.append(odir) @@ -422,7 +422,7 @@ class TestReproChangedDeepData(TestReproChangedData): fname=self.file2 + ".dvc", outs=[self.file2], deps=[self.file1, self.CODE], - cmd="python {} {} {}".format(self.CODE, self.file1, self.file2), + cmd=f"python {self.CODE} {self.file1} {self.file2}", name="copy-file-file2", ) @@ -449,7 +449,7 @@ class TestReproForceDownstream(TestDvc): file1_stage = self.dvc.run( outs=[file1], deps=[self.FOO, code1], - cmd="python {} {} {}".format(code1, self.FOO, file1), + cmd=f"python {code1} {self.FOO} {file1}", single_stage=True, ) self.assertTrue(file1_stage is not None) @@ -460,7 +460,7 @@ class TestReproForceDownstream(TestDvc): file2_stage = self.dvc.run( outs=[file2], deps=[file1, code2], - cmd="python {} {} {}".format(code2, file1, file2), + cmd=f"python {code2} {file1} {file2}", single_stage=True, ) self.assertTrue(file2_stage is not None) @@ -471,7 +471,7 @@ class TestReproForceDownstream(TestDvc): file3_stage = self.dvc.run( outs=[file3], deps=[file2, code3], - cmd="python {} {} {}".format(code3, file2, file3), + cmd=f"python {code3} {file2} {file3}", single_stage=True, ) self.assertTrue(file3_stage is not None) @@ -518,7 +518,7 @@ class TestReproPipelines(SingleStageRun, TestDvc): fname=self.file1 + ".dvc", outs=[self.file1], deps=[self.FOO, self.CODE], - cmd="python {} {} {}".format(self.CODE, self.FOO, self.file1), + cmd=f"python {self.CODE} {self.FOO} {self.file1}", single_stage=True, ) @@ -527,7 +527,7 @@ class TestReproPipelines(SingleStageRun, TestDvc): fname=self.file2 + ".dvc", outs=[self.file2], deps=[self.BAR, self.CODE], - cmd="python {} {} {}".format(self.CODE, self.BAR, self.file2), + cmd=f"python {self.CODE} {self.BAR} {self.file2}", name="copy-BAR-file2", ) @@ -549,7 +549,7 @@ class TestReproLocked(TestReproChangedData): fname=file2 + ".dvc", outs=[file2], deps=[self.file1, self.CODE], - cmd="python {} {} {}".format(self.CODE, self.file1, file2), + cmd=f"python {self.CODE} {self.file1} {file2}", name="copy-file1-file2", ) @@ -590,7 +590,7 @@ class TestReproLockedCallback(SingleStageRun, TestDvc): stage = self._run( fname=file1_stage, outs=[file1], - cmd="python {} {} {}".format(self.CODE, self.FOO, file1), + cmd=f"python {self.CODE} {self.FOO} {file1}", name="copy-FOO-file1", ) self.assertTrue(stage is not None) @@ -637,7 +637,7 @@ class TestReproMetricsAddUnchanged(TestDvc): fname=file1_stage, outs_no_cache=[file1], deps=[self.FOO, self.CODE], - cmd="python {} {} {}".format(self.CODE, self.FOO, file1), + cmd=f"python {self.CODE} {self.FOO} {file1}", single_stage=True, ) @@ -702,7 +702,7 @@ class TestReproChangedDir(SingleStageRun, TestDvc): stage = self._run( outs=[dir_name], deps=[file_name, dir_code], - cmd="python {}".format(dir_code), + cmd=f"python {dir_code}", name="copy-in-dir", ) target = self._get_stage_target(stage) @@ -731,7 +731,7 @@ class TestReproChangedDirData(SingleStageRun, TestDvc): stage = self._run( outs=[dir_name], deps=[self.DATA_DIR, dir_code], - cmd="python {} {} {}".format(dir_code, self.DATA_DIR, dir_name), + cmd=f"python {dir_code} {self.DATA_DIR} {dir_name}", name="copy-dir", ) target = self._get_stage_target(stage) @@ -801,14 +801,14 @@ class TestCmdReproChdir(TestDvc): "run", "--single-stage", "-f", - "{}/Dvcfile".format(dname), + f"{dname}/Dvcfile", "-w", - "{}".format(dname), + f"{dname}", "-d", self.FOO, "-o", self.BAR, - "python {} {} {}".format(self.CODE, self.FOO, self.BAR), + f"python {self.CODE} {self.FOO} {self.BAR}", ] ) self.assertEqual(ret, 0) @@ -878,9 +878,7 @@ class TestReproExternalBase(SingleStageRun, TestDvc): @patch("dvc.prompt.confirm", return_value=True) def test(self, mock_prompt): if not self.should_test(): - raise SkipTest( - "Test {} is disabled".format(self.__class__.__name__) - ) + raise SkipTest(f"Test {self.__class__.__name__} is disabled") cache = ( self.scheme @@ -991,7 +989,7 @@ class TestReproExternalS3(S3, TestReproExternalBase): return TEST_AWS_REPO_BUCKET def cmd(self, i, o): - return "aws s3 cp {} {}".format(i, o) + return f"aws s3 cp {i} {o}" def write(self, bucket, key, body): s3 = boto3.client("s3") @@ -1008,7 +1006,7 @@ class TestReproExternalGS(GCP, TestReproExternalBase): return TEST_GCP_REPO_BUCKET def cmd(self, i, o): - return "gsutil cp {} {}".format(i, o) + return f"gsutil cp {i} {o}" def write(self, bucket, key, body): client = gc.Client() @@ -1023,15 +1021,15 @@ class TestReproExternalHDFS(HDFS, TestReproExternalBase): @property def bucket(self): - return "{}@127.0.0.1".format(getpass.getuser()) + return f"{getpass.getuser()}@127.0.0.1" def cmd(self, i, o): - return "hadoop fs -cp {} {}".format(i, o) + return f"hadoop fs -cp {i} {o}" def write(self, bucket, key, body): url = self.scheme + "://" + bucket + "/" + key p = Popen( - "hadoop fs -rm -f {}".format(url), + f"hadoop fs -rm -f {url}", shell=True, executable=os.getenv("SHELL"), stdin=PIPE, @@ -1085,14 +1083,14 @@ class TestReproExternalSSH(SSH, TestReproExternalBase): def bucket(self): if not self._dir: self._dir = self.mkdtemp() - return "{}@127.0.0.1:{}".format(getpass.getuser(), self._dir) + return f"{getpass.getuser()}@127.0.0.1:{self._dir}" def cmd(self, i, o): prefix = "ssh://" assert i.startswith(prefix) and o.startswith(prefix) i = i[len(prefix) :] o = o[len(prefix) :] - return "scp {} {}".format(i, o) + return f"scp {i} {o}" def write(self, bucket, key, body): path = posixpath.join(self._dir, key) @@ -1106,12 +1104,10 @@ class TestReproExternalSSH(SSH, TestReproExternalBase): try: sftp.stat(path) sftp.remove(path) - except IOError: + except OSError: pass - stdin, stdout, stderr = ssh.exec_command( - "mkdir -p $(dirname {})".format(path) - ) + stdin, stdout, stderr = ssh.exec_command(f"mkdir -p $(dirname {path})") self.assertEqual(stdout.channel.recv_exit_status(), 0) with sftp.open(path, "w+") as fobj: @@ -1150,8 +1146,8 @@ class TestReproExternalLOCAL(Local, TestReproExternalBase): def cmd(self, i, o): if os.name == "nt": - return "copy {} {}".format(i, o) - return "cp {} {}".format(i, o) + return f"copy {i} {o}" + return f"cp {i} {o}" def write(self, bucket, key, body): path = os.path.join(bucket, key) @@ -1169,7 +1165,7 @@ class TestReproExternalHTTP(TestReproExternalBase): @staticmethod def get_remote(port): - return "http://localhost:{}/".format(port) + return f"http://localhost:{port}/" @property def local_cache(self): @@ -1211,7 +1207,7 @@ class TestReproExternalHTTP(TestReproExternalBase): run_dependency = urljoin(remote, self.BAR) run_output = "remote_file" - cmd = 'open("{}", "w+")'.format(run_output) + cmd = f'open("{run_output}", "w+")' with open("create-output.py", "w") as fd: fd.write(cmd) @@ -1249,18 +1245,18 @@ class TestReproShell(TestDvc): self.dvc.run( fname=stage, outs=[fname], - cmd="echo $SHELL > {}".format(fname), + cmd=f"echo $SHELL > {fname}", single_stage=True, ) - with open(fname, "r") as fd: + with open(fname) as fd: self.assertEqual(os.getenv("SHELL"), fd.read().strip()) os.unlink(fname) self.dvc.reproduce(stage) - with open(fname, "r") as fd: + with open(fname) as fd: self.assertEqual(os.getenv("SHELL"), fd.read().strip()) @@ -1386,7 +1382,7 @@ class TestShouldDisplayMetricsOnReproWithMetricsOption(TestDvc): "--single-stage", "-m", metrics_file, - "echo {} >> {}".format(metrics_value, metrics_file), + f"echo {metrics_value} >> {metrics_file}", ] ) self.assertEqual(0, ret) @@ -1400,7 +1396,7 @@ class TestShouldDisplayMetricsOnReproWithMetricsOption(TestDvc): ) self.assertEqual(0, ret) - expected_metrics_display = "{}: {}".format(metrics_file, metrics_value) + expected_metrics_display = f"{metrics_file}: {metrics_value}" self.assertIn(expected_metrics_display, self._caplog.text) diff --git a/tests/func/test_repro_multistage.py b/tests/func/test_repro_multistage.py index e9fd3f3a9..63b3b8755 100644 --- a/tests/func/test_repro_multistage.py +++ b/tests/func/test_repro_multistage.py @@ -492,7 +492,7 @@ def test_cyclic_graph_error(tmp_dir, dvc, run_copy): run_copy("bar", "baz", name="copy-bar-baz") run_copy("baz", "foobar", name="copy-baz-foobar") - with open(PIPELINE_FILE, "r") as f: + with open(PIPELINE_FILE) as f: data = parse_stage(f.read(), PIPELINE_FILE) data["stages"]["copy-baz-foo"] = { "cmd": "echo baz > foo", diff --git a/tests/func/test_run_multistage.py b/tests/func/test_run_multistage.py index 13a357727..078afa888 100644 --- a/tests/func/test_run_multistage.py +++ b/tests/func/test_run_multistage.py @@ -45,7 +45,7 @@ def test_run_multi_stage_repeat(tmp_dir, dvc, run_copy): stages = list(Dvcfile(dvc, PIPELINE_FILE).stages.values()) assert len(stages) == 2 assert all(isinstance(stage, PipelineStage) for stage in stages) - assert set(stage.name for stage in stages) == { + assert {stage.name for stage in stages} == { "copy-foo-foo1", "copy-foo1-foo2", } @@ -183,7 +183,7 @@ def test_run_dump_on_multistage(tmp_dir, dvc, run_head): ) def test_run_with_invalid_stage_name(run_copy, char): with pytest.raises(InvalidStageName): - run_copy("foo", "bar", name="copy_name-{}".format(char)) + run_copy("foo", "bar", name=f"copy_name-{char}") def test_run_with_name_having_hyphen_underscore(tmp_dir, dvc, run_copy): diff --git a/tests/func/test_run_single_stage.py b/tests/func/test_run_single_stage.py index 57b07926e..2e7956281 100644 --- a/tests/func/test_run_single_stage.py +++ b/tests/func/test_run_single_stage.py @@ -110,7 +110,7 @@ class TestRunNoExec(TestDvcGit): single_stage=True, ) self.assertFalse(os.path.exists("out")) - with open(".gitignore", "r") as fobj: + with open(".gitignore") as fobj: self.assertEqual(fobj.read(), "/out\n") @@ -233,7 +233,7 @@ class TestRunBadCwd(TestDvc): def test_same_prefix(self): with self.assertRaises(StagePathOutsideError): - path = "{}-{}".format(self._root_dir, uuid.uuid4()) + path = f"{self._root_dir}-{uuid.uuid4()}" os.mkdir(path) self.dvc.run(cmd="", wdir=path, single_stage=True) @@ -245,7 +245,7 @@ class TestRunBadWdir(TestDvc): def test_same_prefix(self): with self.assertRaises(StagePathOutsideError): - path = "{}-{}".format(self._root_dir, uuid.uuid4()) + path = f"{self._root_dir}-{uuid.uuid4()}" os.mkdir(path) self.dvc.run(cmd="", wdir=path, single_stage=True) @@ -276,7 +276,7 @@ class TestRunBadName(TestDvc): def test_same_prefix(self): with self.assertRaises(StagePathOutsideError): - path = "{}-{}".format(self._root_dir, uuid.uuid4()) + path = f"{self._root_dir}-{uuid.uuid4()}" os.mkdir(path) self.dvc.run( cmd="", @@ -306,7 +306,7 @@ class TestRunRemoveOuts(TestDvc): self.dvc.run( deps=[self.CODE], outs=[self.FOO], - cmd="python {} {}".format(self.CODE, self.FOO), + cmd=f"python {self.CODE} {self.FOO}", single_stage=True, ) @@ -336,7 +336,7 @@ class TestRunUnprotectOutsCopy(TestDvc): ) self.assertEqual(ret, 0) self.assertTrue(os.access(self.FOO, os.W_OK)) - with open(self.FOO, "r") as fd: + with open(self.FOO) as fd: self.assertEqual(fd.read(), "foo") ret = main( @@ -356,7 +356,7 @@ class TestRunUnprotectOutsCopy(TestDvc): ) self.assertEqual(ret, 0) self.assertTrue(os.access(self.FOO, os.W_OK)) - with open(self.FOO, "r") as fd: + with open(self.FOO) as fd: self.assertEqual(fd.read(), "foo") @@ -394,7 +394,7 @@ class TestRunUnprotectOutsSymlink(TestDvc): self.assertFalse(os.access(self.FOO, os.W_OK)) self.assertTrue(System.is_symlink(self.FOO)) - with open(self.FOO, "r") as fd: + with open(self.FOO) as fd: self.assertEqual(fd.read(), "foo") ret = main( @@ -421,7 +421,7 @@ class TestRunUnprotectOutsSymlink(TestDvc): self.assertFalse(os.access(self.FOO, os.W_OK)) self.assertTrue(System.is_symlink(self.FOO)) - with open(self.FOO, "r") as fd: + with open(self.FOO) as fd: self.assertEqual(fd.read(), "foo") @@ -453,7 +453,7 @@ class TestRunUnprotectOutsHardlink(TestDvc): self.assertEqual(ret, 0) self.assertFalse(os.access(self.FOO, os.W_OK)) self.assertTrue(System.is_hardlink(self.FOO)) - with open(self.FOO, "r") as fd: + with open(self.FOO) as fd: self.assertEqual(fd.read(), "foo") ret = main( @@ -474,7 +474,7 @@ class TestRunUnprotectOutsHardlink(TestDvc): self.assertEqual(ret, 0) self.assertFalse(os.access(self.FOO, os.W_OK)) self.assertTrue(System.is_hardlink(self.FOO)) - with open(self.FOO, "r") as fd: + with open(self.FOO) as fd: self.assertEqual(fd.read(), "foo") @@ -594,7 +594,7 @@ class TestCmdRunCliMetrics(TestDvc): ] ) self.assertEqual(ret, 0) - with open("metrics.txt", "r") as fd: + with open("metrics.txt") as fd: self.assertEqual(fd.read().rstrip(), "test") def test_not_cached(self): @@ -608,14 +608,14 @@ class TestCmdRunCliMetrics(TestDvc): ] ) self.assertEqual(ret, 0) - with open("metrics.txt", "r") as fd: + with open("metrics.txt") as fd: self.assertEqual(fd.read().rstrip(), "test") class TestCmdRunWorkingDirectory(TestDvc): def test_default_wdir_is_not_written(self): stage = self.dvc.run( - cmd="echo test > {}".format(self.FOO), + cmd=f"echo test > {self.FOO}", outs=[self.FOO], wdir=".", single_stage=True, @@ -624,9 +624,7 @@ class TestCmdRunWorkingDirectory(TestDvc): self.assertNotIn(Stage.PARAM_WDIR, d.keys()) stage = self.dvc.run( - cmd="echo test > {}".format(self.BAR), - outs=[self.BAR], - single_stage=True, + cmd=f"echo test > {self.BAR}", outs=[self.BAR], single_stage=True, ) d = load_stage_file(stage.relpath) self.assertNotIn(Stage.PARAM_WDIR, d.keys()) @@ -637,7 +635,7 @@ class TestCmdRunWorkingDirectory(TestDvc): foo = os.path.join(dname, self.FOO) fname = os.path.join(dname, "stage" + DVC_FILE_SUFFIX) stage = self.dvc.run( - cmd="echo test > {}".format(foo), + cmd=f"echo test > {foo}", outs=[foo], fname=fname, single_stage=True, @@ -761,7 +759,7 @@ class TestRunPersist(TestDvc): "--single-stage", self.outs_command, file, - "echo {} >> {}".format(file_content, file), + f"echo {file_content} >> {file}", ] ) self.assertEqual(0, ret) @@ -776,7 +774,7 @@ class TestRunPersist(TestDvc): ret = main(["repro", stage_file]) self.assertEqual(0, ret) - with open(file, "r") as fobj: + with open(file) as fobj: lines = fobj.readlines() self.assertEqual(2, len(lines)) @@ -813,7 +811,7 @@ class TestShouldRaiseOnOverlappingOutputPaths(TestDvc): with self.assertRaises(OverlappingOutputPathsError) as err: self.dvc.run( outs=[self.DATA], - cmd="echo data >> {}".format(self.DATA), + cmd=f"echo data >> {self.DATA}", single_stage=True, ) error_output = str(err.exception) @@ -823,12 +821,9 @@ class TestShouldRaiseOnOverlappingOutputPaths(TestDvc): self.assertIn("Paths for outs:\n", error_output) self.assertIn( - "\n'{}'('{}')\n".format(self.DATA_DIR, data_dir_stage), - error_output, - ) - self.assertIn( - "\n'{}'('{}')\n".format(self.DATA, data_stage), error_output + f"\n'{self.DATA_DIR}'('{data_dir_stage}')\n", error_output, ) + self.assertIn(f"\n'{self.DATA}'('{data_stage}')\n", error_output) self.assertIn( "\noverlap. To avoid unpredictable behaviour, rerun " "command with non overlapping outs paths.", @@ -838,7 +833,7 @@ class TestShouldRaiseOnOverlappingOutputPaths(TestDvc): class TestRerunWithSameOutputs(TestDvc): def _read_content_only(self, path): - with open(path, "r") as fobj: + with open(path) as fobj: return [line.rstrip() for line in fobj] @property @@ -852,7 +847,7 @@ class TestRerunWithSameOutputs(TestDvc): "--single-stage", "--outs", self.FOO, - "echo {} > {}".format(self.FOO_CONTENTS, self.FOO), + f"echo {self.FOO_CONTENTS} > {self.FOO}", ] ) self.assertEqual(0, ret) @@ -867,7 +862,7 @@ class TestRerunWithSameOutputs(TestDvc): self.FOO, "--overwrite-dvcfile", "--single-stage", - "echo {} >> {}".format(self.BAR_CONTENTS, self.FOO), + f"echo {self.BAR_CONTENTS} >> {self.FOO}", ] ) self.assertEqual(0, ret) @@ -907,7 +902,7 @@ class TestShouldNotCheckoutUponCorruptedLocalHardlinkCache(TestDvc): self.dvc = DvcRepo(".") def test(self): - cmd = "python {} {} {}".format(self.CODE, self.FOO, self.BAR) + cmd = f"python {self.CODE} {self.FOO} {self.BAR}" stage = self.dvc.run( deps=[self.FOO], outs=[self.BAR], cmd=cmd, single_stage=True ) @@ -959,7 +954,7 @@ class TestPersistentOutput(TestDvc): # Even if the "immutable" dependency didn't change # it should run the command again, as it is "ignoring build cache" - with open("greetings", "r") as fobj: + with open("greetings") as fobj: assert "hello\nhello\n" == fobj.read() diff --git a/tests/func/test_stage.py b/tests/func/test_stage.py index 78a430754..284fe3b48 100644 --- a/tests/func/test_stage.py +++ b/tests/func/test_stage.py @@ -94,7 +94,7 @@ class TestReload(TestDvc): class TestDefaultWorkingDirectory(TestDvc): def test_ignored_in_checksum(self): stage = self.dvc.run( - cmd="echo test > {}".format(self.FOO), + cmd=f"echo test > {self.FOO}", deps=[self.BAR], outs=[self.FOO], single_stage=True, @@ -128,7 +128,7 @@ class TestExternalRemoteResolution(TestDvc): "--single-stage", "-O", "remote://storage/file", - "echo file > {path}".format(path=file_path), + f"echo file > {file_path}", ] ) == 0 diff --git a/tests/func/test_status.py b/tests/func/test_status.py index 477406eda..e94934f19 100644 --- a/tests/func/test_status.py +++ b/tests/func/test_status.py @@ -38,7 +38,7 @@ def test_status_non_dvc_repo_import(tmp_dir, dvc, git_dir): (status,) = dvc.status(["file.dvc"])["file.dvc"] assert status == { - "changed deps": {"file ({})".format(git_dir): "update available"} + "changed deps": {f"file ({git_dir})": "update available"} } diff --git a/tests/func/test_tree.py b/tests/func/test_tree.py index 18748985e..813929105 100644 --- a/tests/func/test_tree.py +++ b/tests/func/test_tree.py @@ -1,5 +1,3 @@ -# encoding: utf-8 - from os.path import join from dvc.ignore import CleanTree @@ -36,7 +34,7 @@ class TestWorkingTree(TestDir): self.assertFalse(self.tree.isfile("not-existing-file")) -class GitTreeTests(object): +class GitTreeTests: def test_open(self): self.scm.add([self.FOO, self.UNICODE, self.DATA_DIR]) self.scm.commit("add") @@ -90,7 +88,7 @@ class TestGitSubmoduleTree(TestGitSubmodule, GitTreeTests): self._pushd(self._root_dir) -class AssertWalkEqualMixin(object): +class AssertWalkEqualMixin: def assertWalkEqual(self, actual, expected, msg=None): def convert_to_sets(walk_results): return [ diff --git a/tests/func/test_utils.py b/tests/func/test_utils.py index 996b2ce2f..b3478e650 100644 --- a/tests/func/test_utils.py +++ b/tests/func/test_utils.py @@ -1,5 +1,3 @@ -# encoding: utf-8 - from dvc import utils diff --git a/tests/remotes.py b/tests/remotes.py index 3dd3eace7..91d1edb11 100644 --- a/tests/remotes.py +++ b/tests/remotes.py @@ -180,11 +180,11 @@ class OSS: @staticmethod def get_storagepath(): - return "{}/{}".format(TEST_OSS_REPO_BUCKET, (uuid.uuid4())) + return f"{TEST_OSS_REPO_BUCKET}/{uuid.uuid4()}" @staticmethod def get_url(): - return "oss://{}".format(OSS.get_storagepath()) + return f"oss://{OSS.get_storagepath()}" class SSH: @@ -200,7 +200,7 @@ class SSH: try: check_output(["ssh", "-o", "BatchMode=yes", "127.0.0.1", "ls"]) - except (CalledProcessError, IOError): + except (CalledProcessError, OSError): return False return True @@ -233,7 +233,7 @@ class SSHMocked: drive, path = os.path.splitdrive(path) assert drive.lower() == "c:" path = path.replace("\\", "/") - url = "ssh://{}@127.0.0.1:{}{}".format(user, port, path) + url = f"ssh://{user}@127.0.0.1:{port}{path}" return url @@ -249,7 +249,7 @@ class HDFS: shell=True, executable=os.getenv("SHELL"), ) - except (CalledProcessError, IOError): + except (CalledProcessError, OSError): return False p = Popen( @@ -275,4 +275,4 @@ class HTTP: @staticmethod def get_url(port): - return "http://127.0.0.1:{}".format(port) + return f"http://127.0.0.1:{port}" diff --git a/tests/unit/remote/ssh/test_connection.py b/tests/unit/remote/ssh/test_connection.py index 3e9e16cb4..abaaa2051 100644 --- a/tests/unit/remote/ssh/test_connection.py +++ b/tests/unit/remote/ssh/test_connection.py @@ -72,7 +72,7 @@ def test_walk(tmp_path, ssh): dir_data_path, subdir_data_path, ] - expected = set([entry.absolute().as_posix() for entry in entries]) + expected = {entry.absolute().as_posix() for entry in entries} paths = set() for root, dirs, files in ssh.walk(root_path.absolute().as_posix()): diff --git a/tests/unit/remote/ssh/test_ssh.py b/tests/unit/remote/ssh/test_ssh.py index f88545281..037ebe197 100644 --- a/tests/unit/remote/ssh/test_ssh.py +++ b/tests/unit/remote/ssh/test_ssh.py @@ -17,14 +17,14 @@ def test_url(dvc): path = "/path/to/dir" # URL ssh://[user@]host.xz[:port]/path - url = "ssh://{}@{}:{}{}".format(user, host, port, path) + url = f"ssh://{user}@{host}:{port}{path}" config = {"url": url} remote = SSHRemote(dvc, config) assert remote.path_info == url # SCP-like URL ssh://[user@]host.xz:/absolute/path - url = "ssh://{}@{}:{}".format(user, host, path) + url = f"ssh://{user}@{host}:{path}" config = {"url": url} remote = SSHRemote(dvc, config) @@ -60,7 +60,7 @@ else: ) @patch("os.path.exists", return_value=True) @patch( - "{}.open".format(builtin_module_name), + f"{builtin_module_name}.open", new_callable=mock_open, read_data=mock_ssh_config, ) @@ -90,7 +90,7 @@ def test_ssh_host_override_from_config( ) @patch("os.path.exists", return_value=True) @patch( - "{}.open".format(builtin_module_name), + f"{builtin_module_name}.open", new_callable=mock_open, read_data=mock_ssh_config, ) @@ -115,7 +115,7 @@ def test_ssh_user(mock_file, mock_exists, dvc, config, expected_user): ) @patch("os.path.exists", return_value=True) @patch( - "{}.open".format(builtin_module_name), + f"{builtin_module_name}.open", new_callable=mock_open, read_data=mock_ssh_config, ) @@ -150,7 +150,7 @@ def test_ssh_port(mock_file, mock_exists, dvc, config, expected_port): ) @patch("os.path.exists", return_value=True) @patch( - "{}.open".format(builtin_module_name), + f"{builtin_module_name}.open", new_callable=mock_open, read_data=mock_ssh_config, ) @@ -172,7 +172,7 @@ def test_ssh_keyfile(mock_file, mock_exists, dvc, config, expected_keyfile): ) @patch("os.path.exists", return_value=True) @patch( - "{}.open".format(builtin_module_name), + f"{builtin_module_name}.open", new_callable=mock_open, read_data=mock_ssh_config, ) diff --git a/tests/unit/remote/test_azure.py b/tests/unit/remote/test_azure.py index e404b2e6e..b3fa97948 100644 --- a/tests/unit/remote/test_azure.py +++ b/tests/unit/remote/test_azure.py @@ -23,7 +23,7 @@ def test_init_compat(dvc): def test_init(dvc): prefix = "some/prefix" - url = "azure://{}/{}".format(container_name, prefix) + url = f"azure://{container_name}/{prefix}" config = {"url": url, "connection_string": connection_string} remote = AzureRemote(dvc, config) assert remote.path_info == url diff --git a/tests/unit/remote/test_base.py b/tests/unit/remote/test_base.py index a5c89f018..1e07589df 100644 --- a/tests/unit/remote/test_base.py +++ b/tests/unit/remote/test_base.py @@ -7,7 +7,7 @@ from dvc.path_info import PathInfo from dvc.remote.base import BaseRemote, RemoteCmdError, RemoteMissingDepsError -class _CallableOrNone(object): +class _CallableOrNone: """Helper for testing if object is callable() or None.""" def __eq__(self, other): @@ -111,11 +111,11 @@ def test_cache_checksums_traverse(path_to_checksum, cache_checksums, dvc): list(remote._cache_checksums_traverse(size, {0})) for i in range(1, 16): cache_checksums.assert_any_call( - prefix="{:03x}".format(i), progress_callback=CallableOrNone + prefix=f"{i:03x}", progress_callback=CallableOrNone ) for i in range(1, 256): cache_checksums.assert_any_call( - prefix="{:02x}".format(i), progress_callback=CallableOrNone + prefix=f"{i:02x}", progress_callback=CallableOrNone ) # default traverse (small remote) diff --git a/tests/unit/remote/test_gdrive.py b/tests/unit/remote/test_gdrive.py index be2fb0150..aeda479c1 100644 --- a/tests/unit/remote/test_gdrive.py +++ b/tests/unit/remote/test_gdrive.py @@ -9,7 +9,7 @@ USER_CREDS_TOKEN_REFRESH_ERROR = '{"access_token": "", "client_id": "", "client_ USER_CREDS_MISSED_KEY_ERROR = "{}" -class TestRemoteGDrive(object): +class TestRemoteGDrive: CONFIG = { "url": "gdrive://root/data", "gdrive_client_id": "client", diff --git a/tests/unit/remote/test_gs.py b/tests/unit/remote/test_gs.py index 34ea34734..3f8643011 100644 --- a/tests/unit/remote/test_gs.py +++ b/tests/unit/remote/test_gs.py @@ -6,7 +6,7 @@ from dvc.remote.gs import GSRemote, dynamic_chunk_size BUCKET = "bucket" PREFIX = "prefix" -URL = "gs://{}/{}".format(BUCKET, PREFIX) +URL = f"gs://{BUCKET}/{PREFIX}" CREDENTIALPATH = "/path/to/gcp_credentials.json" PROJECT = "PROJECT" CONFIG = { diff --git a/tests/unit/remote/test_http.py b/tests/unit/remote/test_http.py index 48449f1a7..06998f22f 100644 --- a/tests/unit/remote/test_http.py +++ b/tests/unit/remote/test_http.py @@ -8,7 +8,7 @@ from tests.utils.httpd import StaticFileServer def test_download_fails_on_error_code(dvc): with StaticFileServer() as httpd: - url = "http://localhost:{}/".format(httpd.server_port) + url = f"http://localhost:{httpd.server_port}/" config = {"url": url} remote = HTTPRemote(dvc, config) diff --git a/tests/unit/remote/test_oss.py b/tests/unit/remote/test_oss.py index 6cd8d0b8a..d6bd51539 100644 --- a/tests/unit/remote/test_oss.py +++ b/tests/unit/remote/test_oss.py @@ -8,7 +8,7 @@ key_secret = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsu" def test_init(dvc): prefix = "some/prefix" - url = "oss://{}/{}".format(bucket_name, prefix) + url = f"oss://{bucket_name}/{prefix}" config = { "url": url, "oss_key_id": key_id, diff --git a/tests/unit/remote/test_remote.py b/tests/unit/remote/test_remote.py index d4f512a1b..58dd29636 100644 --- a/tests/unit/remote/test_remote.py +++ b/tests/unit/remote/test_remote.py @@ -31,7 +31,7 @@ def test_remote_without_checksum_jobs_default(dvc): @pytest.mark.parametrize("remote_cls", [GSRemote, S3Remote]) def test_makedirs_not_create_for_top_level_path(remote_cls, dvc, mocker): - url = "{.scheme}://bucket/".format(remote_cls) + url = f"{remote_cls.scheme}://bucket/" remote = remote_cls(dvc, {"url": url}) mocked_client = mocker.PropertyMock() # we use remote clients with same name as scheme to interact with remote diff --git a/tests/unit/remote/test_remote_dir.py b/tests/unit/remote/test_remote_dir.py index 22b4918b4..9a0f60d4d 100644 --- a/tests/unit/remote/test_remote_dir.py +++ b/tests/unit/remote/test_remote_dir.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import pytest diff --git a/tests/unit/remote/test_s3.py b/tests/unit/remote/test_s3.py index b9ee1ebd3..bf726db61 100644 --- a/tests/unit/remote/test_s3.py +++ b/tests/unit/remote/test_s3.py @@ -5,7 +5,7 @@ from dvc.remote.s3 import S3Remote bucket_name = "bucket-name" prefix = "some/prefix" -url = "s3://{}/{}".format(bucket_name, prefix) +url = f"s3://{bucket_name}/{prefix}" @pytest.fixture(autouse=True) diff --git a/tests/unit/test_updater.py b/tests/unit/test_updater.py index 6ddc1db46..2b9926037 100644 --- a/tests/unit/test_updater.py +++ b/tests/unit/test_updater.py @@ -25,7 +25,7 @@ def test_fetch(mock_get, updater): mock_get.assert_called_once_with(Updater.URL, timeout=Updater.TIMEOUT_GET) assert os.path.isfile(updater.updater_file) - with open(updater.updater_file, "r") as fobj: + with open(updater.updater_file) as fobj: info = json.load(fobj) assert info["version"] == __version__ diff --git a/tests/unit/utils/test_http.py b/tests/unit/utils/test_http.py index 37618be67..cb45e298a 100644 --- a/tests/unit/utils/test_http.py +++ b/tests/unit/utils/test_http.py @@ -29,7 +29,7 @@ def test_open_url(tmp_path, monkeypatch): (tmp_path / "sample.txt").write_text(text * 2) with StaticFileServer() as httpd: - url = "http://localhost:{}/sample.txt".format(httpd.server_port) + url = f"http://localhost:{httpd.server_port}/sample.txt" with open_url(url) as fd: # Test various .read() variants assert fd.read(len(text)) == text diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py index 9e5448abb..060315e95 100644 --- a/tests/utils/__init__.py +++ b/tests/utils/__init__.py @@ -6,7 +6,7 @@ from dvc.scm import Git def get_gitignore_content(): - with open(Git.GITIGNORE, "r") as gitignore: + with open(Git.GITIGNORE) as gitignore: return gitignore.read().splitlines() diff --git a/tests/utils/httpd.py b/tests/utils/httpd.py index d89070b78..d70675280 100644 --- a/tests/utils/httpd.py +++ b/tests/utils/httpd.py @@ -21,7 +21,7 @@ class TestRequestHandler(RangeRequestHandler): file = self.translate_path(self.path) if not os.path.isdir(file) and os.path.exists(file): - with open(file, "r") as fd: + with open(file) as fd: encoded_text = fd.read().encode("utf8") checksum = hashlib.md5(encoded_text).hexdigest() self.send_header(self.checksum_header, checksum)