Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6de665f
cli: split main_parser
casperdcl May 31, 2020
e35a363
cli: basic parser tree printing
casperdcl May 31, 2020
ebb8f21
cli: major completion tidy
casperdcl May 31, 2020
743a6dc
completion: more missing root commands
casperdcl May 31, 2020
d21f48d
completion: much automagic such beauty
casperdcl May 31, 2020
e0ee359
tests: bash completion
casperdcl May 31, 2020
62d8f48
tests: completion: tidy script a little
casperdcl May 31, 2020
387896d
minor tidy
casperdcl May 31, 2020
7769b6c
command: positional name consistency
casperdcl Jun 1, 2020
732f118
completion: bash: add logging
casperdcl Jun 1, 2020
82ca4b2
double-check renames and consistency
casperdcl Jun 2, 2020
3673e5f
cli: add completion subcommand
casperdcl Jun 2, 2020
d900333
ci: completion: update test
casperdcl Jun 2, 2020
5f41c32
minor logging
casperdcl Jun 2, 2020
3f2ea55
more completion logging verbosity
casperdcl Jun 2, 2020
a7bdb8c
fix completion of files
casperdcl Jun 8, 2020
ae49399
add shtab
casperdcl Jun 14, 2020
dd82a7f
purge unneeded completion => shtab
casperdcl Jun 14, 2020
edfd3c2
completion: neaten UI
casperdcl Jun 15, 2020
11a3647
completion: use `shtab>=0.0.2`
casperdcl Jun 18, 2020
2f23ccc
completion: purge hardcoded completions!
casperdcl Jun 18, 2020
ef3ce8f
Merge remote-tracking branch 'upstream/master' into completion-auto
casperdcl Jun 18, 2020
c13dd09
revert unneeded renames for now
casperdcl Jun 18, 2020
dfcf3f2
fix isort
casperdcl Jun 18, 2020
3600385
completion: tidy CLI API
casperdcl Jun 18, 2020
79e8e87
fix snap build
casperdcl Jun 18, 2020
f39cbc8
fix snap build again
casperdcl Jun 18, 2020
8b27135
snap: internally build completion
casperdcl Jun 18, 2020
2267ad9
allow repo-less completion
casperdcl Jun 18, 2020
1386ffa
command: tidy headless logic
casperdcl Jun 18, 2020
ac00de1
use CmdBaseNoRepo
casperdcl Jun 18, 2020
5b80e08
better DVC-file completion
casperdcl Jun 18, 2020
e211340
merge command.choices -> command.completion
casperdcl Jun 18, 2020
9c204f3
drop choices class
casperdcl Jun 18, 2020
80157c2
remove completion optionals
casperdcl Jun 19, 2020
18a0e58
tidy docs
casperdcl Jun 19, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
* [ ] ❗ I have followed the [Contributing to DVC](https://dvc.org/doc/user-guide/contributing/core) checklist.

* [ ] 📖 If this PR requires [documentation](https://dvc.org/doc) updates, I have created a separate PR (or issue, at least) in [dvc.org](https://github.com/iterative/dvc.org) and linked it here. If the CLI API is changed, I have updated [tab completion scripts](https://github.com/iterative/dvc/tree/master/scripts/completion).
* [ ] 📖 If this PR requires [documentation](https://dvc.org/doc) updates, I have created a separate PR (or issue, at least) in [dvc.org](https://github.com/iterative/dvc.org) and linked it here.

* [ ] ❌ I will check DeepSource, CodeClimate, and other sanity checks below. (We consider them recommendatory and don't expect everything to be addressed. Please fix things that actually improve code or fix bugs.)

Expand Down
26 changes: 16 additions & 10 deletions dvc/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
cache,
checkout,
commit,
completion,
config,
daemon,
dag,
Expand Down Expand Up @@ -70,6 +71,7 @@
dag,
daemon,
commit,
completion,
diff,
version,
update,
Expand Down Expand Up @@ -140,15 +142,7 @@ def get_parent_parser():
return parent_parser


def parse_args(argv=None):
"""Parses CLI arguments.

Args:
argv: optional list of arguments to parse. sys.argv is used by default.

Raises:
dvc.exceptions.DvcParserError: raised for argument parsing errors.
"""
def get_main_parser():
parent_parser = get_parent_parser()

# Main parser
Expand Down Expand Up @@ -196,6 +190,18 @@ def parse_args(argv=None):
for cmd in COMMANDS:
cmd.add_parser(subparsers, parent_parser)

args = parser.parse_args(argv)
return parser


def parse_args(argv=None):
"""Parses CLI arguments.

Args:
argv: optional list of arguments to parse. sys.argv is used by default.

Raises:
dvc.exceptions.DvcParserError: raised for argument parsing errors.
"""
parser = get_main_parser()
args = parser.parse_args(argv)
return args
6 changes: 5 additions & 1 deletion dvc/command/add.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import logging

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import DvcException, RecursiveAddingWhileUsingFilename

Expand Down Expand Up @@ -62,6 +63,9 @@ def add_parser(subparsers, parent_parser):
metavar="<filename>",
)
parser.add_argument(
"targets", nargs="+", help="Input files/directories to add."
"targets",
nargs="+",
help="Input files/directories to add.",
choices=completion.Required.FILE,
)
parser.set_defaults(func=CmdAdd)
2 changes: 2 additions & 0 deletions dvc/command/cache.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import argparse

from dvc.command import completion
from dvc.command.base import append_doc_link, fix_subparsers
from dvc.command.config import CmdConfig

Expand Down Expand Up @@ -55,5 +56,6 @@ def add_parser(subparsers, parent_parser):
help="Path to cache directory. Relative paths are resolved relative "
"to the current directory and saved to config relative to the "
"config file location.",
choices=completion.Required.DIR,
)
cache_dir_parser.set_defaults(func=CmdCacheDir)
2 changes: 2 additions & 0 deletions dvc/command/checkout.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import colorama

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import CheckoutError
from dvc.utils.humanize import get_summary
Expand Down Expand Up @@ -113,5 +114,6 @@ def add_parser(subparsers, parent_parser):
nargs="*",
help="DVC-files to checkout. Optional. "
"(Finds all DVC-files in the workspace by default.)",
choices=completion.Optional.DVC_FILE,
)
checkout_parser.set_defaults(func=CmdCheckout)
2 changes: 2 additions & 0 deletions dvc/command/commit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import logging

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import DvcException

Expand Down Expand Up @@ -66,5 +67,6 @@ def add_parser(subparsers, parent_parser):
nargs="*",
help="DVC-files to commit. Optional. "
"(Finds all DVC-files in the workspace by default.)",
choices=completion.Optional.DVC_FILE,
)
commit_parser.set_defaults(func=CmdCommit)
68 changes: 68 additions & 0 deletions dvc/command/completion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import argparse
import logging

