mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-10 07:18:27 +01:00
dvc: check stage filename
Fixes #1054 Signed-off-by: Ruslan Kuprieiev <[email protected]>
This commit is contained in:
+6
-1
@@ -217,7 +217,12 @@ def parse_args(argv=None):
|
||||
run_parser.add_argument(
|
||||
'-f',
|
||||
'--file',
|
||||
help='Specify name of the state file.')
|
||||
help="Specify name of the stage file. It should be "
|
||||
"either 'Dvcfile' or have a '.dvc' suffix (e.g. "
|
||||
"'prepare.dvc', 'clean.dvc', etc) in order for "
|
||||
"dvc to be able to find it later. By default "
|
||||
"the first output basename + .dvc is used as "
|
||||
"a stage filename.")
|
||||
run_parser.add_argument(
|
||||
'-c',
|
||||
'--cwd',
|
||||
|
||||
+24
-4
@@ -36,6 +36,13 @@ class StageFileIsNotDvcFileError(DvcException):
|
||||
super(StageFileIsNotDvcFileError, self).__init__(msg)
|
||||
|
||||
|
||||
class StageFileBadNameError(DvcException):
|
||||
def __init__(self, fname):
|
||||
msg = "Bad stage filename '{}'. Stage files should be named " \
|
||||
"'Dvcfile' or have a '.dvc' suffix(e.g. '{}.dvc')."
|
||||
super(StageFileBadNameError, self).__init__(msg.format(fname, fname))
|
||||
|
||||
|
||||
class MissingDataSource(DvcException):
|
||||
def __init__(self, missing_files):
|
||||
assert len(missing_files) > 0
|
||||
@@ -93,16 +100,20 @@ class Stage(object):
|
||||
return self.cmd is None
|
||||
|
||||
@staticmethod
|
||||
def is_stage_file(path):
|
||||
if not os.path.isfile(path):
|
||||
return False
|
||||
|
||||
def is_stage_filename(path):
|
||||
if not path.endswith(Stage.STAGE_FILE_SUFFIX) \
|
||||
and os.path.basename(path) != Stage.STAGE_FILE:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def is_stage_file(path):
|
||||
if not os.path.isfile(path):
|
||||
return False
|
||||
|
||||
return Stage.is_stage_filename(path)
|
||||
|
||||
def changed_md5(self):
|
||||
md5 = self.dumpd().get(self.PARAM_MD5, None)
|
||||
|
||||
@@ -276,6 +287,11 @@ class Stage(object):
|
||||
|
||||
return stage
|
||||
|
||||
@staticmethod
|
||||
def _check_dvc_filename(fname):
|
||||
if not Stage.is_stage_filename(fname):
|
||||
raise StageFileBadNameError(os.path.relpath(fname))
|
||||
|
||||
@staticmethod
|
||||
def _check_dvc_file(fname):
|
||||
sname = fname + Stage.STAGE_FILE_SUFFIX
|
||||
@@ -288,6 +304,8 @@ class Stage(object):
|
||||
Stage._check_dvc_file(fname)
|
||||
raise StageFileDoesNotExistError(fname)
|
||||
|
||||
Stage._check_dvc_filename(fname)
|
||||
|
||||
if not Stage.is_stage_file(fname):
|
||||
Stage._check_dvc_file(fname)
|
||||
raise StageFileIsNotDvcFileError(fname)
|
||||
@@ -320,6 +338,8 @@ class Stage(object):
|
||||
if not fname:
|
||||
fname = self.path
|
||||
|
||||
self._check_dvc_filename(fname)
|
||||
|
||||
msg = "Saving information to '{}'.".format(os.path.relpath(fname))
|
||||
Logger.info(msg)
|
||||
|
||||
|
||||
+12
-1
@@ -3,7 +3,7 @@ import filecmp
|
||||
|
||||
from dvc.main import main
|
||||
from dvc.utils import file_md5
|
||||
from dvc.stage import Stage
|
||||
from dvc.stage import Stage, StageFileBadNameError
|
||||
from dvc.command.run import CmdRun
|
||||
from dvc.exceptions import OutputDuplicationError
|
||||
|
||||
@@ -55,6 +55,17 @@ class TestRunEmpty(TestDvc):
|
||||
cwd=os.curdir)
|
||||
|
||||
|
||||
class TestRunBadStageFilename(TestDvc):
|
||||
def test(self):
|
||||
with self.assertRaises(StageFileBadNameError):
|
||||
self.dvc.run(cmd='',
|
||||
deps=[],
|
||||
outs=[],
|
||||
outs_no_cache=[],
|
||||
fname='empty',
|
||||
cwd=os.curdir)
|
||||
|
||||
|
||||
class TestRunNoExec(TestDvc):
|
||||
def test(self):
|
||||
self.dvc.run(cmd='python {} {} {}'.format(self.CODE, self.FOO, 'out'),
|
||||
|
||||
Reference in New Issue
Block a user