mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
+23
-17
@@ -4,26 +4,11 @@ from dvc.exceptions import DvcException
|
||||
|
||||
|
||||
class CmdRun(CmdBase):
|
||||
def _joined_cmd(self):
|
||||
if len(self.args.command) == 0:
|
||||
return ''
|
||||
|
||||
if len(self.args.command) == 1:
|
||||
return self.args.command[0]
|
||||
|
||||
cmd = ''
|
||||
for chunk in self.args.command:
|
||||
if len(chunk.split()) != 1:
|
||||
fmt = ' "{}"'
|
||||
else:
|
||||
fmt = ' {}'
|
||||
cmd += fmt.format(chunk)
|
||||
return cmd
|
||||
|
||||
def run(self):
|
||||
overwrite = (self.args.yes or self.args.overwrite_dvcfile)
|
||||
|
||||
try:
|
||||
self.project.run(cmd=self._joined_cmd(),
|
||||
self.project.run(cmd=self._parsed_cmd(),
|
||||
outs=self.args.outs,
|
||||
outs_no_cache=self.args.outs_no_cache,
|
||||
metrics_no_cache=self.args.metrics_no_cache,
|
||||
@@ -39,3 +24,24 @@ class CmdRun(CmdBase):
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
def _parsed_cmd(self):
|
||||
"""
|
||||
We need to take into account two cases:
|
||||
|
||||
- ['python code.py foo bar']: Used mainly with dvc as a library
|
||||
- ['echo', 'foo bar']: List of arguments received from the CLI
|
||||
|
||||
The second case would need quoting, as it was passed through:
|
||||
dvc run echo "foo bar"
|
||||
"""
|
||||
if len(self.args.command) < 2:
|
||||
return ' '.join(self.args.command)
|
||||
|
||||
return ' '.join(self._quote_argument(arg) for arg in self.args.command)
|
||||
|
||||
def _quote_argument(self, argument):
|
||||
if ' ' not in argument or '"' in argument:
|
||||
return argument
|
||||
|
||||
return '"{}"'.format(argument)
|
||||
|
||||
+15
-17
@@ -7,6 +7,7 @@ import subprocess
|
||||
from dvc.main import main
|
||||
from dvc.utils import file_md5
|
||||
from dvc.system import System
|
||||
from dvc.stage import Stage
|
||||
from dvc.stage import StageFileBadNameError, MissingDep
|
||||
from dvc.stage import StageBadCwdError, StageFileAlreadyExistsError
|
||||
from dvc.exceptions import (OutputDuplicationError,
|
||||
@@ -173,33 +174,30 @@ class TestCmdRun(TestDvc):
|
||||
'-o', 'out',
|
||||
'-f', 'out.dvc',
|
||||
'python', self.CODE, self.FOO, 'out'])
|
||||
|
||||
stage = Stage.load(self.dvc, fname='out.dvc')
|
||||
|
||||
self.assertEqual(ret, 0)
|
||||
self.assertTrue(os.path.isfile('out'))
|
||||
self.assertTrue(os.path.isfile('out.dvc'))
|
||||
self.assertTrue(filecmp.cmp(self.FOO, 'out', shallow=False))
|
||||
self.assertEqual(stage.cmd, 'python code.py foo out')
|
||||
|
||||
def test_run_args_from_cli(self):
|
||||
ret = main(['run', 'echo', 'foo'])
|
||||
stage = Stage.load(self.dvc, fname='Dvcfile')
|
||||
self.assertEqual(ret, 0)
|
||||
self.assertEqual(stage.cmd, 'echo foo')
|
||||
|
||||
def test_run_bad_command(self):
|
||||
ret = main(['run',
|
||||
'non-existing-command'])
|
||||
ret = main(['run', 'non-existing-command'])
|
||||
self.assertNotEqual(ret, 0)
|
||||
|
||||
def test_run_args_with_spaces(self):
|
||||
with open(self.CODE, 'w') as fobj:
|
||||
fobj.write(
|
||||
"import sys\nopen(sys.argv[1], 'w+').write(sys.argv[2])")
|
||||
|
||||
arg = 'arg1 arg2'
|
||||
log = 'log'
|
||||
ret = main(['run',
|
||||
'python',
|
||||
self.CODE,
|
||||
log,
|
||||
'arg1 arg2'])
|
||||
|
||||
ret = main(['run', 'echo', 'foo bar'])
|
||||
stage = Stage.load(self.dvc, fname='Dvcfile')
|
||||
self.assertEqual(ret, 0)
|
||||
|
||||
with open(log, 'r') as fobj:
|
||||
self.assertEqual(fobj.read(), arg)
|
||||
self.assertEqual(stage.cmd, 'echo "foo bar"')
|
||||
|
||||
@mock.patch.object(subprocess, 'Popen', side_effect=KeyboardInterrupt)
|
||||
def test_keyboard_interrupt(self, mock_popen):
|
||||
|
||||
Reference in New Issue
Block a user