import shtab

from dvc.command.base import CmdBaseNoRepo, append_doc_link

logger = logging.getLogger(__name__)
CHOICE_FUNCTIONS = {
"bash": {"DVCFile": "_dvc_compgen_DVCFiles"},
"zsh": {"DVCFile": "_files -g '(*?.dvc|Dvcfile|dvc.yaml)'"},
}
PREAMBLE = {
"bash": """
# $1=COMP_WORDS[1]
_dvc_compgen_DVCFiles() {
compgen -d -S '/' -- $1 # recurse into subdirs
compgen -f -X '!*?.dvc' -- $1
compgen -f -X '!*Dvcfile' -- $1
compgen -f -X '!*dvc.yaml' -- $1
}
""",
"zsh": "",
}


class Optional(shtab.Optional):
DVC_FILE = [shtab.Choice("DVCFile", required=False)]


class Required(shtab.Required):
DVC_FILE = [shtab.Choice("DVCFile", required=True)]


class CmdCompletion(CmdBaseNoRepo):
def run(self):
from dvc.cli import get_main_parser

parser = get_main_parser()
shell = self.args.shell
script = shtab.complete(
parser,
shell=shell,
preamble=PREAMBLE[shell],
choice_functions=CHOICE_FUNCTIONS[shell],
)
print(script)
return 0


def add_parser(subparsers, parent_parser):
COMPLETION_HELP = "Generate shell tab completion."
COMPLETION_DESCRIPTION = "Prints out shell tab completion scripts."
completion_parser = subparsers.add_parser(
"completion",
parents=[parent_parser],
description=append_doc_link(COMPLETION_DESCRIPTION, "completion"),
help=COMPLETION_HELP,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
completion_parser.add_argument(
"-s",
"--shell",
help="Shell syntax for completions.",
default="bash",
choices=["bash", "zsh"],
)
completion_parser.set_defaults(func=CmdCompletion)
5 changes: 4 additions & 1 deletion dvc/command/daemon.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from dvc.command import completion
from dvc.command.base import CmdBaseNoRepo, fix_subparsers


Expand Down Expand Up @@ -64,5 +65,7 @@ def add_parser(subparsers, parent_parser):
description=DAEMON_ANALYTICS_HELP,
help=DAEMON_ANALYTICS_HELP,
)
daemon_analytics_parser.add_argument("target", help="Analytics file.")
daemon_analytics_parser.add_argument(
"target", help="Analytics file.", choices=completion.Required.FILE
)
daemon_analytics_parser.set_defaults(func=CmdDaemonAnalytics)
2 changes: 2 additions & 0 deletions dvc/command/data_sync.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import logging

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.command.checkout import log_changes
from dvc.exceptions import CheckoutError, DvcException
Expand Down Expand Up @@ -104,6 +105,7 @@ def shared_parent_parser():
nargs="*",
help="Limit command scope to these DVC-files. "
"Using -R, directories to search DVC-files in can also be given.",
choices=completion.Optional.DVC_FILE,
)

