From b159ace6d7dd051d79e76bedc0af1905874d6097 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Wed, 29 Aug 2018 23:57:55 +0300 Subject: [PATCH] run: add `-y|--yes` option to bypass prompts Fixes #1072 Signed-off-by: Ruslan Kuprieiev --- dvc/cli.py | 8 ++++++++ dvc/command/destroy.py | 4 ++-- dvc/command/run.py | 3 +++ dvc/project.py | 7 +++++-- dvc/prompt.py | 21 ++++++++++++++------- dvc/stage.py | 7 ++++--- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/dvc/cli.py b/dvc/cli.py index bec8c7abe..b0449c186 100644 --- a/dvc/cli.py +++ b/dvc/cli.py @@ -235,6 +235,14 @@ def parse_args(argv=None): default=False, help="Only create stage file without actually " "running it.") + run_parser.add_argument( + '-y', + '--yes', + action='store_true', + default=False, + help="Automatic 'yes' answer to all prompts. E.g. " + "when '.dvc' file exists and dvc asks if you " + "want to overwrite it.") run_parser.add_argument( 'command', nargs=argparse.REMAINDER, diff --git a/dvc/command/destroy.py b/dvc/command/destroy.py index 01716906c..e7f0643e1 100644 --- a/dvc/command/destroy.py +++ b/dvc/command/destroy.py @@ -1,5 +1,4 @@ from dvc.command.base import CmdBase -from dvc.prompt import prompt from dvc.exceptions import DvcException @@ -10,7 +9,8 @@ class CmdDestroy(CmdBase): u'all data files, as well as cache in .dvc/cache.\n' \ u'Are you sure you want to continue?' - if not self.args.force and not prompt(msg, False): + if not self.args.force \ + and not self.project.prompt.prompt(msg, False): msg = u'Cannot destroy without a confirmation from the ' \ u'user. Use \'-f\' to force.' raise DvcException(msg) diff --git a/dvc/command/run.py b/dvc/command/run.py index e9e9f29a5..7167c2489 100644 --- a/dvc/command/run.py +++ b/dvc/command/run.py @@ -5,6 +5,9 @@ from dvc.exceptions import DvcException class CmdRun(CmdBase): def run(self): try: + if self.args.yes: + self.project.prompt.default = True + self.project.run(cmd=' '.join(self.args.command), outs=self.args.outs, outs_no_cache=self.args.outs_no_cache, diff --git a/dvc/project.py b/dvc/project.py index 464b01437..2eeb4d2f1 100644 --- a/dvc/project.py +++ b/dvc/project.py @@ -28,6 +28,7 @@ class Project(object): from dvc.cache import Cache from dvc.data_cloud import DataCloud from dvc.updater import Updater + from dvc.prompt import Prompt self.root_dir = os.path.abspath(os.path.realpath(root_dir)) self.dvc_dir = os.path.join(self.root_dir, self.DVC_DIR) @@ -46,6 +47,7 @@ class Project(object): self.cache = Cache(self) self.cloud = DataCloud(self, config=self.config._config) self.updater = Updater(self.dvc_dir) + self.prompt = Prompt() self._ignore() @@ -227,7 +229,8 @@ class Project(object): metrics_no_cache=[], fname=Stage.STAGE_FILE, cwd=os.curdir, - no_exec=False): + no_exec=False, + overwrite=False): stage = Stage.loads(project=self, fname=fname, cmd=cmd, @@ -236,7 +239,7 @@ class Project(object): outs_no_cache=outs_no_cache, metrics_no_cache=metrics_no_cache, deps=deps, - overwrite=False) + overwrite=overwrite) self._check_output_duplication(stage.outs) diff --git a/dvc/prompt.py b/dvc/prompt.py index ccf1c6251..bbece3ce6 100644 --- a/dvc/prompt.py +++ b/dvc/prompt.py @@ -7,12 +7,19 @@ except NameError: pass -def prompt(msg, default=False): # pragma: no cover - if not sys.stdout.isatty(): - return default +class Prompt(object): + def __init__(self): + self.default = None - answer = input(msg + u' (y/n)\n').lower() - while answer not in ['yes', 'no', 'y', 'n']: - answer = input('Enter \'yes\' or \'no\'.\n').lower() + def prompt(self, msg, default=False): # pragma: no cover + if self.default is not None: + return self.default - return answer[0] == "y" + if not sys.stdout.isatty(): + return default + + answer = input(msg + u' (y/n)\n').lower() + while answer not in ['yes', 'no', 'y', 'n']: + answer = input('Enter \'yes\' or \'no\'.\n').lower() + + return answer[0] == "y" diff --git a/dvc/stage.py b/dvc/stage.py index 25d6ee045..13872439a 100644 --- a/dvc/stage.py +++ b/dvc/stage.py @@ -8,7 +8,6 @@ from schema import Schema, SchemaError, Optional, Or, And import dvc.dependency as dependency import dvc.output as output from dvc.exceptions import DvcException -from dvc.prompt import prompt from dvc.logger import Logger from dvc.utils import dict_md5, fix_env @@ -183,7 +182,8 @@ class Stage(object): msg = "Going to reproduce '{}'. Are you sure you want to continue?" msg = msg.format(self.relpath) - if interactive and not prompt(msg): + if interactive \ + and not self.project.prompt.prompt(msg): raise DvcException('Reproduction aborted by the user') self.project.logger.info(u'Reproducing \'{}\''.format(self.relpath)) @@ -279,7 +279,8 @@ class Stage(object): relpath = os.path.relpath(path) msg = "'{}' already exists. " \ "Do you wish to run the command and overwrite it?" - if not overwrite and not prompt(msg.format(relpath), False): + if not overwrite \ + and not project.prompt.prompt(msg.format(relpath), False): raise DvcException("'{}' already exists".format(relpath)) stage.cwd = cwd