cli: config: add support for --show-origin (#5126)

* 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 #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]>
This commit is contained in:
Michael Stegeman
2020-12-30 21:56:20 +02:00
committed by GitHub
co-authored by Ruslan Kuprieiev
parent 23811e028c
commit 34ed545d64
2 changed files with 77 additions and 4 deletions
+40 -4
View File
@@ -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__)
@@ -34,6 +36,14 @@ class CmdConfig(CmdBaseNoRepo):
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(
@@ -43,7 +53,11 @@ class CmdConfig(CmdBaseNoRepo):
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:
@@ -54,10 +68,14 @@ class CmdConfig(CmdBaseNoRepo):
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:
@@ -90,9 +108,21 @@ class CmdConfig(CmdBaseNoRepo):
)
@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)
@@ -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
View File
@@ -48,9 +48,15 @@ class TestConfigCLI(TestDvc):
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))
@@ -60,9 +66,15 @@ class TestConfigCLI(TestDvc):
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)
@@ -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
)