Skip to content

Commit

Permalink
Make imports on dvc.repo and dvc.repo.plots lazy (iterative#5227)
Browse files Browse the repository at this point in the history
  • Loading branch information
skshetry authored Jan 7, 2021
1 parent 40122ce commit 66fc988
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 24 deletions.
4 changes: 2 additions & 2 deletions dvc/repo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@

from funcy import cached_property, cat

from dvc.config import Config
from dvc.exceptions import FileMissingError
from dvc.exceptions import IsADirectoryError as DvcIsADirectoryError
from dvc.exceptions import NotDvcRepoError, OutputNotFoundError
from dvc.path_info import PathInfo
from dvc.scm.base import SCMError
from dvc.utils.fs import path_isin

from .graph import build_graph, build_outs_graph, get_pipelines
Expand Down Expand Up @@ -94,6 +92,7 @@ def _get_repo_dirs(
assert bool(scm) == bool(rev)

from dvc.scm import SCM
from dvc.scm.base import SCMError
from dvc.scm.git import Git
from dvc.utils.fs import makedirs

Expand Down Expand Up @@ -131,6 +130,7 @@ def __init__(
config=None,
):
from dvc.cache import Cache
from dvc.config import Config
from dvc.data_cloud import DataCloud
from dvc.lock import LockNoop, make_lock
from dvc.repo.live import Live
Expand Down
2 changes: 1 addition & 1 deletion dvc/repo/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from dvc.config import NoRemoteError
from dvc.exceptions import DownloadError
from dvc.scm.base import CloneError

from . import locked

Expand Down Expand Up @@ -81,6 +80,7 @@ def fetch(

def _fetch_external(self, repo_url, repo_rev, files, jobs):
from dvc.external_repo import external_repo
from dvc.scm.base import CloneError

failed, downloaded = 0, 0
cache = self.cache.local
Expand Down
4 changes: 2 additions & 2 deletions dvc/repo/get.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import logging
import os

import shortuuid

from dvc.exceptions import DvcException
from dvc.utils import resolve_output
from dvc.utils.fs import remove
Expand All @@ -19,6 +17,8 @@ def __init__(self):


def get(url, path, out=None, rev=None):
import shortuuid

from dvc.dvcfile import is_valid_filename
from dvc.external_repo import external_repo

Expand Down
16 changes: 10 additions & 6 deletions dvc/repo/live.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import contextlib
import os
from typing import List
from typing import TYPE_CHECKING, List, Optional

from dvc.exceptions import MetricDoesNotExistError, MetricsError
from dvc.output import BaseOutput
from dvc.path_info import PathInfo
from dvc.repo import Repo

if TYPE_CHECKING:
from dvc.output import BaseOutput
from dvc.path_info import PathInfo
from dvc.repo import Repo


def summary_path_info(out: "BaseOutput") -> Optional["PathInfo"]:
from dvc.output import BaseOutput

def summary_path_info(out: BaseOutput) -> PathInfo:
assert out.live
has_summary = True
if isinstance(out.live, dict):
Expand All @@ -19,7 +23,7 @@ def summary_path_info(out: BaseOutput) -> PathInfo:


class Live:
def __init__(self, repo: Repo):
def __init__(self, repo: "Repo"):
self.repo = repo

def show(self, target: str, revs: List[str] = None):
Expand Down
6 changes: 4 additions & 2 deletions dvc/repo/plots/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
NoMetricsFoundError,
NoMetricsParsedError,
)
from dvc.repo.collect import collect
from dvc.repo.plots.data import PlotParsingError
from dvc.utils import relpath

if TYPE_CHECKING:
Expand Down Expand Up @@ -95,6 +93,8 @@ def collect(
@staticmethod
def render(data, revs=None, props=None, templates=None):
"""Renders plots"""
from dvc.repo.plots.data import PlotParsingError

props = props or {}

# Merge data by plot file and apply overriding props
Expand Down Expand Up @@ -213,6 +213,8 @@ def _collect_plots(
rev: str = None,
recursive: bool = False,
) -> Dict[str, Dict]:
from dvc.repo.collect import collect

plots, path_infos = collect(
repo,
output_filter=_is_plot,
Expand Down
14 changes: 6 additions & 8 deletions dvc/repo/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@

from funcy import concat, first, lfilter, without

from dvc.exceptions import InvalidArgumentError
from dvc.stage.exceptions import (
DuplicateStageName,
InvalidStageName,
StageFileAlreadyExistsError,
)

from ..exceptions import OutputDuplicationError
from . import locked
from .scm_context import scm_context

Expand Down Expand Up @@ -61,6 +53,10 @@ def _get_file_path(kwargs):

def _check_stage_exists(dvcfile, stage):
from dvc.stage import PipelineStage
from dvc.stage.exceptions import (
DuplicateStageName,
StageFileAlreadyExistsError,
)

if not dvcfile.exists():
return
Expand All @@ -80,7 +76,9 @@ def _check_stage_exists(dvcfile, stage):
@scm_context
def run(self, fname=None, no_exec=False, single_stage=False, **kwargs):
from dvc.dvcfile import PIPELINE_FILE, Dvcfile
from dvc.exceptions import InvalidArgumentError, OutputDuplicationError
from dvc.stage import PipelineStage, Stage, create_stage, restore_meta
from dvc.stage.exceptions import InvalidStageName

if not kwargs.get("cmd"):
raise InvalidArgumentError("command is not specified")
Expand Down
23 changes: 20 additions & 3 deletions dvc/repo/stage.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
from contextlib import suppress
from typing import Iterable, List, NamedTuple, Optional, Set, Tuple

from dvc.dvcfile import PIPELINE_FILE, Dvcfile, is_valid_filename
from dvc.exceptions import (
DvcException,
NoOutputOrStageError,
OutputNotFoundError,
)
from dvc.path_info import PathInfo
from dvc.repo.graph import collect_inside_path, collect_pipeline
from dvc.stage.exceptions import StageFileDoesNotExistError, StageNotFound
from dvc.utils import parse_target, relpath

logger = logging.getLogger(__name__)
Expand All @@ -26,6 +23,8 @@
from dvc.stage.loader import StageLoader
from dvc.types import OptStr

PIPELINE_FILE = "dvc.yaml"


class StageInfo(NamedTuple):
stage: "Stage"
Expand All @@ -38,6 +37,8 @@ class StageInfo(NamedTuple):


def _collect_with_deps(stages: StageList, graph: "DiGraph") -> StageSet:
from dvc.repo.graph import collect_pipeline

res: StageSet = set()
for stage in stages:
res.update(collect_pipeline(stage, graph=graph))
Expand All @@ -47,6 +48,7 @@ def _collect_with_deps(stages: StageList, graph: "DiGraph") -> StageSet:
def _maybe_collect_from_dvc_yaml(
loader: "StageLoad", target, with_deps: bool, **load_kwargs,
) -> StageIter:
from dvc.stage.exceptions import StageNotFound

stages: StageList = []
if loader.tree.exists(PIPELINE_FILE):
Expand All @@ -62,6 +64,8 @@ def _collect_specific_target(
recursive: bool,
accept_group: bool,
) -> Tuple[StageIter, "OptStr", "OptStr"]:
from dvc.dvcfile import is_valid_filename

# Optimization: do not collect the graph for a specific target
file, name = parse_target(target)

Expand Down Expand Up @@ -163,6 +167,7 @@ def load_all(
glob: if true, `name` is considered as a glob, which is
used to filter list of stages from the given `path`.
"""
from dvc.dvcfile import Dvcfile
from dvc.stage.loader import SingleStageLoader, StageLoader

path = self._get_filepath(path, name)
Expand All @@ -185,6 +190,8 @@ def load_one(self, path: str = None, name: str = None) -> "Stage":
path: if not provided, default `dvc.yaml` is assumed.
name: required for `dvc.yaml` files, ignored for `.dvc` files.
"""
from dvc.dvcfile import Dvcfile

path = self._get_filepath(path, name)
dvcfile = Dvcfile(self.repo, path)

Expand Down Expand Up @@ -251,6 +258,8 @@ def collect(
return list(graph) if graph else self.repo.stages

if recursive and self.repo.tree.isdir(target):
from dvc.repo.graph import collect_inside_path

path = os.path.abspath(target)
return collect_inside_path(path, graph or self.graph)

Expand Down Expand Up @@ -301,6 +310,12 @@ def collect_granular(
except OutputNotFoundError:
pass

from dvc.dvcfile import is_valid_filename
from dvc.stage.exceptions import (
StageFileDoesNotExistError,
StageNotFound,
)

try:
stages = self.collect(
target,
Expand Down Expand Up @@ -331,6 +346,8 @@ def collect_repo(self, onerror=None):
Otherwise, the file will be skipped, and dvc will partially
load the stages.
"""
from dvc.dvcfile import is_valid_filename

stages = []
outs = set()
for root, dirs, files in self.tree.walk(self.repo.root_dir):
Expand Down

0 comments on commit 66fc988

Please sign in to comment.