From 537e7c75a0e42cb331612f418fe5500aaf0bbefa Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Sun, 9 Sep 2018 22:44:05 +0300 Subject: [PATCH] stage: check that deps exist before running the command Fixes #1101 Signed-off-by: Ruslan Kuprieiev --- dvc/dependency/base.py | 2 +- dvc/stage.py | 24 ++++++++++++++++++++++++ tests/test_run.py | 13 ++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/dvc/dependency/base.py b/dvc/dependency/base.py index 512c44621..605d686ec 100644 --- a/dvc/dependency/base.py +++ b/dvc/dependency/base.py @@ -54,7 +54,7 @@ class DependencyBase(object): @property def exists(self): - return self.remote.exists([self.path_info]) + return self.remote.exists([self.path_info])[0] def changed(self): raise NotImplementedError diff --git a/dvc/stage.py b/dvc/stage.py index 13872439a..6b6e1a991 100644 --- a/dvc/stage.py +++ b/dvc/stage.py @@ -42,6 +42,19 @@ class StageFileBadNameError(DvcException): super(StageFileBadNameError, self).__init__(msg.format(fname, fname)) +class MissingDep(DvcException): + def __init__(self, deps): + assert len(deps) > 0 + + if len(deps) > 1: + dep = 'dependencies' + else: + dep = 'dependency' + + msg = u'missing {}: {}'.format(dep, ', '.join(map(str, deps))) + super(MissingDep, self).__init__(msg) + + class MissingDataSource(DvcException): def __init__(self, missing_files): assert len(missing_files) > 0 @@ -354,7 +367,18 @@ class Stage(object): for out in self.outs: out.save() + def _check_missing_deps(self): + missing = [] + for dep in self.deps: + if not dep.exists: + missing.append(dep) + + if len(missing) > 0: + raise MissingDep(missing) + def run(self, dry=False): + self._check_missing_deps() + if self.locked: msg = u'Verifying outputs in locked stage \'{}\'' self.project.logger.info(msg.format(self.relpath)) diff --git a/tests/test_run.py b/tests/test_run.py index 32052fc9e..89f8674ce 100644 --- a/tests/test_run.py +++ b/tests/test_run.py @@ -3,7 +3,7 @@ import filecmp from dvc.main import main from dvc.utils import file_md5 -from dvc.stage import Stage, StageFileBadNameError +from dvc.stage import Stage, StageFileBadNameError, MissingDep from dvc.command.run import CmdRun from dvc.exceptions import OutputDuplicationError @@ -55,6 +55,17 @@ class TestRunEmpty(TestDvc): cwd=os.curdir) +class TestRunMissingDep(TestDvc): + def test(self): + with self.assertRaises(MissingDep): + self.dvc.run(cmd='', + deps=['non-existing-dep'], + outs=[], + outs_no_cache=[], + fname='empty.dvc', + cwd=os.curdir) + + class TestRunBadStageFilename(TestDvc): def test(self): with self.assertRaises(StageFileBadNameError):