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):