mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-05 23:09:32 +01:00
For now, this only takes a URL (or local path) and lists its contents if the protocol supports it. The command fails if the target doesn't exist and returns the (absolute) path to the target if it's not a directory.
223 lines
4.9 KiB
Python
223 lines
4.9 KiB
Python
"""Main parser for the dvc cli."""
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
from dvc.commands import (
|
|
add,
|
|
cache,
|
|
check_ignore,
|
|
checkout,
|
|
commit,
|
|
completion,
|
|
config,
|
|
daemon,
|
|
dag,
|
|
data,
|
|
data_sync,
|
|
destroy,
|
|
diff,
|
|
experiments,
|
|
freeze,
|
|
gc,
|
|
get,
|
|
get_url,
|
|
git_hook,
|
|
imp,
|
|
imp_url,
|
|
init,
|
|
install,
|
|
ls,
|
|
ls_url,
|
|
machine,
|
|
metrics,
|
|
move,
|
|
params,
|
|
plots,
|
|
queue,
|
|
remote,
|
|
remove,
|
|
repro,
|
|
root,
|
|
run,
|
|
stage,
|
|
unprotect,
|
|
update,
|
|
version,
|
|
)
|
|
|
|
from . import DvcParserError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
COMMANDS = [
|
|
init,
|
|
queue,
|
|
get,
|
|
get_url,
|
|
destroy,
|
|
add,
|
|
remove,
|
|
move,
|
|
unprotect,
|
|
run,
|
|
repro,
|
|
data_sync,
|
|
gc,
|
|
imp,
|
|
imp_url,
|
|
config,
|
|
checkout,
|
|
remote,
|
|
cache,
|
|
metrics,
|
|
params,
|
|
install,
|
|
root,
|
|
ls,
|
|
ls_url,
|
|
freeze,
|
|
dag,
|
|
daemon,
|
|
commit,
|
|
completion,
|
|
diff,
|
|
version,
|
|
update,
|
|
git_hook,
|
|
plots,
|
|
stage,
|
|
experiments,
|
|
check_ignore,
|
|
machine,
|
|
data,
|
|
]
|
|
|
|
|
|
def _find_parser(parser, cmd_cls):
|
|
defaults = parser._defaults # pylint: disable=protected-access
|
|
if not cmd_cls or cmd_cls == defaults.get("func"):
|
|
parser.print_help()
|
|
raise DvcParserError
|
|
|
|
actions = parser._actions # pylint: disable=protected-access
|
|
for action in actions:
|
|
if not isinstance(action.choices, dict):
|
|
# NOTE: we are only interested in subparsers
|
|
continue
|
|
for subparser in action.choices.values():
|
|
_find_parser(subparser, cmd_cls)
|
|
|
|
|
|
class DvcParser(argparse.ArgumentParser):
|
|
"""Custom parser class for dvc CLI."""
|
|
|
|
def error(self, message, cmd_cls=None): # pylint: disable=arguments-differ
|
|
logger.error(message)
|
|
_find_parser(self, cmd_cls)
|
|
|
|
def parse_args(self, args=None, namespace=None):
|
|
# NOTE: overriding to provide a more granular help message.
|
|
# E.g. `dvc plots diff --bad-flag` would result in a `dvc plots diff`
|
|
# help message instead of generic `dvc` usage.
|
|
args, argv = self.parse_known_args(args, namespace)
|
|
if argv:
|
|
msg = "unrecognized arguments: %s"
|
|
self.error(msg % " ".join(argv), getattr(args, "func", None))
|
|
return args
|
|
|
|
|
|
class VersionAction(argparse.Action): # pragma: no cover
|
|
# pylint: disable=too-few-public-methods
|
|
"""Shows DVC version and exits."""
|
|
|
|
def __call__(self, parser, namespace, values, option_string=None):
|
|
from dvc import __version__
|
|
|
|
print(__version__)
|
|
sys.exit(0)
|
|
|
|
|
|
def get_parent_parser():
|
|
"""Create instances of a parser containing common arguments shared among
|
|
all the commands.
|
|
|
|
When overwriting `-q` or `-v`, you need to instantiate a new object
|
|
in order to prevent some weird behavior.
|
|
"""
|
|
from dvc._debug import add_debugging_flags
|
|
|
|
parent_parser = argparse.ArgumentParser(add_help=False)
|
|
add_debugging_flags(parent_parser)
|
|
log_level_group = parent_parser.add_mutually_exclusive_group()
|
|
log_level_group.add_argument(
|
|
"-q", "--quiet", action="count", default=0, help="Be quiet."
|
|
)
|
|
log_level_group.add_argument(
|
|
"-v", "--verbose", action="count", default=0, help="Be verbose."
|
|
)
|
|
|
|
return parent_parser
|
|
|
|
|
|
def get_main_parser():
|
|
parent_parser = get_parent_parser()
|
|
|
|
# Main parser
|
|
desc = "Data Version Control"
|
|
parser = DvcParser(
|
|
prog="dvc",
|
|
description=desc,
|
|
parents=[parent_parser],
|
|
formatter_class=argparse.RawTextHelpFormatter,
|
|
add_help=False,
|
|
)
|
|
|
|
# NOTE: We are doing this to capitalize help message.
|
|
# Unfortunately, there is no easier and clearer way to do it,
|
|
# as adding this argument in get_parent_parser() either in
|
|
# log_level_group or on parent_parser itself will cause unexpected error.
|
|
parser.add_argument(
|
|
"-h",
|
|
"--help",
|
|
action="help",
|
|
default=argparse.SUPPRESS,
|
|
help="Show this help message and exit.",
|
|
)
|
|
|
|
# NOTE: On some python versions action='version' prints to stderr
|
|
# instead of stdout https://bugs.python.org/issue18920
|
|
parser.add_argument(
|
|
"-V",
|
|
"--version",
|
|
action=VersionAction,
|
|
nargs=0,
|
|
help="Show program's version.",
|
|
)
|
|
|
|
parser.add_argument(
|
|
"--cd",
|
|
default=os.path.curdir,
|
|
metavar="<path>",
|
|
help="Change to directory before executing.",
|
|
type=str,
|
|
)
|
|
|
|
# Sub commands
|
|
subparsers = parser.add_subparsers(
|
|
title="Available Commands",
|
|
metavar="COMMAND",
|
|
dest="cmd",
|
|
help="Use `dvc COMMAND --help` for command-specific help.",
|
|
)
|
|
|
|
from .utils import fix_subparsers
|
|
|
|
fix_subparsers(subparsers)
|
|
|
|
for cmd in COMMANDS:
|
|
cmd.add_parser(subparsers, parent_parser)
|
|
|
|
return parser
|