run: Check for circular dependencies

Close #1235
This commit is contained in:
Mr. Outis
2018-10-22 17:29:55 -05:00
parent 7a004fa328
commit 239313d67e
3 changed files with 26 additions and 1 deletions
+7
View File
@@ -31,6 +31,13 @@ class OutputDuplicationError(DvcException):
super(OutputDuplicationError, self).__init__(msg.format(output, s))
class CircularDependencyError(DvcException):
def __init__(self, dependency):
assert isinstance(dependency, str)
msg = "File '{}' is specified as an output and as a dependency."
super(CircularDependencyError, self).__init__(msg.format(dependency))
class MoveNotDataSourceError(DvcException):
def __init__(self, path):
msg = "Move is not permitted for stages that are not data sources. " \
+9
View File
@@ -143,6 +143,14 @@ class Project(object):
stages = [o.stage.relpath, out.stage.relpath]
raise OutputDuplicationError(o.path, stages)
def _check_circular_dependency(self, deps, outs):
from dvc.exceptions import CircularDependencyError
circular_dependencies = set(deps) & set(outs)
raise CircularDependencyError(circular_dependencies.pop())
def add(self, fname, recursive=False):
fnames = []
if recursive and os.path.isdir(fname):
@@ -258,6 +266,7 @@ class Project(object):
overwrite=overwrite)
self._check_output_duplication(stage.outs)
self._check_circular_dependency(deps, outs)
self._files_to_git_add = []
with self.state:
+10 -1
View File
@@ -5,7 +5,7 @@ from dvc.main import main
from dvc.utils import file_md5
from dvc.stage import Stage, StageFileBadNameError, MissingDep
from dvc.command.run import CmdRun
from dvc.exceptions import OutputDuplicationError
from dvc.exceptions import OutputDuplicationError, CircularDependencyError
from tests.basic_env import TestDvc
@@ -93,6 +93,15 @@ class TestRunNoExec(TestDvc):
self.assertFalse(os.path.exists('out'))
class TestRunCircularDependency(TestDvc):
def test(self):
with self.assertRaises(CircularDependencyError):
self.dvc.run(cmd='',
deps=[self.FOO],
outs=[self.FOO],
fname='circular-dependency.dvc')
class TestCmdRun(TestDvc):
def test_run(self):
ret = main(['run',