Skip to content

Commit

Permalink
cli: config: add support for --show-origin (iterative#5126)
Browse files Browse the repository at this point in the history
* cli: config: add support for --show-origin

Support the --show-origin option for config, which, similar to git,
prefixes each config option with the source file it originated from.

Fixes iterative#5119

* Reformat with black.

* Simplify logic for local config files.

* Add test for --show-config output.

* Update tests/func/test_config.py

Co-authored-by: Ruslan Kuprieiev <[email protected]>
  • Loading branch information
mrstegeman and efiop authored Dec 30, 2020
1 parent 23811e0 commit 34ed545
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 4 deletions.
44 changes: 40 additions & 4 deletions dvc/command/config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import argparse
import logging
import os

from dvc.command.base import CmdBaseNoRepo, append_doc_link
from dvc.config import Config, ConfigError
from dvc.repo import Repo
from dvc.utils.flatten import flatten

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -34,6 +36,14 @@ def __init__(self, args):
self.config = Config(validate=False)

def run(self):
if self.args.show_origin:
if any((self.args.value, self.args.unset)):
logger.error(
"--show-origin can't be used together with any of these "
"options: -u/--unset, value"
)
return 1

if self.args.list:
if any((self.args.name, self.args.value, self.args.unset)):
logger.error(
Expand All @@ -43,7 +53,11 @@ def run(self):
return 1

conf = self.config.load_one(self.args.level)
logger.info("\n".join(self._format_config(conf)))
prefix = self._config_file_prefix(
self.args.show_origin, self.config, self.args.level
)

logger.info("\n".join(self._format_config(conf, prefix)))
return 0

if self.args.name is None:
Expand All @@ -54,10 +68,14 @@ def run(self):

if self.args.value is None and not self.args.unset:
conf = self.config.load_one(self.args.level)
prefix = self._config_file_prefix(
self.args.show_origin, self.config, self.args.level
)

if remote:
conf = conf["remote"]
self._check(conf, remote, section, opt)
logger.info(conf[section][opt])
logger.info("{}{}".format(prefix, conf[section][opt]))
return 0

with self.config.edit(self.args.level) as conf:
Expand Down Expand Up @@ -90,9 +108,21 @@ def _check(self, conf, remote, section, opt=None):
)

@staticmethod
def _format_config(config):
def _format_config(config, prefix=""):
for key, value in flatten(config).items():
yield f"{key}={value}"
yield f"{prefix}{key}={value}"

@staticmethod
def _config_file_prefix(show_origin, config, level):
if not show_origin:
return ""

fname = config.files[level]

if level in ["local", "repo"]:
fname = os.path.relpath(fname, start=Repo.find_root())

return fname + "\t"


parent_config_parser = argparse.ArgumentParser(add_help=False)
Expand Down Expand Up @@ -152,4 +182,10 @@ def add_parser(subparsers, parent_parser):
action="store_true",
help="List all defined config values.",
)
config_parser.add_argument(
"--show-origin",
default=False,
action="store_true",
help="Show the source file containing each config value.",
)
config_parser.set_defaults(func=CmdConfig)
37 changes: 37 additions & 0 deletions tests/func/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,15 @@ def _do_test(self, local=False):
self.assertEqual(ret, 0)
self.assertTrue(self._contains(section, field, value, local))

ret = main(base + [section_field, value, "--show-origin"])
self.assertEqual(ret, 1)

ret = main(base + [section_field])
self.assertEqual(ret, 0)

ret = main(base + ["--show-origin", section_field])
self.assertEqual(ret, 0)

ret = main(base + [section_field, newvalue])
self.assertEqual(ret, 0)
self.assertTrue(self._contains(section, field, newvalue, local))
Expand All @@ -60,9 +66,15 @@ def _do_test(self, local=False):
self.assertEqual(ret, 0)
self.assertFalse(self._contains(section, field, value, local))

ret = main(base + [section_field, "--unset", "--show-origin"])
self.assertEqual(ret, 1)

ret = main(base + ["--list"])
self.assertEqual(ret, 0)

ret = main(base + ["--list", "--show-origin"])
self.assertEqual(ret, 0)

def test(self):
self._do_test(False)

Expand Down Expand Up @@ -174,3 +186,28 @@ def test_config_remote(tmp_dir, dvc, caplog):
caplog.clear()
assert main(["config", "remote.myremote.region"]) == 0
assert "myregion" in caplog.text


def test_config_show_origin(tmp_dir, dvc, caplog):
(tmp_dir / ".dvc" / "config").write_text(
"['remote \"myremote\"']\n"
" url = s3://bucket/path\n"
" region = myregion\n"
)

caplog.clear()
assert main(["config", "--show-origin", "remote.myremote.url"]) == 0
assert (
"{}\t{}\n".format(os.path.join(".dvc", "config"), "s3://bucket/path")
in caplog.text
)

caplog.clear()
assert main(["config", "--list", "--show-origin"]) == 0
assert (
"{}\t{}\n".format(
os.path.join(".dvc", "config"),
"remote.myremote.url=s3://bucket/path",
)
in caplog.text
)

0 comments on commit 34ed545

Please sign in to comment.