dvc: separate data and objects

Initial simple separation to get the process of extracting dvc-objects
and dvc-data packages out of dvc.

dvc-objects is for:
 * defining base Object (aka HashFile) and ObjectDB
 * providing tools to work with those objects (check/transfer/etc)
 * etc

dvc-data is for:
 * defining higher level objects (e.g. Tree)
 * bulding objects from the workspace (aka staging)
 * projecting objects back into the workspace (aka checkout)
 * comparing Tree objects (aka diff)
 * defining misc object databases (e.g LocalObjectDB)
 * higher-level transfer (e.g. with Tree indexes)
 * etc

For example, the objects we use in run-cache are based on dvc-objects
and not on dvc-data, as they have absolutely nothing to do with data
management.

There are still some mixups in the code that will be addressed in the
followups.
This commit is contained in:
Ruslan Kuprieiev
2022-01-11 00:47:38 +02:00
parent 92f714e5ca
commit f64018b75e
52 changed files with 124 additions and 126 deletions
@@ -5,9 +5,8 @@ from .tree import Tree
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.db import ObjectDB
from .db.base import ObjectDB from dvc.objects.file import HashFile
from .file import HashFile
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -5,14 +5,13 @@ from dvc import prompt
from dvc.exceptions import CacheLinkError, CheckoutError, ConfirmRemoveError from dvc.exceptions import CacheLinkError, CheckoutError, ConfirmRemoveError
from dvc.fs.utils import test_links, transfer from dvc.fs.utils import test_links, transfer
from dvc.ignore import DvcIgnoreFilter from dvc.ignore import DvcIgnoreFilter
from dvc.objects.db.slow_link_detection import ( # type: ignore[attr-defined]
slow_link_guard,
)
from dvc.objects.diff import ROOT
from dvc.objects.diff import diff as odiff
from dvc.objects.stage import stage
from dvc.types import Optional from dvc.types import Optional
from .diff import ROOT
from .diff import diff as odiff
from .slow_link_detection import slow_link_guard # type: ignore[attr-defined]
from .stage import stage
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -7,7 +7,8 @@ if TYPE_CHECKING:
def get_odb(fs, fs_path, **config): def get_odb(fs, fs_path, **config):
from .base import ObjectDB from dvc.objects.db import ObjectDB
from .local import LocalObjectDB from .local import LocalObjectDB
if fs.scheme == Schemes.LOCAL: if fs.scheme == Schemes.LOCAL:
@@ -3,7 +3,7 @@ import os
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Iterable, Set from typing import TYPE_CHECKING, Iterable, Set
from ..errors import ObjectDBError from dvc.objects.errors import ObjectDBError
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.types import StrPath from dvc.types import StrPath
@@ -6,13 +6,12 @@ from funcy import cached_property
from shortuuid import uuid from shortuuid import uuid
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.db import ObjectDB
from dvc.objects.errors import ObjectFormatError from dvc.objects.errors import ObjectFormatError
from dvc.progress import Tqdm from dvc.progress import Tqdm
from dvc.utils import relpath from dvc.utils import relpath
from dvc.utils.fs import copyfile, remove, umask, walk_files from dvc.utils.fs import copyfile, remove, umask, walk_files
from .base import ObjectDB
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -3,11 +3,11 @@ import logging
import os import os
from typing import TYPE_CHECKING, Dict from typing import TYPE_CHECKING, Dict
from dvc.objects.db import ObjectDB
from dvc.objects.errors import ObjectFormatError
from dvc.scheme import Schemes from dvc.scheme import Schemes
from ..errors import ObjectFormatError
from ..reference import ReferenceHashFile from ..reference import ReferenceHashFile
from .base import ObjectDB
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.fs.base import FileSystem from dvc.fs.base import FileSystem
+2 -3
View File
@@ -3,8 +3,7 @@ from typing import TYPE_CHECKING, List, Optional, Tuple
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.file import HashFile
from .file import HashFile
ADD = "add" ADD = "add"
MODIFY = "modify" MODIFY = "modify"
@@ -96,7 +95,7 @@ def diff(
return entry_obj.hash_info if entry_obj else None return entry_obj.hash_info if entry_obj else None
def _in_cache(oid, cache): def _in_cache(oid, cache):
from .errors import ObjectFormatError from dvc.objects.errors import ObjectFormatError
if not oid: if not oid:
return False return False
@@ -4,16 +4,15 @@ import os
import pickle import pickle
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from .errors import ObjectFormatError from dvc.objects.errors import ObjectFormatError
from .file import HashFile from dvc.objects.file import HashFile
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.fs.base import FileSystem from dvc.fs.base import FileSystem
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.db import ObjectDB
from dvc.types import AnyPath from dvc.types import AnyPath
from .db.base import ObjectDB
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
+4 -4
View File
@@ -8,19 +8,18 @@ from typing import TYPE_CHECKING, Dict, Optional, Tuple
from dvc.exceptions import DvcIgnoreInCollectedDirError from dvc.exceptions import DvcIgnoreInCollectedDirError
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.ignore import DvcIgnore from dvc.ignore import DvcIgnore
from dvc.objects.file import HashFile
from dvc.progress import Tqdm from dvc.progress import Tqdm
from dvc.utils import file_md5 from dvc.utils import file_md5
from .db.reference import ReferenceObjectDB from .db.reference import ReferenceObjectDB
from .file import HashFile
from .meta import Meta from .meta import Meta
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.fs.base import FileSystem from dvc.fs.base import FileSystem
from dvc.objects.db import ObjectDB
from dvc.types import AnyPath from dvc.types import AnyPath
from .db.base import ObjectDB
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -245,8 +244,9 @@ def _get_staging(odb: "ObjectDB") -> "ObjectDB":
def _load_from_state(odb, staging, fs_path, fs, name): def _load_from_state(odb, staging, fs_path, fs, name):
from dvc.objects.errors import ObjectFormatError
from . import check, load from . import check, load
from .errors import ObjectFormatError
from .tree import Tree from .tree import Tree
state = odb.state state = odb.state
+3 -2
View File
@@ -7,9 +7,10 @@ from dvc.scheme import Schemes
from .tree import Tree from .tree import Tree
if TYPE_CHECKING: if TYPE_CHECKING:
from .db.base import ObjectDB from dvc.objects.db import ObjectDB
from dvc.objects.file import HashFile
from .db.index import ObjectDBIndexBase from .db.index import ObjectDBIndexBase
from .file import HashFile
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -10,8 +10,8 @@ from dvc.utils.threadpool import ThreadPoolExecutor
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.db import ObjectDB
from .db.base import ObjectDB
from .db.index import ObjectDBIndexBase from .db.index import ObjectDBIndexBase
from .tree import Tree from .tree import Tree
@@ -40,7 +40,8 @@ def _log_exceptions(func):
def find_tree_by_obj_id( def find_tree_by_obj_id(
odbs: Iterable[Optional["ObjectDB"]], obj_id: "HashInfo" odbs: Iterable[Optional["ObjectDB"]], obj_id: "HashInfo"
) -> Optional["Tree"]: ) -> Optional["Tree"]:
from .errors import ObjectFormatError from dvc.objects.errors import ObjectFormatError
from .tree import Tree from .tree import Tree
for odb in odbs: for odb in odbs:
+3 -2
View File
@@ -5,8 +5,9 @@ from typing import TYPE_CHECKING, Dict, Optional, Tuple
from funcy import cached_property from funcy import cached_property
from .errors import ObjectFormatError from dvc.objects.errors import ObjectFormatError
from .file import HashFile from dvc.objects.file import HashFile
from .stage import get_file_hash from .stage import get_file_hash
if TYPE_CHECKING: if TYPE_CHECKING:
+6 -6
View File
@@ -3,11 +3,11 @@
import logging import logging
from typing import TYPE_CHECKING, Iterable, Optional from typing import TYPE_CHECKING, Iterable, Optional
from dvc.objects.db import get_index from dvc.data.db import get_index
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.db.base import ObjectDB from dvc.objects.db import ObjectDB
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -55,8 +55,8 @@ class DataCloud:
raise NoRemoteError(error_msg) raise NoRemoteError(error_msg)
def _init_odb(self, name): def _init_odb(self, name):
from dvc.data.db import get_odb
from dvc.fs import get_cloud_fs from dvc.fs import get_cloud_fs
from dvc.objects.db import get_odb
cls, config, fs_path = get_cloud_fs(self.repo, name=name) cls, config, fs_path = get_cloud_fs(self.repo, name=name)
config["tmp_dir"] = self.repo.index_db_dir config["tmp_dir"] = self.repo.index_db_dir
@@ -78,7 +78,7 @@ class DataCloud:
By default remote from core.remote config option is used. By default remote from core.remote config option is used.
odb: optional ODB to push to. Overrides remote. odb: optional ODB to push to. Overrides remote.
""" """
from dvc.objects.transfer import transfer from dvc.data.transfer import transfer
if not odb: if not odb:
odb = self.get_remote_odb(remote, "push") odb = self.get_remote_odb(remote, "push")
@@ -107,7 +107,7 @@ class DataCloud:
By default remote from core.remote config option is used. By default remote from core.remote config option is used.
odb: optional ODB to pull from. Overrides remote. odb: optional ODB to pull from. Overrides remote.
""" """
from dvc.objects.transfer import transfer from dvc.data.transfer import transfer
if not odb: if not odb:
odb = self.get_remote_odb(remote, "pull") odb = self.get_remote_odb(remote, "pull")
@@ -141,7 +141,7 @@ class DataCloud:
log_missing: log warning messages if file doesn't exist log_missing: log warning messages if file doesn't exist
neither in cache, neither in cloud. neither in cache, neither in cloud.
""" """
from dvc.objects.status import compare_status from dvc.data.status import compare_status
if not odb: if not odb:
odb = self.get_remote_odb(remote, "status") odb = self.get_remote_odb(remote, "status")
+6 -6
View File
@@ -9,7 +9,7 @@ from .base import Dependency
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.db.base import ObjectDB from dvc.objects.db import ObjectDB
from dvc.objects.file import HashFile from dvc.objects.file import HashFile
@@ -61,7 +61,7 @@ class RepoDependency(Dependency):
return {self.PARAM_PATH: self.def_path, self.PARAM_REPO: self.def_repo} return {self.PARAM_PATH: self.def_path, self.PARAM_REPO: self.def_repo}
def download(self, to, jobs=None): def download(self, to, jobs=None):
from dvc.objects.checkout import checkout from dvc.data.checkout import checkout
for odb, objs in self.get_used_objs().items(): for odb, objs in self.get_used_objs().items():
self.repo.cloud.pull(objs, jobs=jobs, odb=odb) self.repo.cloud.pull(objs, jobs=jobs, odb=odb)
@@ -98,9 +98,9 @@ class RepoDependency(Dependency):
self, obj_only=False, **kwargs self, obj_only=False, **kwargs
) -> Tuple[Dict[Optional["ObjectDB"], Set["HashInfo"]], "HashFile"]: ) -> Tuple[Dict[Optional["ObjectDB"], Set["HashInfo"]], "HashFile"]:
from dvc.config import NoRemoteError from dvc.config import NoRemoteError
from dvc.data.stage import stage
from dvc.data.tree import Tree
from dvc.exceptions import NoOutputOrStageError, PathMissingError from dvc.exceptions import NoOutputOrStageError, PathMissingError
from dvc.objects.stage import stage
from dvc.objects.tree import Tree
local_odb = self.repo.odb.local local_odb = self.repo.odb.local
locked = kwargs.pop("locked", True) locked = kwargs.pop("locked", True)
@@ -150,10 +150,10 @@ class RepoDependency(Dependency):
return used_obj_ids, staged_obj return used_obj_ids, staged_obj
def _check_circular_import(self, odb, obj_ids): def _check_circular_import(self, odb, obj_ids):
from dvc.data.db.reference import ReferenceObjectDB
from dvc.data.tree import Tree
from dvc.exceptions import CircularImportError from dvc.exceptions import CircularImportError
from dvc.fs.repo import RepoFileSystem from dvc.fs.repo import RepoFileSystem
from dvc.objects.db.reference import ReferenceObjectDB
from dvc.objects.tree import Tree
if not isinstance(odb, ReferenceObjectDB): if not isinstance(odb, ReferenceObjectDB):
return return
+1 -1
View File
@@ -357,7 +357,7 @@ class ObjectDB:
pass pass
def gc(self, used, jobs=None, cache_odb=None, shallow=True): def gc(self, used, jobs=None, cache_odb=None, shallow=True):
from ..tree import Tree from dvc.data.tree import Tree
if self.read_only: if self.read_only:
raise ObjectDBPermissionError("Cannot gc read-only ODB") raise ObjectDBPermissionError("Cannot gc read-only ODB")
+3 -4
View File
@@ -3,14 +3,12 @@ import logging
import os import os
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from .errors import ObjectFormatError
if TYPE_CHECKING: if TYPE_CHECKING:
from dvc.fs.base import FileSystem from dvc.fs.base import FileSystem
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.types import AnyPath from dvc.types import AnyPath
from .db.base import ObjectDB from .db import ObjectDB
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -68,7 +66,8 @@ class HashFile:
self._check_hash(odb) self._check_hash(odb)
def _check_hash(self, odb): def _check_hash(self, odb):
from .stage import get_file_hash from dvc.data.stage import get_file_hash
from dvc.objects.errors import ObjectFormatError
_, actual = get_file_hash( _, actual = get_file_hash(
self.fs_path, self.fs, self.hash_info.name, odb.state self.fs_path, self.fs, self.hash_info.name, odb.state
+15 -13
View File
@@ -7,7 +7,7 @@ from urllib.parse import urlparse
from funcy import collecting, project from funcy import collecting, project
from voluptuous import And, Any, Coerce, Length, Lower, Required, SetTo from voluptuous import And, Any, Coerce, Length, Lower, Required, SetTo
from dvc import objects, prompt from dvc import prompt
from dvc.exceptions import ( from dvc.exceptions import (
CheckoutError, CheckoutError,
CollectCacheError, CollectCacheError,
@@ -15,25 +15,27 @@ from dvc.exceptions import (
MergeError, MergeError,
RemoteCacheRequiredError, RemoteCacheRequiredError,
) )
from dvc.objects.checkout import checkout
from .data import check as ocheck
from .data import load as oload
from .data.checkout import checkout
from .data.meta import Meta
from .data.stage import stage as ostage
from .data.transfer import transfer as otransfer
from .data.tree import Tree
from .fs import get_cloud_fs from .fs import get_cloud_fs
from .fs.hdfs import HDFSFileSystem from .fs.hdfs import HDFSFileSystem
from .fs.local import LocalFileSystem from .fs.local import LocalFileSystem
from .fs.s3 import S3FileSystem from .fs.s3 import S3FileSystem
from .hash_info import HashInfo from .hash_info import HashInfo
from .istextfile import istextfile from .istextfile import istextfile
from .objects import Tree
from .objects.errors import ObjectFormatError from .objects.errors import ObjectFormatError
from .objects.meta import Meta
from .objects.stage import stage as ostage
from .objects.transfer import transfer as otransfer
from .scheme import Schemes from .scheme import Schemes
from .utils import relpath from .utils import relpath
from .utils.fs import path_isin from .utils.fs import path_isin
if TYPE_CHECKING: if TYPE_CHECKING:
from .objects.db.base import ObjectDB from .objects.db import ObjectDB
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -456,7 +458,7 @@ class Output:
return True return True
try: try:
objects.check(self.odb, obj) ocheck(self.odb, obj)
return False return False
except (FileNotFoundError, ObjectFormatError): except (FileNotFoundError, ObjectFormatError):
return True return True
@@ -710,7 +712,7 @@ class Output:
obj = self.obj obj = self.obj
elif self.hash_info: elif self.hash_info:
try: try:
obj = objects.load(self.odb, self.hash_info) obj = oload(self.odb, self.hash_info)
except FileNotFoundError: except FileNotFoundError:
return None return None
else: else:
@@ -857,7 +859,7 @@ class Output:
obj = self.odb.get(self.hash_info) obj = self.odb.get(self.hash_info)
try: try:
objects.check(self.odb, obj) ocheck(self.odb, obj)
except FileNotFoundError: except FileNotFoundError:
if self.remote: if self.remote:
kwargs["remote"] = self.remote kwargs["remote"] = self.remote
@@ -867,7 +869,7 @@ class Output:
return self.obj return self.obj
try: try:
self.obj = objects.load(self.odb, self.hash_info) self.obj = oload(self.odb, self.hash_info)
except (FileNotFoundError, ObjectFormatError): except (FileNotFoundError, ObjectFormatError):
self.obj = None self.obj = None
@@ -884,7 +886,7 @@ class Output:
logger.debug(f"failed to pull cache for '{self}'") logger.debug(f"failed to pull cache for '{self}'")
try: try:
objects.check(self.odb, self.odb.get(self.hash_info)) ocheck(self.odb, self.odb.get(self.hash_info))
except FileNotFoundError: except FileNotFoundError:
msg = ( msg = (
"Missing cache for directory '{}'. " "Missing cache for directory '{}'. "
@@ -1012,7 +1014,7 @@ class Output:
) )
def merge(self, ancestor, other): def merge(self, ancestor, other):
from dvc.objects.tree import du, merge from dvc.data.tree import du, merge
assert other assert other
+2 -2
View File
@@ -150,11 +150,11 @@ class Repo:
repo_factory=None, repo_factory=None,
): ):
from dvc.config import Config from dvc.config import Config
from dvc.data.db import ODBManager
from dvc.data_cloud import DataCloud from dvc.data_cloud import DataCloud
from dvc.fs.git import GitFileSystem from dvc.fs.git import GitFileSystem
from dvc.fs.local import localfs from dvc.fs.local import localfs
from dvc.lock import LockNoop, make_lock from dvc.lock import LockNoop, make_lock
from dvc.objects.db import ODBManager
from dvc.repo.live import Live from dvc.repo.live import Live
from dvc.repo.metrics import Metrics from dvc.repo.metrics import Metrics
from dvc.repo.params import Params from dvc.repo.params import Params
@@ -406,7 +406,7 @@ class Repo:
def _add_suffix(objs: Set["HashFile"], suffix: str) -> None: def _add_suffix(objs: Set["HashFile"], suffix: str) -> None:
from itertools import chain from itertools import chain
from dvc.objects import iterobjs from dvc.data import iterobjs
for obj in chain.from_iterable(map(iterobjs, objs)): for obj in chain.from_iterable(map(iterobjs, objs)):
if obj.name is not None: if obj.name is not None:
+1 -1
View File
@@ -113,8 +113,8 @@ def _paths_checksums(repo, targets):
def _output_paths(repo, targets): def _output_paths(repo, targets):
from dvc.data.stage import stage as ostage
from dvc.fs.local import LocalFileSystem from dvc.fs.local import LocalFileSystem
from dvc.objects.stage import stage as ostage
on_working_fs = isinstance(repo.fs, LocalFileSystem) on_working_fs = isinstance(repo.fs, LocalFileSystem)
+1 -1
View File
@@ -156,7 +156,7 @@ class SSHExecutor(BaseExecutor):
return sshfs.fs.execute(f"cd {working_dir};{cmd}", **kwargs) return sshfs.fs.execute(f"cd {working_dir};{cmd}", **kwargs)
def init_cache(self, dvc: "Repo", rev: str, run_cache: bool = True): def init_cache(self, dvc: "Repo", rev: str, run_cache: bool = True):
from dvc.objects.db import ODBManager, get_odb from dvc.data.db import ODBManager, get_odb
from dvc.repo import Repo from dvc.repo import Repo
from dvc.repo.push import push from dvc.repo.push import push
+1 -1
View File
@@ -44,7 +44,7 @@ def gc(
from contextlib import ExitStack from contextlib import ExitStack
from dvc.objects.db import get_index from dvc.data.db import get_index
from dvc.repo import Repo from dvc.repo import Repo
if not repos: if not repos:
+1 -1
View File
@@ -3,7 +3,7 @@ from collections.abc import Mapping
from voluptuous import Any, Optional, Required, Schema from voluptuous import Any, Optional, Required, Schema
from dvc import dependency, output from dvc import dependency, output
from dvc.objects.meta import Meta from dvc.data.meta import Meta
from dvc.output import CHECKSUMS_SCHEMA, Output from dvc.output import CHECKSUMS_SCHEMA, Output
from dvc.parsing import DO_KWD, FOREACH_KWD, VARS_KWD from dvc.parsing import DO_KWD, FOREACH_KWD, VARS_KWD
from dvc.parsing.versions import SCHEMA_KWD, lockfile_version_schema from dvc.parsing.versions import SCHEMA_KWD, lockfile_version_schema
+3 -3
View File
@@ -21,7 +21,7 @@ class RunCacheNotFoundError(DvcException):
def _get_cache_hash(cache, key=False): def _get_cache_hash(cache, key=False):
from dvc.objects.meta import Meta from dvc.data.meta import Meta
if key: if key:
cache["outs"] = [out["path"] for out in cache.get("outs", [])] cache["outs"] = [out["path"] for out in cache.get("outs", [])]
@@ -236,7 +236,7 @@ class StageCache:
return ret return ret
def push(self, remote: Optional[str], odb: Optional["ObjectDB"] = None): def push(self, remote: Optional[str], odb: Optional["ObjectDB"] = None):
from dvc.objects.transfer import _log_exceptions from dvc.data.transfer import _log_exceptions
if odb is None: if odb is None:
odb = self.repo.cloud.get_remote_odb(remote) odb = self.repo.cloud.get_remote_odb(remote)
@@ -247,7 +247,7 @@ class StageCache:
) )
def pull(self, remote: Optional[str]): def pull(self, remote: Optional[str]):
from dvc.objects.transfer import _log_exceptions from dvc.data.transfer import _log_exceptions
odb = self.repo.cloud.get_remote_odb(remote) odb = self.repo.cloud.get_remote_odb(remote)
return self._transfer( return self._transfer(
+1 -1
View File
@@ -6,8 +6,8 @@ from itertools import chain
from funcy import cached_property, get_in, lcat, once, project from funcy import cached_property, get_in, lcat, once, project
from dvc import dependency, output from dvc import dependency, output
from dvc.data.meta import Meta
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.meta import Meta
from dvc.parsing import FOREACH_KWD, JOIN, DataResolver, EntryNotFound from dvc.parsing import FOREACH_KWD, JOIN, DataResolver, EntryNotFound
from dvc.parsing.versions import LOCKFILE_VERSION from dvc.parsing.versions import LOCKFILE_VERSION
+1 -1
View File
@@ -4,8 +4,8 @@ from typing import TYPE_CHECKING, Union
from funcy import concat, first, lsplit, rpartial, without from funcy import concat, first, lsplit, rpartial, without
from dvc.data.meta import Meta
from dvc.exceptions import InvalidArgumentError from dvc.exceptions import InvalidArgumentError
from dvc.objects.meta import Meta
from .exceptions import ( from .exceptions import (
MissingDataSource, MissingDataSource,
+1 -1
View File
@@ -103,7 +103,7 @@ class State(StateBase): # pylint: disable=too-many-instance-attributes
HashInfo or None: hash for the specified path info or None if it HashInfo or None: hash for the specified path info or None if it
doesn't exist in the state database. doesn't exist in the state database.
""" """
from .objects.meta import Meta from .data.meta import Meta
if not isinstance(fs, LocalFileSystem): if not isinstance(fs, LocalFileSystem):
return None, None return None, None
+1 -1
View File
@@ -149,7 +149,7 @@ def local_remote(make_remote):
@pytest.fixture @pytest.fixture
def make_workspace(tmp_dir, dvc, make_cloud): def make_workspace(tmp_dir, dvc, make_cloud):
def _make_workspace(name, typ="local"): def _make_workspace(name, typ="local"):
from dvc.objects.db import ODBManager from dvc.data.db import ODBManager
cloud = make_cloud(typ) # pylint: disable=W0621 cloud = make_cloud(typ) # pylint: disable=W0621
+1 -1
View File
@@ -20,7 +20,7 @@ class TestImport:
pytest.skip() pytest.skip()
def test_import_dir(self, tmp_dir, dvc, workspace, stage_md5, dir_md5): def test_import_dir(self, tmp_dir, dvc, workspace, stage_md5, dir_md5):
from dvc.objects.db import ODBManager from dvc.data.db import ODBManager
workspace.gen( workspace.gen(
{"dir": {"file": "file", "subdir": {"subfile": "subfile"}}} {"dir": {"file": "file", "subdir": {"subfile": "subfile"}}}
+1 -1
View File
@@ -1,8 +1,8 @@
import pytest import pytest
from dvc.data.db import get_index
from dvc.exceptions import DownloadError, UploadError from dvc.exceptions import DownloadError, UploadError
from dvc.fs.local import LocalFileSystem from dvc.fs.local import LocalFileSystem
from dvc.objects.db import get_index
from dvc.utils.fs import remove from dvc.utils.fs import remove
from tests.utils import clean_staging from tests.utils import clean_staging
+6 -6
View File
@@ -11,6 +11,7 @@ import colorama
import pytest import pytest
import dvc as dvc_module import dvc as dvc_module
from dvc.data.db import ODBManager
from dvc.dvcfile import DVC_FILE_SUFFIX from dvc.dvcfile import DVC_FILE_SUFFIX
from dvc.exceptions import ( from dvc.exceptions import (
DvcException, DvcException,
@@ -22,7 +23,6 @@ from dvc.exceptions import (
from dvc.fs.local import LocalFileSystem from dvc.fs.local import LocalFileSystem
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.main import main from dvc.main import main
from dvc.objects.db import ODBManager
from dvc.output import ( from dvc.output import (
OutputAlreadyTrackedError, OutputAlreadyTrackedError,
OutputDoesNotExistError, OutputDoesNotExistError,
@@ -102,7 +102,7 @@ def test_add_unsupported_file(dvc):
def test_add_directory(tmp_dir, dvc): def test_add_directory(tmp_dir, dvc):
from dvc.objects import load from dvc.data import load
(stage,) = tmp_dir.dvc_gen({"dir": {"file": "file"}}) (stage,) = tmp_dir.dvc_gen({"dir": {"file": "file"}})
@@ -378,7 +378,7 @@ class TestDoubleAddUnchanged(TestDvc):
def test_should_update_state_entry_for_file_after_add(mocker, dvc, tmp_dir): def test_should_update_state_entry_for_file_after_add(mocker, dvc, tmp_dir):
file_md5_counter = mocker.spy(dvc_module.objects.stage, "file_md5") file_md5_counter = mocker.spy(dvc_module.data.stage, "file_md5")
tmp_dir.gen("foo", "foo") tmp_dir.gen("foo", "foo")
ret = main(["config", "cache.type", "copy"]) ret = main(["config", "cache.type", "copy"])
@@ -409,7 +409,7 @@ def test_should_update_state_entry_for_file_after_add(mocker, dvc, tmp_dir):
def test_should_update_state_entry_for_directory_after_add( def test_should_update_state_entry_for_directory_after_add(
mocker, dvc, tmp_dir mocker, dvc, tmp_dir
): ):
file_md5_counter = mocker.spy(dvc_module.objects.stage, "file_md5") file_md5_counter = mocker.spy(dvc_module.data.stage, "file_md5")
tmp_dir.gen({"data/data": "foo", "data/data_sub/sub_data": "foo"}) tmp_dir.gen({"data/data": "foo", "data/data_sub/sub_data": "foo"})
@@ -456,7 +456,7 @@ class TestAddCommit(TestDvc):
def test_should_collect_dir_cache_only_once(mocker, tmp_dir, dvc): def test_should_collect_dir_cache_only_once(mocker, tmp_dir, dvc):
tmp_dir.gen({"data/data": "foo"}) tmp_dir.gen({"data/data": "foo"})
counter = mocker.spy(dvc_module.objects.stage, "_stage_tree") counter = mocker.spy(dvc_module.data.stage, "_stage_tree")
ret = main(["add", "data"]) ret = main(["add", "data"])
assert ret == 0 assert ret == 0
assert counter.mock.call_count == 1 assert counter.mock.call_count == 1
@@ -880,7 +880,7 @@ def test_add_with_cache_link_error(tmp_dir, dvc, mocker, capsys):
tmp_dir.gen("foo", "foo") tmp_dir.gen("foo", "foo")
mocker.patch( mocker.patch(
"dvc.objects.checkout.test_links", "dvc.data.checkout.test_links",
return_value=[], return_value=[],
) )
dvc.add("foo") dvc.add("foo")
+1 -1
View File
@@ -85,7 +85,7 @@ class TestCheckoutCorruptedCacheFile(TestRepro):
class TestCheckoutCorruptedCacheDir(TestDvc): class TestCheckoutCorruptedCacheDir(TestDvc):
def test(self): def test(self):
from dvc.objects import load from dvc.data import load
# NOTE: using 'copy' so that cache and link don't have same inode # NOTE: using 'copy' so that cache and link don't have same inode
ret = main(["config", "cache.type", "copy"]) ret = main(["config", "cache.type", "copy"])
+2 -2
View File
@@ -107,7 +107,7 @@ def test_warn_on_outdated_stage(tmp_dir, dvc, local_remote, caplog):
def test_hash_recalculation(mocker, dvc, tmp_dir, local_remote): def test_hash_recalculation(mocker, dvc, tmp_dir, local_remote):
tmp_dir.gen({"foo": "foo"}) tmp_dir.gen({"foo": "foo"})
test_file_md5 = mocker.spy(dvc_module.objects.stage, "file_md5") test_file_md5 = mocker.spy(dvc_module.data.stage, "file_md5")
ret = main(["config", "cache.type", "hardlink"]) ret = main(["config", "cache.type", "hardlink"])
assert ret == 0 assert ret == 0
ret = main(["add", "foo"]) ret = main(["add", "foo"])
@@ -169,7 +169,7 @@ def test_verify_hashes(
remove("dir") remove("dir")
remove(dvc.odb.local.cache_dir) remove(dvc.odb.local.cache_dir)
hash_spy = mocker.spy(dvc_module.objects.stage, "file_md5") hash_spy = mocker.spy(dvc_module.data.stage, "file_md5")
dvc.pull() dvc.pull()
assert hash_spy.call_count == 0 assert hash_spy.call_count == 0
+2 -2
View File
@@ -3,9 +3,9 @@ from unittest.mock import ANY, patch
from scmrepo.git import Git from scmrepo.git import Git
from dvc.data.stage import stage
from dvc.data.transfer import transfer
from dvc.external_repo import CLONES, external_repo from dvc.external_repo import CLONES, external_repo
from dvc.objects.stage import stage
from dvc.objects.transfer import transfer
from dvc.utils import relpath from dvc.utils import relpath
from dvc.utils.fs import makedirs, remove from dvc.utils.fs import makedirs, remove
from tests.unit.fs.test_repo import make_subrepo from tests.unit.fs.test_repo import make_subrepo
+1 -1
View File
@@ -6,10 +6,10 @@ import configobj
import pytest import pytest
from git import Repo from git import Repo
from dvc.data.db.local import LocalObjectDB
from dvc.exceptions import CollectCacheError from dvc.exceptions import CollectCacheError
from dvc.fs.local import LocalFileSystem from dvc.fs.local import LocalFileSystem
from dvc.main import main from dvc.main import main
from dvc.objects.db.local import LocalObjectDB
from dvc.repo import Repo as DvcRepo from dvc.repo import Repo as DvcRepo
from dvc.utils.fs import remove from dvc.utils.fs import remove
from tests.basic_env import TestDir, TestDvcGit from tests.basic_env import TestDir, TestDvcGit
+1 -1
View File
@@ -3,8 +3,8 @@ import os
import pytest import pytest
from dvc.data.db import ODBManager
from dvc.main import main from dvc.main import main
from dvc.objects.db import ODBManager
from dvc.repo import Repo from dvc.repo import Repo
from dvc.repo.get import GetDVCFileError from dvc.repo.get import GetDVCFileError
from dvc.system import System from dvc.system import System
+2 -2
View File
@@ -7,9 +7,9 @@ from funcy import first
from scmrepo.git import Git from scmrepo.git import Git
from dvc.config import NoRemoteError from dvc.config import NoRemoteError
from dvc.data.db import ODBManager
from dvc.dvcfile import Dvcfile from dvc.dvcfile import Dvcfile
from dvc.exceptions import DownloadError, PathMissingError from dvc.exceptions import DownloadError, PathMissingError
from dvc.objects.db import ODBManager
from dvc.stage.exceptions import StagePathNotFoundError from dvc.stage.exceptions import StagePathNotFoundError
from dvc.system import System from dvc.system import System
from dvc.utils.fs import makedirs, remove from dvc.utils.fs import makedirs, remove
@@ -529,7 +529,7 @@ def test_import_with_no_exec(tmp_dir, dvc, erepo_dir):
def test_import_with_jobs(mocker, dvc, erepo_dir): def test_import_with_jobs(mocker, dvc, erepo_dir):
import dvc.objects.transfer as otransfer import dvc.data.transfer as otransfer
with erepo_dir.chdir(): with erepo_dir.chdir():
erepo_dir.dvc_gen( erepo_dir.dvc_gen(
+2 -2
View File
@@ -4,9 +4,9 @@ import stat
import configobj import configobj
import pytest import pytest
from dvc.data.db import ODBManager
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.main import main from dvc.main import main
from dvc.objects.db import ODBManager
from dvc.objects.errors import ObjectFormatError from dvc.objects.errors import ObjectFormatError
from dvc.utils import relpath from dvc.utils import relpath
from tests.basic_env import TestDir, TestDvc from tests.basic_env import TestDir, TestDvc
@@ -47,7 +47,7 @@ class TestCacheLoadBadDirCache(TestDvc):
self.assertEqual(len(ret), 0) self.assertEqual(len(ret), 0)
def test(self): def test(self):
from dvc.objects import load from dvc.data import load
dir_hash = "123.dir" dir_hash = "123.dir"
fname = os.fspath(self.dvc.odb.local.hash_to_path(dir_hash)) fname = os.fspath(self.dvc.odb.local.hash_to_path(dir_hash))
+4 -4
View File
@@ -139,8 +139,8 @@ def test_upper_case_remote(tmp_dir, dvc, local_cloud):
def test_dir_hash_should_be_key_order_agnostic(tmp_dir, dvc): def test_dir_hash_should_be_key_order_agnostic(tmp_dir, dvc):
from dvc.objects.stage import stage from dvc.data.stage import stage
from dvc.objects.tree import Tree from dvc.data.tree import Tree
tmp_dir.gen({"data": {"1": "1 content", "2": "2 content"}}) tmp_dir.gen({"data": {"1": "1 content", "2": "2 content"}})
@@ -150,7 +150,7 @@ def test_dir_hash_should_be_key_order_agnostic(tmp_dir, dvc):
[{"relpath": "1", "md5": "1"}, {"relpath": "2", "md5": "2"}] [{"relpath": "1", "md5": "1"}, {"relpath": "2", "md5": "2"}]
) )
tree.digest() tree.digest()
with patch("dvc.objects.stage._stage_tree", return_value=(None, tree)): with patch("dvc.data.stage._stage_tree", return_value=(None, tree)):
_, _, obj = stage(dvc.odb.local, path, dvc.odb.local.fs, "md5") _, _, obj = stage(dvc.odb.local, path, dvc.odb.local.fs, "md5")
hash1 = obj.hash_info hash1 = obj.hash_info
@@ -158,7 +158,7 @@ def test_dir_hash_should_be_key_order_agnostic(tmp_dir, dvc):
[{"md5": "1", "relpath": "1"}, {"md5": "2", "relpath": "2"}] [{"md5": "1", "relpath": "1"}, {"md5": "2", "relpath": "2"}]
) )
tree.digest() tree.digest()
with patch("dvc.objects.stage._stage_tree", return_value=(None, tree)): with patch("dvc.data.stage._stage_tree", return_value=(None, tree)):
_, _, obj = stage(dvc.odb.local, path, dvc.odb.local.fs, "md5") _, _, obj = stage(dvc.odb.local, path, dvc.odb.local.fs, "md5")
hash2 = obj.hash_info hash2 = obj.hash_info
+1 -1
View File
@@ -1,5 +1,5 @@
from dvc.data.db import ODBManager
from dvc.dvcfile import PIPELINE_FILE, PIPELINE_LOCK from dvc.dvcfile import PIPELINE_FILE, PIPELINE_LOCK
from dvc.objects.db import ODBManager
from dvc.system import System from dvc.system import System
+2 -2
View File
@@ -4,9 +4,9 @@ import shutil
import pytest import pytest
from dvc.config import NoRemoteError from dvc.config import NoRemoteError
from dvc.data.stage import stage
from dvc.fs.dvc import DvcFileSystem from dvc.fs.dvc import DvcFileSystem
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.stage import stage
from dvc.utils.fs import remove from dvc.utils.fs import remove
@@ -227,7 +227,7 @@ def test_get_hash_dir(tmp_dir, dvc, mocker):
{"dir": {"foo": "foo", "bar": "bar", "subdir": {"data": "data"}}} {"dir": {"foo": "foo", "bar": "bar", "subdir": {"data": "data"}}}
) )
fs = DvcFileSystem(repo=dvc) fs = DvcFileSystem(repo=dvc)
get_file_hash_spy = mocker.spy(dvc_module.objects.stage, "get_file_hash") get_file_hash_spy = mocker.spy(dvc_module.data.stage, "get_file_hash")
assert ( assert (
fs.info((tmp_dir / "dir").fs_path)["md5"] fs.info((tmp_dir / "dir").fs_path)["md5"]
== "8761c4e9acad696bee718615e23e22db.dir" == "8761c4e9acad696bee718615e23e22db.dir"
+3 -3
View File
@@ -4,9 +4,9 @@ from unittest import mock
import pytest import pytest
from dvc.data.stage import stage
from dvc.fs.repo import RepoFileSystem from dvc.fs.repo import RepoFileSystem
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.stage import stage
from tests.utils import clean_staging from tests.utils import clean_staging
@@ -584,9 +584,9 @@ def test_get_hash_mixed_dir(tmp_dir, scm, dvc):
def test_get_hash_dirty_file(tmp_dir, dvc): def test_get_hash_dirty_file(tmp_dir, dvc):
from dvc.objects import check from dvc.data import check
from dvc.data.stage import get_file_hash
from dvc.objects.errors import ObjectFormatError from dvc.objects.errors import ObjectFormatError
from dvc.objects.stage import get_file_hash
tmp_dir.dvc_gen("file", "file") tmp_dir.dvc_gen("file", "file")
file_hash_info = HashInfo("md5", "8c7dd922ad47494fc02c388e12c00eac") file_hash_info = HashInfo("md5", "8c7dd922ad47494fc02c388e12c00eac")
+8 -8
View File
@@ -3,9 +3,9 @@ import os
import pytest import pytest
from dvc.data.db.local import LocalObjectDB
from dvc.fs.local import LocalFileSystem from dvc.fs.local import LocalFileSystem
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.db.local import LocalObjectDB
def test_status_download_optimization(mocker, dvc): def test_status_download_optimization(mocker, dvc):
@@ -13,7 +13,7 @@ def test_status_download_optimization(mocker, dvc):
And the desired files to fetch are already on the local cache, And the desired files to fetch are already on the local cache,
Don't check the existence of the desired files on the remote cache Don't check the existence of the desired files on the remote cache
""" """
from dvc.objects.status import compare_status from dvc.data.status import compare_status
odb = LocalObjectDB(LocalFileSystem(), os.getcwd()) odb = LocalObjectDB(LocalFileSystem(), os.getcwd())
obj_ids = { obj_ids = {
@@ -85,9 +85,9 @@ def test_set_exec_ignore_errors(tmp_dir, dvc, mocker, err):
def test_staging_file(tmp_dir, dvc): def test_staging_file(tmp_dir, dvc):
from dvc.objects import check from dvc.data import check
from dvc.objects.stage import stage from dvc.data.stage import stage
from dvc.objects.transfer import transfer from dvc.data.transfer import transfer
tmp_dir.gen("foo", "foo") tmp_dir.gen("foo", "foo")
fs = LocalFileSystem() fs = LocalFileSystem()
@@ -113,9 +113,9 @@ def test_staging_file(tmp_dir, dvc):
def test_staging_dir(tmp_dir, dvc): def test_staging_dir(tmp_dir, dvc):
from dvc.objects import check from dvc.data import check
from dvc.objects.stage import stage from dvc.data.stage import stage
from dvc.objects.transfer import transfer from dvc.data.transfer import transfer
tmp_dir.gen({"dir": {"foo": "foo", "bar": "bar"}}) tmp_dir.gen({"dir": {"foo": "foo", "bar": "bar"}})
fs = LocalFileSystem() fs = LocalFileSystem()
+2 -2
View File
@@ -2,9 +2,9 @@ from operator import itemgetter
import pytest import pytest
from dvc.data.meta import Meta
from dvc.data.tree import Tree, _merge
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.meta import Meta
from dvc.objects.tree import Tree, _merge
@pytest.mark.parametrize( @pytest.mark.parametrize(
+1 -1
View File
@@ -1,8 +1,8 @@
import os import os
from unittest.mock import patch from unittest.mock import patch
from dvc.data.meta import Meta
from dvc.hash_info import HashInfo from dvc.hash_info import HashInfo
from dvc.objects.meta import Meta
from dvc.output import Output from dvc.output import Output
from dvc.stage import Stage from dvc.stage import Stage
from dvc.utils import relpath from dvc.utils import relpath
+1 -1
View File
@@ -3,7 +3,7 @@ import posixpath
from unittest import mock from unittest import mock
from dvc.fs.base import FileSystem from dvc.fs.base import FileSystem
from dvc.objects.db.base import ObjectDB from dvc.objects.db import ObjectDB
class _CallableOrNone: class _CallableOrNone:
+1 -1
View File
@@ -3,7 +3,7 @@ import os
import pytest import pytest
from funcy import first from funcy import first
from dvc.objects.db.index import ObjectDBIndex from dvc.data.db.index import ObjectDBIndex
@pytest.fixture @pytest.fixture
+1 -1
View File
@@ -2,10 +2,10 @@ import os
import pytest import pytest
from dvc.data.db import get_index
from dvc.fs import get_cloud_fs from dvc.fs import get_cloud_fs
from dvc.fs.gs import GSFileSystem from dvc.fs.gs import GSFileSystem
from dvc.fs.s3 import S3FileSystem from dvc.fs.s3 import S3FileSystem
from dvc.objects.db import get_index
def test_remote_with_hash_jobs(dvc): def test_remote_with_hash_jobs(dvc):
@@ -1,14 +1,12 @@
import pytest import pytest
import dvc.objects.db.slow_link_detection import dvc.data.slow_link_detection
from dvc.objects.db.slow_link_detection import slow_link_guard from dvc.data.slow_link_detection import slow_link_guard
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def timeout_immediately(monkeypatch): def timeout_immediately(monkeypatch):
monkeypatch.setattr( monkeypatch.setattr(dvc.data.slow_link_detection, "timeout_seconds", 0.0)
dvc.objects.db.slow_link_detection, "timeout_seconds", 0.0
)
@pytest.fixture @pytest.fixture
@@ -27,7 +25,7 @@ def test_show_warning_once(caplog, make_remote):
slow_link_guard(lambda x, y: None)(None, remote) slow_link_guard(lambda x, y: None)(None, remote)
slow_link_guard(lambda x, y: None)(None, remote) slow_link_guard(lambda x, y: None)(None, remote)
slow_link_detection = dvc.objects.db.slow_link_detection slow_link_detection = dvc.data.slow_link_detection
message = slow_link_detection.message # noqa, pylint: disable=no-member message = slow_link_detection.message # noqa, pylint: disable=no-member
assert len(caplog.records) == 1 assert len(caplog.records) == 1
assert caplog.records[0].message == message assert caplog.records[0].message == message
+1 -1
View File
@@ -167,7 +167,7 @@ def test_stage_cache_wdir(tmp_dir, dvc, mocker):
def test_shared_stage_cache(tmp_dir, dvc, run_copy): def test_shared_stage_cache(tmp_dir, dvc, run_copy):
import stat import stat
from dvc.objects.db import ODBManager from dvc.data.db import ODBManager
tmp_dir.gen("foo", "foo") tmp_dir.gen("foo", "foo")
+1 -1
View File
@@ -45,8 +45,8 @@ def dump_sv(stream, metrics, delimiter=",", header=True):
def clean_staging(): def clean_staging():
from dvc.data.stage import _STAGING_MEMFS_PATH
from dvc.fs.memory import MemoryFileSystem from dvc.fs.memory import MemoryFileSystem
from dvc.objects.stage import _STAGING_MEMFS_PATH
try: try:
MemoryFileSystem().fs.rm( MemoryFileSystem().fs.rm(