diff --git a/dvc/analytics.py b/dvc/analytics.py index a8969b2ef..d843d04fa 100644 --- a/dvc/analytics.py +++ b/dvc/analytics.py @@ -17,7 +17,7 @@ from dvc.lock import Lock, LockError from dvc.repo import Repo from dvc.scm import SCM from dvc.utils import env2bool, is_binary, makedirs -from dvc.utils.compat import str, FileNotFoundError +from dvc.utils.compat import FileNotFoundError logger = logging.getLogger(__name__) diff --git a/dvc/api.py b/dvc/api.py index 45c20c0c1..447cf60cd 100644 --- a/dvc/api.py +++ b/dvc/api.py @@ -9,7 +9,7 @@ try: except ImportError: from contextlib import GeneratorContextManager as GCM -from dvc.utils.compat import urlparse, builtin_str +from dvc.utils.compat import urlparse import ruamel.yaml from voluptuous import Schema, Required, Invalid @@ -188,8 +188,6 @@ def _import_string(import_name): :return: imported object """ - import_name = builtin_str(import_name) - if "." in import_name: module, obj = import_name.rsplit(".", 1) else: diff --git a/dvc/cache.py b/dvc/cache.py index b29004457..cfdc6113c 100644 --- a/dvc/cache.py +++ b/dvc/cache.py @@ -5,7 +5,6 @@ from collections import defaultdict from funcy import cached_property from dvc.config import Config -from dvc.utils.compat import builtin_str class CacheConfig(object): @@ -54,7 +53,7 @@ def _make_remote_property(name): return Remote(self.repo, name=remote) - getter.__name__ = builtin_str(name) + getter.__name__ = str(name) return cached_property(getter) diff --git a/dvc/command/pipeline.py b/dvc/command/pipeline.py index 08fa9bd4d..cbec6abf3 100644 --- a/dvc/command/pipeline.py +++ b/dvc/command/pipeline.py @@ -1,6 +1,5 @@ import argparse import logging -from dvc.utils.compat import str from dvc.command.base import CmdBase, append_doc_link, fix_subparsers from dvc.exceptions import DvcException @@ -102,7 +101,7 @@ class CmdPipelineShow(CmdBase): tree.show() def __write_dot(self, target, commands, outs): - from dvc.utils.compat import StringIO + import io import networkx from networkx.drawing.nx_pydot import write_dot @@ -112,7 +111,7 @@ class CmdPipelineShow(CmdBase): simple_g = networkx.DiGraph() simple_g.add_edges_from(edges) - dot_file = StringIO() + dot_file = io.StringIO() write_dot(simple_g, dot_file) logger.info(dot_file.getvalue()) diff --git a/dvc/command/status.py b/dvc/command/status.py index 3774192c0..640294860 100644 --- a/dvc/command/status.py +++ b/dvc/command/status.py @@ -1,7 +1,6 @@ import logging from dvc.command.data_sync import CmdDataBase -from dvc.utils.compat import str logger = logging.getLogger(__name__) diff --git a/dvc/config.py b/dvc/config.py index c90ed7549..e9fc0d598 100644 --- a/dvc/config.py +++ b/dvc/config.py @@ -12,7 +12,7 @@ from voluptuous import All, Any, Lower, Range, Coerce, Match from dvc.exceptions import DvcException from dvc.exceptions import NotDvcRepoError -from dvc.utils.compat import open, str +from dvc.utils.compat import open logger = logging.getLogger(__name__) diff --git a/dvc/dependency/repo.py b/dvc/dependency/repo.py index e008f540b..0963e1061 100644 --- a/dvc/dependency/repo.py +++ b/dvc/dependency/repo.py @@ -7,7 +7,6 @@ from funcy import merge from .local import DependencyLOCAL from dvc.external_repo import external_repo -from dvc.utils.compat import str from dvc.exceptions import OutputNotFoundError from dvc.exceptions import PathMissingError from dvc.utils.fs import fs_copy diff --git a/dvc/exceptions.py b/dvc/exceptions.py index 7fb9ddc6c..bcfeb4789 100644 --- a/dvc/exceptions.py +++ b/dvc/exceptions.py @@ -3,8 +3,6 @@ import traceback from dvc.utils import relpath -from dvc.utils.compat import builtin_str -from dvc.utils.compat import str class DvcException(Exception): @@ -38,7 +36,7 @@ class OutputDuplicationError(DvcException): """ def __init__(self, output, stages): - assert isinstance(output, (str, builtin_str)) + assert isinstance(output, str) assert all(hasattr(stage, "relpath") for stage in stages) msg = ( "file/directory '{}' is specified as an output in more than one " @@ -75,7 +73,7 @@ class StagePathAsOutputError(DvcException): """ def __init__(self, stage, output): - assert isinstance(output, (str, builtin_str)) + assert isinstance(output, str) super(StagePathAsOutputError, self).__init__( "'{stage}' is within an output '{output}' of another stage".format( stage=stage.relpath, output=output @@ -92,7 +90,7 @@ class CircularDependencyError(DvcException): """ def __init__(self, dependency): - assert isinstance(dependency, (str, builtin_str)) + assert isinstance(dependency, str) msg = ( "file/directory '{}' is specified as an output and as a " @@ -110,7 +108,7 @@ class ArgumentDuplicationError(DvcException): """ def __init__(self, path): - assert isinstance(path, (str, builtin_str)) + assert isinstance(path, str) msg = "file '{}' is specified more than once." super(ArgumentDuplicationError, self).__init__(msg.format(path)) diff --git a/dvc/logger.py b/dvc/logger.py index b4b0d9c07..3f93f5640 100644 --- a/dvc/logger.py +++ b/dvc/logger.py @@ -1,5 +1,6 @@ """Manages logging configuration for dvc repo.""" +import io import logging.config import logging.handlers @@ -7,8 +8,6 @@ import colorama from dvc.progress import Tqdm from dvc.utils.compat import RecursionError -from dvc.utils.compat import str -from dvc.utils.compat import StringIO FOOTER = ( @@ -105,7 +104,7 @@ class ColorFormatter(logging.Formatter): def _walk_exc(self, exc_info): import traceback - buffer = StringIO() + buffer = io.StringIO() traceback.print_exception(*exc_info, file=buffer) diff --git a/dvc/output/__init__.py b/dvc/output/__init__.py index cbddb5b37..075b623f9 100644 --- a/dvc/output/__init__.py +++ b/dvc/output/__init__.py @@ -11,7 +11,6 @@ from dvc.remote.hdfs import RemoteHDFS from dvc.remote.local import RemoteLOCAL from dvc.remote.s3 import RemoteS3 from dvc.scheme import Schemes -from dvc.utils.compat import str from dvc.utils.compat import urlparse OUTS = [ diff --git a/dvc/output/base.py b/dvc/output/base.py index 53c4d2cb3..8c7d99b7c 100644 --- a/dvc/output/base.py +++ b/dvc/output/base.py @@ -8,7 +8,6 @@ from dvc.cache import NamedCache from dvc.exceptions import CollectCacheError from dvc.exceptions import DvcException from dvc.remote.base import RemoteBASE -from dvc.utils.compat import str from dvc.utils.compat import urlparse diff --git a/dvc/output/local.py b/dvc/output/local.py index 718e752c5..8e1de6df2 100644 --- a/dvc/output/local.py +++ b/dvc/output/local.py @@ -7,7 +7,6 @@ from dvc.output.base import OutputBase from dvc.remote.local import RemoteLOCAL from dvc.utils import relpath from dvc.utils.compat import fspath_py35 -from dvc.utils.compat import str from dvc.utils.compat import urlparse from dvc.utils.fs import path_isin diff --git a/dvc/path_info.py b/dvc/path_info.py index f521b7d6c..0e2245cf2 100644 --- a/dvc/path_info.py +++ b/dvc/path_info.py @@ -4,16 +4,13 @@ import posixpath from funcy import cached_property from dvc.utils import relpath -from dvc.utils.compat import basestring -from dvc.utils.compat import builtin_str from dvc.utils.compat import pathlib -from dvc.utils.compat import str from dvc.utils.compat import urlparse class _BasePath(object): def overlaps(self, other): - if isinstance(other, basestring): + if isinstance(other, (str, bytes)): other = self.__class__(other) elif self.__class__ != other.__class__: return False @@ -54,7 +51,7 @@ class PathInfo(pathlib.PurePath, _BasePath): return relpath(path) def __repr__(self): - return builtin_str("{}: '{}'").format(type(self).__name__, self) + return str("{}: '{}'").format(type(self).__name__, self) # This permits passing it to file utils directly in Python 3.6+ # With Python 2.7, Python 3.5+ we are stuck with path_info.fspath for now @@ -71,7 +68,7 @@ class PathInfo(pathlib.PurePath, _BasePath): return self.__class__(relpath(self, other)) def isin(self, other): - if isinstance(other, basestring): + if isinstance(other, (str, bytes)): other = self.__class__(other) elif self.__class__ != other.__class__: return False @@ -135,13 +132,13 @@ class URLInfo(_BasePath): def fill_parts(self, scheme, host, user, port, path): assert scheme != "remote" - assert isinstance(path, (basestring, _URLPathInfo)) + assert isinstance(path, (str, bytes, _URLPathInfo)) self.scheme, self.host, self.user = scheme, host, user self.port = int(port) if port else self.DEFAULT_PORTS.get(self.scheme) if isinstance(path, _URLPathInfo): - self._spath = builtin_str(path) + self._spath = str(path) self._path = path else: if path and path[0] != "/": @@ -170,7 +167,7 @@ class URLInfo(_BasePath): return "{}: '{}'".format(type(self).__name__, self) def __eq__(self, other): - if isinstance(other, basestring): + if isinstance(other, (str, bytes)): other = self.__class__(other) return ( self.__class__ == other.__class__ @@ -220,7 +217,7 @@ class URLInfo(_BasePath): return _URLPathParents(self) def relative_to(self, other): - if isinstance(other, basestring): + if isinstance(other, (str, bytes)): other = self.__class__(other) if self.__class__ != other.__class__: msg = "'{}' has incompatible class with '{}'".format(self, other) @@ -231,7 +228,7 @@ class URLInfo(_BasePath): return self._path.relative_to(other._path) def isin(self, other): - if isinstance(other, basestring): + if isinstance(other, (str, bytes)): other = self.__class__(other) elif self.__class__ != other.__class__: return False diff --git a/dvc/remote/base.py b/dvc/remote/base.py index b33021530..b215a5586 100644 --- a/dvc/remote/base.py +++ b/dvc/remote/base.py @@ -1,6 +1,6 @@ import errno -from dvc.utils.compat import basestring, FileNotFoundError, str, urlparse +from dvc.utils.compat import FileNotFoundError, urlparse import itertools import json @@ -153,7 +153,7 @@ class RemoteBASE(object): @classmethod def supported(cls, config): - if isinstance(config, basestring): + if isinstance(config, (str, bytes)): url = config else: url = config[Config.SECTION_REMOTE_URL] diff --git a/dvc/remote/local.py b/dvc/remote/local.py index bb2be9356..a25a986b5 100644 --- a/dvc/remote/local.py +++ b/dvc/remote/local.py @@ -30,7 +30,6 @@ from dvc.utils import tmp_fname from dvc.utils import walk_files from dvc.utils.compat import fspath_py35 from dvc.utils.compat import open -from dvc.utils.compat import str from dvc.utils.fs import move from dvc.utils.fs import remove @@ -411,7 +410,7 @@ class RemoteLOCAL(RemoteBASE): def _unprotect_file(path): if System.is_symlink(path) or System.is_hardlink(path): logger.debug("Unprotecting '{}'".format(path)) - tmp = os.path.join(os.path.dirname(path), "." + str(uuid())) + tmp = os.path.join(os.path.dirname(path), "." + uuid()) # The operations order is important here - if some application # would access the file during the process of copyfile then it diff --git a/dvc/remote/ssh/__init__.py b/dvc/remote/ssh/__init__.py index 710525710..37dde23da 100644 --- a/dvc/remote/ssh/__init__.py +++ b/dvc/remote/ssh/__init__.py @@ -17,7 +17,6 @@ from dvc.remote.base import RemoteBASE from dvc.remote.pool import get_connection from dvc.scheme import Schemes from dvc.utils import to_chunks -from dvc.utils.compat import StringIO from dvc.utils.compat import urlparse logger = logging.getLogger(__name__) @@ -104,7 +103,7 @@ class RemoteSSH(RemoteBASE): ssh_config = paramiko.SSHConfig() with open(user_config_file) as f: # For whatever reason parsing directly from f is unreliable - f_copy = StringIO(f.read()) + f_copy = io.StringIO(f.read()) ssh_config.parse(f_copy) user_ssh_config = ssh_config.lookup(hostname) return user_ssh_config diff --git a/dvc/repo/metrics/show.py b/dvc/repo/metrics/show.py index f9e9a36bc..177e7b546 100644 --- a/dvc/repo/metrics/show.py +++ b/dvc/repo/metrics/show.py @@ -3,16 +3,15 @@ import errno import json import logging import os +import io from jsonpath_ng.ext import parse from dvc.exceptions import NoMetricsError from dvc.exceptions import OutputNotFoundError from dvc.repo import locked -from dvc.utils.compat import builtin_str from dvc.utils.compat import csv_reader from dvc.utils.compat import open -from dvc.utils.compat import StringIO NO_METRICS_FILE_AT_REFERENCE_WARNING = ( "Metrics file '{}' does not exist at the reference '{}'." @@ -48,7 +47,7 @@ def _read_metric_hxsv(fd, hxsv_path, delimiter): row = indices[0] row = int(row) if row else None col = indices[1] if len(indices) > 1 and indices[1] else None - reader = list(csv.DictReader(fd, delimiter=builtin_str(delimiter))) + reader = list(csv.DictReader(fd, delimiter=delimiter)) return _do_read_metric_xsv(reader, row, col) @@ -57,7 +56,7 @@ def _read_metric_xsv(fd, xsv_path, delimiter): row = indices[0] row = int(row) if row else None col = int(indices[1]) if len(indices) > 1 and indices[1] else None - reader = list(csv.reader(fd, delimiter=builtin_str(delimiter))) + reader = list(csv.reader(fd, delimiter=delimiter)) return _do_read_metric_xsv(reader, row, col) @@ -102,7 +101,7 @@ def _format_csv(content, delimiter): "0.67528 0.289545 testing\n" "0.671502 0.297848 validation\n" """ - reader = csv_reader(StringIO(content), delimiter=builtin_str(delimiter)) + reader = csv_reader(io.StringIO(content), delimiter=delimiter) rows = [row for row in reader] max_widths = [max(map(len, column)) for column in zip(*rows)] @@ -128,10 +127,10 @@ def _format_output(content, typ): str: Content in a raw or tabular format. """ - if "csv" in str(typ): + if "csv" in typ: return _format_csv(content, delimiter=",") - if "tsv" in str(typ): + if "tsv" in typ: return _format_csv(content, delimiter="\t") return content diff --git a/dvc/scm/git/__init__.py b/dvc/scm/git/__init__.py index a61c1ee37..2ccb418bf 100644 --- a/dvc/scm/git/__init__.py +++ b/dvc/scm/git/__init__.py @@ -19,7 +19,6 @@ from dvc.utils import relpath from dvc.utils.fs import path_isin from dvc.utils.compat import cast_bytes_py2 from dvc.utils.compat import open -from dvc.utils.compat import str logger = logging.getLogger(__name__) diff --git a/dvc/scm/git/tree.py b/dvc/scm/git/tree.py index d775a5433..c7d2ff26f 100644 --- a/dvc/scm/git/tree.py +++ b/dvc/scm/git/tree.py @@ -1,11 +1,10 @@ +import io import errno import os from dvc.exceptions import DvcException from dvc.scm.tree import BaseTree from dvc.utils import relpath -from dvc.utils.compat import BytesIO -from dvc.utils.compat import StringIO # see git-fast-import(1) @@ -63,8 +62,8 @@ class GitTree(BaseTree): # and `open` with default "r" mode returns str) data = obj.data_stream.read() if mode == "rb": - return BytesIO(data) - return StringIO(data.decode(encoding)) + return io.BytesIO(data) + return io.StringIO(data.decode(encoding)) def exists(self, path): return self.git_object_by_path(path) is not None diff --git a/dvc/stage.py b/dvc/stage.py index d89699d4e..79127e261 100644 --- a/dvc/stage.py +++ b/dvc/stage.py @@ -1,4 +1,4 @@ -from dvc.utils.compat import pathlib, str +from dvc.utils.compat import pathlib import logging import os import re diff --git a/dvc/system.py b/dvc/system.py index 3723094b7..5010508c8 100644 --- a/dvc/system.py +++ b/dvc/system.py @@ -5,7 +5,6 @@ import shutil from dvc.utils.compat import fspath from dvc.utils.compat import open -from dvc.utils.compat import str logger = logging.getLogger(__name__) diff --git a/dvc/utils/__init__.py b/dvc/utils/__init__.py index b157adc53..3712c796c 100644 --- a/dvc/utils/__init__.py +++ b/dvc/utils/__init__.py @@ -8,20 +8,18 @@ import os import re import sys import time +import io import colorama import nanotime from ruamel.yaml import YAML from shortuuid import uuid -from dvc.utils.compat import builtin_str from dvc.utils.compat import cast_bytes_py2 from dvc.utils.compat import fspath from dvc.utils.compat import fspath_py35 from dvc.utils.compat import makedirs as _makedirs from dvc.utils.compat import open -from dvc.utils.compat import str -from dvc.utils.compat import StringIO logger = logging.getLogger(__name__) @@ -92,16 +90,14 @@ def dict_filter(d, exclude=()): Exclude specified keys from a nested dict """ - def fix_key(k): - return str(k) if isinstance(k, builtin_str) else k - if isinstance(d, list): return [dict_filter(e, exclude) for e in d] if isinstance(d, dict): - items = ((fix_key(k), v) for k, v in d.items()) return { - k: dict_filter(v, exclude) for k, v in items if k not in exclude + k: dict_filter(v, exclude) + for k, v in d.items() + if k not in exclude } return d @@ -268,7 +264,7 @@ def fix_env(env=None): def tmp_fname(fname): """ Temporary name for a partial download """ - return fspath(fname) + "." + str(uuid()) + ".tmp" + return fspath(fname) + "." + uuid() + ".tmp" def current_timestamp(): @@ -276,11 +272,11 @@ def current_timestamp(): def from_yaml_string(s): - return YAML().load(StringIO(s)) + return YAML().load(io.StringIO(s)) def to_yaml_string(data): - stream = StringIO() + stream = io.StringIO() yaml = YAML() yaml.default_flow_style = False yaml.dump(data, stream) diff --git a/dvc/utils/fs.py b/dvc/utils/fs.py index dd27e031e..d116924b2 100644 --- a/dvc/utils/fs.py +++ b/dvc/utils/fs.py @@ -13,7 +13,6 @@ from dvc.utils import dict_md5 from dvc.utils import fspath from dvc.utils import fspath_py35 from dvc.utils import relpath -from dvc.utils.compat import str logger = logging.getLogger(__name__) @@ -101,7 +100,7 @@ def move(src, dst, mode=None): dst = fspath_py35(dst) dst = os.path.abspath(dst) - tmp = "{}.{}".format(dst, str(uuid())) + tmp = "{}.{}".format(dst, uuid()) if os.path.islink(src): shutil.copy(os.readlink(src), tmp) diff --git a/tests/basic_env.py b/tests/basic_env.py index 380524f92..8d1f5ce2c 100644 --- a/tests/basic_env.py +++ b/tests/basic_env.py @@ -13,7 +13,6 @@ from git.exc import GitCommandNotFound from dvc.repo import Repo as DvcRepo from dvc.utils.compat import open -from dvc.utils.compat import str from dvc.utils.fs import remove diff --git a/tests/dir_helpers.py b/tests/dir_helpers.py index 682062871..256581ce2 100644 --- a/tests/dir_helpers.py +++ b/tests/dir_helpers.py @@ -49,7 +49,7 @@ import pytest from funcy.py3 import lmap, retry from dvc.utils import makedirs -from dvc.utils.compat import basestring, pathlib, fspath, fspath_py35, bytes +from dvc.utils.compat import pathlib, fspath, fspath_py35 __all__ = ["tmp_dir", "scm", "dvc", "repo_template", "run_copy", "erepo_dir"] @@ -87,7 +87,7 @@ class TmpDir(pathlib.Path): ) def gen(self, struct, text=""): - if isinstance(struct, (basestring, pathlib.PurePath)): + if isinstance(struct, (str, bytes, pathlib.PurePath)): struct = {struct: text} self._gen(struct) @@ -142,7 +142,7 @@ class TmpDir(pathlib.Path): def _coerce_filenames(filenames): - if isinstance(filenames, (basestring, pathlib.PurePath)): + if isinstance(filenames, (str, bytes, pathlib.PurePath)): filenames = [filenames] return lmap(fspath, filenames) diff --git a/tests/func/test_data_cloud.py b/tests/func/test_data_cloud.py index 0d5673466..2de59d2e7 100644 --- a/tests/func/test_data_cloud.py +++ b/tests/func/test_data_cloud.py @@ -25,7 +25,6 @@ from dvc.remote.base import STATUS_DELETED from dvc.remote.base import STATUS_NEW from dvc.remote.base import STATUS_OK from dvc.utils import file_md5 -from dvc.utils.compat import str from dvc.utils.stage import dump_stage_file from dvc.utils.stage import load_stage_file from tests.basic_env import TestDvc diff --git a/tests/func/test_import_url.py b/tests/func/test_import_url.py index 9522639c4..855484371 100644 --- a/tests/func/test_import_url.py +++ b/tests/func/test_import_url.py @@ -8,7 +8,6 @@ from mock import patch import dvc from dvc.main import main from dvc.utils import makedirs -from dvc.utils.compat import str from tests.basic_env import TestDvc from tests.utils import spy diff --git a/tests/func/test_repro.py b/tests/func/test_repro.py index 00ea003aa..42885acbd 100644 --- a/tests/func/test_repro.py +++ b/tests/func/test_repro.py @@ -29,7 +29,6 @@ from dvc.system import System from dvc.utils import file_md5 from dvc.utils import relpath from dvc.utils.compat import pathlib -from dvc.utils.compat import str from dvc.utils.compat import urljoin from dvc.utils.stage import dump_stage_file from dvc.utils.stage import load_stage_file diff --git a/tests/func/test_scm.py b/tests/func/test_scm.py index 23eea236b..83912559a 100644 --- a/tests/func/test_scm.py +++ b/tests/func/test_scm.py @@ -6,7 +6,6 @@ from dvc.scm import Git from dvc.scm import NoSCM from dvc.scm import SCM from dvc.system import System -from dvc.utils.compat import str # noqa: F401 from tests.basic_env import TestDir from tests.basic_env import TestGit from tests.basic_env import TestGitSubmodule diff --git a/tests/func/test_state.py b/tests/func/test_state.py index d0c6d1c3f..31610e08a 100644 --- a/tests/func/test_state.py +++ b/tests/func/test_state.py @@ -6,7 +6,6 @@ from dvc.main import main from dvc.path_info import PathInfo from dvc.state import State from dvc.utils import file_md5 -from dvc.utils.compat import str def test_state(dvc_repo, repo_dir): diff --git a/tests/unit/test_analytics.py b/tests/unit/test_analytics.py index 43eb37dcb..59cd19628 100644 --- a/tests/unit/test_analytics.py +++ b/tests/unit/test_analytics.py @@ -7,10 +7,6 @@ from voluptuous import Schema, Any from dvc import analytics from dvc.cli import parse_args -from dvc.utils.compat import str, builtin_str - - -string = Any(str, builtin_str) @pytest.fixture @@ -51,10 +47,10 @@ def test_collect_and_send_report(mock_json, mock_daemon, tmp_global_config): def test_runtime_info(tmp_global_config): schema = Schema( { - "dvc_version": string, + "dvc_version": str, "is_binary": bool, "scm_class": Any("Git", None), - "user_id": string, + "user_id": str, "system_info": dict, }, required=True, @@ -109,19 +105,19 @@ def test_system_info(): "windows_version_build": int, "windows_version_major": int, "windows_version_minor": int, - "windows_version_service_pack": string, + "windows_version_service_pack": str, } ) if system == "Darwin": - schema = schema.extend({"mac_version": string}) + schema = schema.extend({"mac_version": str}) if system == "Linux": schema = schema.extend( { - "linux_distro": string, - "linux_distro_like": string, - "linux_distro_version": string, + "linux_distro": str, + "linux_distro_like": str, + "linux_distro_version": str, } ) diff --git a/tests/unit/utils/test_fs.py b/tests/unit/utils/test_fs.py index bc1547629..2c11d287c 100644 --- a/tests/unit/utils/test_fs.py +++ b/tests/unit/utils/test_fs.py @@ -10,7 +10,6 @@ from dvc.path_info import PathInfo from dvc.scm.tree import WorkingTree from dvc.system import System from dvc.utils import relpath -from dvc.utils.compat import str from dvc.utils.fs import BasePathNotInCheckedPathException from dvc.utils.fs import contains_symlink_up_to from dvc.utils.fs import get_inode