return parent_parser
Expand Down
11 changes: 9 additions & 2 deletions dvc/command/freeze.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import logging

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import DvcException

Expand Down Expand Up @@ -39,7 +40,10 @@ def add_parser(subparsers, parent_parser):
formatter_class=argparse.RawDescriptionHelpFormatter,
)
freeze_parser.add_argument(
"targets", nargs="+", help="DVC-files to freeze."
"targets",
nargs="+",
help="DVC-files to freeze.",
choices=completion.Required.DVC_FILE,
)
freeze_parser.set_defaults(func=CmdFreeze)

Expand All @@ -52,6 +56,9 @@ def add_parser(subparsers, parent_parser):
formatter_class=argparse.RawDescriptionHelpFormatter,
)
unfreeze_parser.add_argument(
"targets", nargs="+", help="DVC-files to unfreeze."
"targets",
nargs="+",
help="DVC-files to unfreeze.",
choices=completion.Required.DVC_FILE,
)
unfreeze_parser.set_defaults(func=CmdUnfreeze)
6 changes: 5 additions & 1 deletion dvc/command/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from dvc.exceptions import DvcException

from . import completion
from .base import CmdBaseNoRepo, append_doc_link

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -62,14 +63,17 @@ def add_parser(subparsers, parent_parser):
"url", help="Location of DVC or Git repository to download from"
)
get_parser.add_argument(
"path", help="Path to a file or directory within the repository"
"path",
help="Path to a file or directory within the repository",
choices=completion.Required.FILE,
)
get_parser.add_argument(
"-o",
"--out",
nargs="?",
help="Destination path to download files to",
metavar="<path>",
choices=completion.Optional.DIR,
)
get_parser.add_argument(
"--rev",
Expand Down
6 changes: 5 additions & 1 deletion dvc/command/get_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from dvc.exceptions import DvcException

from . import completion
from .base import CmdBaseNoRepo, append_doc_link

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -33,6 +34,9 @@ def add_parser(subparsers, parent_parser):
"url", help="See `dvc import-url -h` for full list of supported URLs."
)
get_parser.add_argument(
"out", nargs="?", help="Destination path to put data to."
"out",
nargs="?",
help="Destination path to put data to.",
choices=completion.Optional.DIR,
)
get_parser.set_defaults(func=CmdGetUrl)
6 changes: 5 additions & 1 deletion dvc/command/imp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import logging

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import DvcException

Expand Down Expand Up @@ -43,14 +44,17 @@ def add_parser(subparsers, parent_parser):
"url", help="Location of DVC or Git repository to download from"
)
import_parser.add_argument(
"path", help="Path to a file or directory within the repository"
"path",
help="Path to a file or directory within the repository",
choices=completion.Required.FILE,
)
import_parser.add_argument(
"-o",
"--out",
nargs="?",
help="Destination path to download files to",
metavar="<path>",
choices=completion.Optional.DIR,
)
import_parser.add_argument(
"--rev",
Expand Down
7 changes: 6 additions & 1 deletion dvc/command/imp_url.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import logging

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.exceptions import DvcException

Expand Down Expand Up @@ -54,11 +55,15 @@ def add_parser(subparsers, parent_parser):
"remote://myremote/path/to/file (see `dvc remote`)",
)
import_parser.add_argument(
"out", nargs="?", help="Destination path to put files to."
"out",
nargs="?",
help="Destination path to put files to.",
choices=completion.Optional.DIR,
)
import_parser.add_argument(
"--file",
help="Specify name of the DVC-file this command will generate.",
metavar="<filename>",
choices=completion.Optional.DIR,
)
import_parser.set_defaults(func=CmdImportUrl)
2 changes: 2 additions & 0 deletions dvc/command/ls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import sys

from dvc.command import completion
from dvc.command.base import CmdBaseNoRepo, append_doc_link
from dvc.command.ls.ls_colors import LsColors
from dvc.exceptions import DvcException
Expand Down Expand Up @@ -74,5 +75,6 @@ def add_parser(subparsers, parent_parser):
"path",
nargs="?",
help="Path to directory within the repository to list outputs for",
choices=completion.Optional.DIR,
)
list_parser.set_defaults(func=CmdList)
3 changes: 3 additions & 0 deletions dvc/command/metrics.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import logging

from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link, fix_subparsers
from dvc.exceptions import BadMetricError, DvcException

Expand Down Expand Up @@ -169,6 +170,7 @@ def add_parser(subparsers, parent_parser):
"Limit command scope to these metric files. Using -R, "
"directories to search metric files in can also be given."
),
choices=completion.Optional.FILE,
)
metrics_show_parser.add_argument(
"-a",
Expand Down Expand Up @@ -235,6 +237,7 @@ def add_parser(subparsers, parent_parser):
"directories to search metric files in can also be given."
),
metavar="<paths>",
choices=completion.Optional.FILE,
)
metrics_diff_parser.add_argument(
"-R",
Expand Down
Loading