ui: migrating rest to the ui.write (#6176)

* complete migration to ui.write

* fix small bugs
This commit is contained in:
Saugat Pachhai
2021-06-21 22:14:59 +03:00
committed by GitHub
parent f2998630a3
commit 476af100de
29 changed files with 231 additions and 230 deletions
+5 -2
View File
@@ -3,6 +3,7 @@ import logging
import os
from dvc.command.base import CmdBaseNoRepo, append_doc_link
from dvc.ui import ui
logger = logging.getLogger(__name__)
@@ -71,7 +72,9 @@ class CmdConfig(CmdBaseNoRepo):
prefix = self._config_file_prefix(
self.args.show_origin, self.config, level
)
logger.info("\n".join(self._format_config(conf, prefix)))
configs = list(self._format_config(conf, prefix))
if configs:
ui.write("\n".join(configs))
return 0
@@ -96,7 +99,7 @@ class CmdConfig(CmdBaseNoRepo):
prefix = self._config_file_prefix(
self.args.show_origin, self.config, level
)
logger.info("{}{}".format(prefix, conf[section][opt]))
ui.write(prefix, conf[section][opt], sep="")
break
return 0
+2 -1
View File
@@ -9,10 +9,11 @@ logger = logging.getLogger(__name__)
class CmdDataBase(CmdBase):
def log_summary(self, stats):
from dvc.ui import ui
from dvc.utils.humanize import get_summary
default_msg = "Everything is up to date."
logger.info(get_summary(stats.items()) or default_msg)
ui.write(get_summary(stats.items()) or default_msg)
class CmdDataPull(CmdDataBase):
+2 -2
View File
@@ -1,7 +1,6 @@
import argparse
import logging
from dvc import prompt
from dvc.command.base import CmdBase, append_doc_link
logger = logging.getLogger(__name__)
@@ -10,6 +9,7 @@ logger = logging.getLogger(__name__)
class CmdDestroy(CmdBase):
def run(self):
from dvc.exceptions import DvcException
from dvc.ui import ui
try:
statement = (
@@ -19,7 +19,7 @@ class CmdDestroy(CmdBase):
"Are you sure you want to continue?"
)
if not self.args.force and not prompt.confirm(statement):
if not self.args.force and not ui.confirm(statement):
raise DvcException(
"cannot destroy without a confirmation from the user."
" Use `-f` to force."
+16 -28
View File
@@ -3,10 +3,9 @@ import json
import logging
import os
import colorama
from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.ui import ui
logger = logging.getLogger(__name__)
@@ -18,13 +17,12 @@ def _digest(checksum):
def _show_md(diff, show_hash=False, hide_missing=False):
from dvc.ui import ui
headers = ["Status", "Hash", "Path"] if show_hash else ["Status", "Path"]
rows = []
statuses = ["added", "deleted", "renamed", "modified"]
if not hide_missing:
statuses.append("not in cache")
for status in statuses:
entries = diff.get(status, [])
if not entries:
@@ -44,7 +42,7 @@ def _show_md(diff, show_hash=False, hide_missing=False):
class CmdDiff(CmdBase):
@staticmethod
def _format(diff, hide_missing=False):
def _show_diff(diff, hide_missing=False):
"""
Given a diff structure, generate a string of paths separated
by new lines and grouped together by their state.
@@ -71,15 +69,14 @@ class CmdDiff(CmdBase):
"""
colors = {
"added": colorama.Fore.GREEN,
"modified": colorama.Fore.YELLOW,
"deleted": colorama.Fore.RED,
"renamed": colorama.Fore.GREEN,
"not in cache": colorama.Fore.YELLOW,
"added": "green",
"modified": "yellow",
"deleted": "red",
"renamed": "green",
"not in cache": "yellow",
}
summary = {}
groups = []
states = ["added", "deleted", "renamed", "modified"]
if not hide_missing:
@@ -91,7 +88,8 @@ class CmdDiff(CmdBase):
if not entries:
continue
content = []
header = state.capitalize()
ui.write(f"[{colors[state]}]{header}[/]:", styled=True)
for entry in entries:
path = entry["path"]
@@ -99,7 +97,7 @@ class CmdDiff(CmdBase):
path = f"{path['old']} -> {path['new']}"
checksum = entry.get("hash")
summary[state] += 1 if not path.endswith(os.sep) else 0
content.append(
ui.write(
"{space}{checksum}{separator}{path}".format(
space=" ",
checksum=_digest(checksum) if checksum else "",
@@ -108,14 +106,7 @@ class CmdDiff(CmdBase):
)
)
groups.append(
"{color}{header}{nc}:\n{content}".format(
color=colors[state],
header=state.capitalize(),
nc=colorama.Fore.RESET,
content="\n".join(content),
)
)
ui.write()
if not sum(summary.values()):
return None
@@ -126,9 +117,8 @@ class CmdDiff(CmdBase):
)
if not hide_missing:
fmt += ", {not in cache} not in cache"
groups.append(fmt.format_map(summary))
return "\n\n".join(groups)
ui.write(fmt.format_map(summary))
def run(self):
from dvc.exceptions import DvcException
@@ -155,13 +145,11 @@ class CmdDiff(CmdBase):
diff[key] = entries
if self.args.show_json:
logger.info(json.dumps(diff))
ui.write(json.dumps(diff))
elif self.args.show_md:
logger.info(_show_md(diff, show_hash, hide_missing))
_show_md(diff, show_hash, hide_missing)
elif diff:
output = self._format(diff, hide_missing)
if output:
logger.info(output)
self._show_diff(diff, hide_missing)
except DvcException:
logger.exception("failed to get diff")
+24 -24
View File
@@ -14,6 +14,7 @@ from dvc.command.metrics import DEFAULT_PRECISION
from dvc.command.repro import CmdRepro
from dvc.command.repro import add_arguments as add_repro_arguments
from dvc.exceptions import DvcException, InvalidArgumentError
from dvc.ui import ui
from dvc.utils.flatten import flatten
if TYPE_CHECKING:
@@ -450,7 +451,7 @@ class CmdExperimentsShow(CmdBase):
if self.args.show_json:
import json
logger.info(json.dumps(all_experiments, default=_format_json))
ui.write(json.dumps(all_experiments, default=_format_json))
else:
show_experiments(
all_experiments,
@@ -494,7 +495,7 @@ class CmdExperimentsDiff(CmdBase):
if self.args.show_json:
import json
logger.info(json.dumps(diff))
ui.write(json.dumps(diff))
else:
from dvc.compare import show_diff
@@ -502,8 +503,6 @@ class CmdExperimentsDiff(CmdBase):
diffs = [("metrics", "Metric"), ("params", "Param")]
for idx, (key, title) in enumerate(diffs):
if idx:
from dvc.ui import ui
# we are printing tables even in `--quiet` mode
# so we should also be printing the "table" separator
ui.write(force=True)
@@ -537,7 +536,7 @@ class CmdExperimentsRun(CmdRepro):
)
if self.args.reset:
logger.info("Any existing checkpoints will be reset and re-run.")
ui.write("Any existing checkpoints will be reset and re-run.")
results = self.repo.experiments.run(
name=self.args.name,
@@ -554,7 +553,7 @@ class CmdExperimentsRun(CmdRepro):
if self.args.metrics and results:
metrics = self.repo.metrics.show(revs=list(results))
metrics.pop("workspace", None)
logger.info(show_metrics(metrics))
show_metrics(metrics)
return 0
@@ -608,12 +607,13 @@ class CmdExperimentsGC(CmdRepro):
)
if removed:
logger.info(
f"Removed {removed} experiments. To remove unused cache files "
"use 'dvc gc'."
ui.write(
f"Removed {removed} experiments.",
"To remove unused cache files",
"use 'dvc gc'.",
)
else:
logger.info("No experiments to remove.")
ui.write("No experiments to remove.")
return 0
@@ -662,15 +662,15 @@ class CmdExperimentsPush(CmdBase):
run_cache=self.args.run_cache,
)
logger.info(
"Pushed experiment '%s' to Git remote '%s'.",
self.args.experiment,
self.args.git_remote,
ui.write(
f"Pushed experiment '{self.args.experiment}'"
f"to Git remote '{self.args.git_remote}'."
)
if not self.args.push_cache:
logger.info(
"To push cached outputs for this experiment to DVC remote "
"storage, re-run this command without '--no-cache'."
ui.write(
"To push cached outputs",
"for this experiment to DVC remote storage,"
"re-run this command without '--no-cache'.",
)
return 0
@@ -689,15 +689,15 @@ class CmdExperimentsPull(CmdBase):
run_cache=self.args.run_cache,
)
logger.info(
"Pulled experiment '%s' from Git remote '%s'. ",
self.args.experiment,
self.args.git_remote,
ui.write(
f"Pulled experiment '{self.args.experiment}'",
f"from Git remote '{self.args.git_remote}'.",
)
if not self.args.pull_cache:
logger.info(
"To pull cached outputs for this experiment from DVC remote "
"storage, re-run this command without '--no-cache'."
ui.write(
"To pull cached outputs for this experiment"
"from DVC remote storage,"
"re-run this command without '--no-cache'."
)
return 0
+2 -2
View File
@@ -2,8 +2,8 @@ import argparse
import logging
import os
from dvc import prompt
from dvc.command.base import CmdBase, append_doc_link
from dvc.ui import ui
logger = logging.getLogger(__name__)
@@ -44,7 +44,7 @@ class CmdGC(CmdBase):
logger.warning(msg)
msg = "Are you sure you want to proceed?"
if not self.args.force and not prompt.confirm(msg):
if not self.args.force and not ui.confirm(msg):
return 1
self.repo.gc(
+2 -1
View File
@@ -12,12 +12,13 @@ logger = logging.getLogger(__name__)
class CmdGet(CmdBaseNoRepo):
def _show_url(self):
from dvc.api import get_url
from dvc.ui import ui
try:
url = get_url(
self.args.path, repo=self.args.url, rev=self.args.rev
)
logger.info(url)
ui.write(url, force=True)
except DvcException:
logger.exception("failed to show URL")
return 1
+4 -2
View File
@@ -12,8 +12,10 @@ logger = logging.getLogger(__name__)
def _welcome_message():
from dvc.ui import ui
if analytics.is_enabled():
logger.info(
ui.write(
boxify(
"DVC has enabled anonymous aggregate usage analytics.\n"
"Read the analytics documentation (and how to opt-out) here:\n"
@@ -30,7 +32,7 @@ def _welcome_message():
f"- Star us on GitHub: {fmt_link('https://github.com/iterative/dvc')}"
).format(yellow=colorama.Fore.YELLOW, nc=colorama.Fore.RESET)
logger.info(msg)
ui.write(msg)
class CmdInit(CmdBaseNoRepo):
+2 -4
View File
@@ -1,11 +1,9 @@
import argparse
import logging
import os
from dvc.command import completion
from dvc.command.base import CmdBase, fix_subparsers
logger = logging.getLogger(__name__)
from dvc.ui import ui
class CmdLive(CmdBase):
@@ -17,7 +15,7 @@ class CmdLive(CmdBase):
html_path = self.args.target + ".html"
self.repo.plots.write_html(html_path, plots, metrics)
logger.info(f"\nfile://{os.path.abspath(html_path)}")
ui.write("\nfile://", os.path.abspath(html_path), sep="")
return 0
+3 -2
View File
@@ -4,6 +4,7 @@ import logging
from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link, fix_subparsers
from dvc.exceptions import BadMetricError, DvcException
from dvc.ui import ui
logger = logging.getLogger(__name__)
@@ -32,7 +33,7 @@ class CmdMetricsShow(CmdMetricsBase):
if self.args.show_json:
import json
logger.info(json.dumps(metrics))
ui.write(json.dumps(metrics))
else:
from dvc.compare import show_metrics
@@ -73,7 +74,7 @@ class CmdMetricsDiff(CmdMetricsBase):
if self.args.show_json:
import json
logger.info(json.dumps(diff))
ui.write(json.dumps(diff))
else:
from dvc.compare import show_diff
+2 -1
View File
@@ -4,6 +4,7 @@ import logging
from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link, fix_subparsers
from dvc.exceptions import DvcException
from dvc.ui import ui
logger = logging.getLogger(__name__)
@@ -27,7 +28,7 @@ class CmdParamsDiff(CmdBase):
if self.args.show_json:
import json
logger.info(json.dumps(diff))
ui.write(json.dumps(diff))
else:
from dvc.compare import show_diff
+6 -3
View File
@@ -4,6 +4,7 @@ import logging
from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link, fix_subparsers
from dvc.exceptions import DvcException
from dvc.ui import ui
from dvc.utils import format_link
logger = logging.getLogger(__name__)
@@ -38,7 +39,7 @@ class CmdPlots(CmdBase):
if self.args.show_vega:
target = self.args.targets[0]
logger.info(plots[target])
ui.write(plots[target])
return 0
rel: str = self.args.out or "plots.html"
@@ -53,13 +54,15 @@ class CmdPlots(CmdBase):
assert path.is_absolute() # as_uri throws ValueError if not absolute
url = path.as_uri()
logger.info(url)
ui.write(url)
if self.args.open:
import webbrowser
opened = webbrowser.open(rel)
if not opened:
logger.error("Failed to open. Please try opening it manually.")
ui.error_write(
"Failed to open. Please try opening it manually."
)
return 1
return 0
+4 -6
View File
@@ -1,12 +1,10 @@
import argparse
import logging
from dvc.command.base import append_doc_link, fix_subparsers
from dvc.command.config import CmdConfig
from dvc.ui import ui
from dvc.utils import format_link
logger = logging.getLogger(__name__)
class CmdRemote(CmdConfig):
def __init__(self, args):
@@ -27,7 +25,7 @@ class CmdRemoteAdd(CmdRemote):
from dvc.config import ConfigError
if self.args.default:
logger.info(f"Setting '{self.args.name}' as a default remote.")
ui.write(f"Setting '{self.args.name}' as a default remote.")
with self.config.edit(self.args.level) as conf:
if self.args.name in conf["remote"] and not self.args.force:
@@ -90,7 +88,7 @@ class CmdRemoteDefault(CmdRemote):
try:
print(conf["core"]["remote"])
except KeyError:
logger.info("No default remote set")
ui.write("No default remote set")
return 1
else:
with self.config.edit(self.args.level) as conf:
@@ -116,7 +114,7 @@ class CmdRemoteList(CmdRemote):
def run(self):
conf = self.config.read(self.args.level)
for name, conf in conf["remote"].items():
logger.info("{}\t{}".format(name, conf["url"]))
ui.write(name, conf["url"], sep="\t")
return 0
+4 -5
View File
@@ -1,20 +1,19 @@
import argparse
import logging
from dvc.command import completion
from dvc.command.base import CmdBase, append_doc_link
from dvc.command.status import CmdDataStatus
logger = logging.getLogger(__name__)
class CmdRepro(CmdBase):
def run(self):
from dvc.ui import ui
stages = self.repo.reproduce(**self._repro_kwargs)
if len(stages) == 0:
logger.info(CmdDataStatus.UP_TO_DATE_MSG)
ui.write(CmdDataStatus.UP_TO_DATE_MSG)
else:
logger.info(
ui.write(
"Use `dvc push` to send your updates to " "remote storage."
)
+2 -1
View File
@@ -10,8 +10,9 @@ logger = logging.getLogger(__name__)
class CmdRoot(CmdBaseNoRepo):
def run(self):
from dvc.repo import Repo
from dvc.ui import ui
logger.info(relpath(Repo.find_root()))
ui.write(relpath(Repo.find_root()))
return 0
+5 -5
View File
@@ -2,6 +2,7 @@ import logging
from dvc.command.data_sync import CmdDataBase
from dvc.exceptions import DvcException
from dvc.ui import ui
from dvc.utils import format_link
logger = logging.getLogger(__name__)
@@ -26,7 +27,7 @@ class CmdDataStatus(CmdDataBase):
ind = indent * self.STATUS_INDENT
if isinstance(status, str):
logger.info(f"{ind}{status}")
ui.write(f"{ind}{status}")
return
if isinstance(status, list):
@@ -38,14 +39,13 @@ class CmdDataStatus(CmdDataBase):
for key, value in status.items():
if isinstance(value, str):
logger.info("{}{}{}".format(ind, self._normalize(value), key))
ui.write("{}{}{}".format(ind, self._normalize(value), key))
elif value:
logger.info(f"{ind}{key}:")
ui.write(f"{ind}{key}:")
self._show(value, indent + 1)
def run(self):
from dvc.repo import lock_repo
from dvc.ui import ui
indent = 1 if self.args.cloud else 0
@@ -72,7 +72,7 @@ class CmdDataStatus(CmdDataBase):
if self.args.show_json:
import json
logger.info(json.dumps(st))
ui.write(json.dumps(st))
return 0
if st:
+2 -1
View File
@@ -2,6 +2,7 @@ import argparse
import logging
from dvc.command.base import CmdBaseNoRepo, append_doc_link
from dvc.ui import ui
logger = logging.getLogger(__name__)
@@ -11,7 +12,7 @@ class CmdVersion(CmdBaseNoRepo):
from dvc.info import get_dvc_info
dvc_info = get_dvc_info()
logger.info(dvc_info)
ui.write(dvc_info, force=True)
return 0
+11 -6
View File
@@ -1,5 +1,4 @@
import sys
from collections import defaultdict
from typing import (
TYPE_CHECKING,
Any,
@@ -7,20 +6,21 @@ from typing import (
Iterable,
Optional,
Sequence,
TextIO,
Union,
)
from funcy import cached_property
from dvc.progress import Tqdm
from dvc.utils import colorize
if TYPE_CHECKING:
from dvc.progress import Tqdm
from dvc.ui.table import Headers, Styles, TableData
class Formatter:
def __init__(self, theme: Dict = None, defaults: Dict = None) -> None:
from collections import defaultdict
theme = theme or {
"success": {"color": "green", "style": "bold"},
"warn": {"color": "yellow"},
@@ -29,6 +29,8 @@ class Formatter:
self.theme = defaultdict(lambda: defaults or {}, theme)
def format(self, message: str, style: str = None, **kwargs) -> str:
from dvc.utils import colorize
return colorize(message, **self.theme[style])
@@ -75,6 +77,7 @@ class Console:
stderr: bool = False,
force: bool = False,
styled: bool = False,
file: TextIO = None,
) -> None:
sep = " " if sep is None else sep
end = "\n" if end is None else end
@@ -85,12 +88,14 @@ class Console:
console = self.error_console if stderr else self.rich_console
return console.print(*objects, sep=sep, end=end)
file = sys.stderr if stderr else sys.stdout
file = file or (sys.stderr if stderr else sys.stdout)
values = (self.formatter.format(obj, style=style) for obj in objects)
return print(*values, sep=sep, end=end, file=file)
@staticmethod
def progress(*args, **kwargs) -> Tqdm:
def progress(*args, **kwargs) -> "Tqdm":
from dvc.progress import Tqdm
return Tqdm(*args, **kwargs)
def prompt(
+4 -3
View File
@@ -683,17 +683,18 @@ def test_show_no_repo(tmp_dir):
dvc.plots.show(["metric.json"])
def test_show_from_subdir(tmp_dir, dvc, caplog):
def test_show_from_subdir(tmp_dir, dvc, capsys):
subdir = tmp_dir / "subdir"
subdir.mkdir()
metric = [{"first_val": 100, "val": 2}, {"first_val": 200, "val": 3}]
_write_json(subdir, metric, "metric.json")
with subdir.chdir(), caplog.at_level(logging.INFO, "dvc"):
with subdir.chdir():
assert main(["plots", "show", "metric.json"]) == 0
assert subdir.as_uri() in caplog.text
out, _ = capsys.readouterr()
assert subdir.as_uri() in out
assert (subdir / "plots.html").exists()
+30 -29
View File
@@ -98,7 +98,7 @@ def test_config_set_local(tmp_dir, dvc):
),
],
)
def test_config_get(tmp_dir, dvc, caplog, args, ret, msg):
def test_config_get(tmp_dir, dvc, capsys, caplog, args, ret, msg):
(tmp_dir / ".dvc" / "config").write_text(
textwrap.dedent(
"""\
@@ -123,12 +123,12 @@ def test_config_get(tmp_dir, dvc, caplog, args, ret, msg):
)
)
caplog.clear()
assert main(["config"] + args) == ret
assert msg in caplog.text
text = caplog.text if ret else capsys.readouterr()[0]
assert msg in text
def test_config_list(tmp_dir, dvc, caplog):
def test_config_list(tmp_dir, dvc, capsys):
(tmp_dir / ".dvc" / "config").write_text(
textwrap.dedent(
"""\
@@ -155,17 +155,18 @@ def test_config_list(tmp_dir, dvc, caplog):
)
)
caplog.clear()
assert main(["config", "--list"]) == 0
assert "remote.myremote.url=s3://bucket/path" in caplog.text
assert "remote.myremote.region=us-east-2" in caplog.text
assert "remote.myremote.profile=iterative" in caplog.text
assert "remote.myremote.access_key_id=abcde" in caplog.text
assert "remote.myremote.secret_access_key=123456" in caplog.text
assert "remote.other.url=gs://bucket/path" in caplog.text
assert "core.analytics=False" in caplog.text
assert "core.no_scm=true" in caplog.text
assert "core.remote=myremote" in caplog.text
out, _ = capsys.readouterr()
assert "remote.myremote.url=s3://bucket/path" in out
assert "remote.myremote.region=us-east-2" in out
assert "remote.myremote.profile=iterative" in out
assert "remote.myremote.access_key_id=abcde" in out
assert "remote.myremote.secret_access_key=123456" in out
assert "remote.other.url=gs://bucket/path" in out
assert "core.analytics=False" in out
assert "core.no_scm=true" in out
assert "core.remote=myremote" in out
@pytest.mark.parametrize(
@@ -241,57 +242,56 @@ def test_load_relative_paths(dvc, field, remote_url):
)
def test_config_remote(tmp_dir, dvc, caplog):
def test_config_remote(tmp_dir, dvc, capsys):
(tmp_dir / ".dvc" / "config").write_text(
"['remote \"myremote\"']\n"
" url = s3://bucket/path\n"
" region = myregion\n"
)
caplog.clear()
assert main(["config", "remote.myremote.url"]) == 0
assert "s3://bucket/path" in caplog.text
out, _ = capsys.readouterr()
assert "s3://bucket/path" in out
caplog.clear()
assert main(["config", "remote.myremote.region"]) == 0
assert "myregion" in caplog.text
out, _ = capsys.readouterr()
assert "myregion" in out
def test_config_show_origin_single(tmp_dir, dvc, caplog):
def test_config_show_origin_single(tmp_dir, dvc, capsys):
(tmp_dir / ".dvc" / "config").write_text(
"['remote \"myremote\"']\n"
" url = s3://bucket/path\n"
" region = myregion\n"
)
caplog.clear()
assert (
main(["config", "--show-origin", "--project", "remote.myremote.url"])
== 0
)
out, _ = capsys.readouterr()
assert (
"{}\t{}\n".format(os.path.join(".dvc", "config"), "s3://bucket/path")
in caplog.text
in out
)
caplog.clear()
assert (
main(["config", "--show-origin", "--local", "remote.myremote.url"])
== 251
)
caplog.clear()
assert main(["config", "--list", "--project", "--show-origin"]) == 0
out, _ = capsys.readouterr()
assert (
"{}\t{}\n".format(
os.path.join(".dvc", "config"),
"remote.myremote.url=s3://bucket/path",
)
in caplog.text
in out
)
def test_config_show_origin_merged(tmp_dir, dvc, caplog):
def test_config_show_origin_merged(tmp_dir, dvc, capsys):
(tmp_dir / ".dvc" / "config").write_text(
"['remote \"myremote\"']\n"
" url = s3://bucket/path\n"
@@ -302,18 +302,19 @@ def test_config_show_origin_merged(tmp_dir, dvc, caplog):
"['remote \"myremote\"']\n timeout = 100\n"
)
caplog.clear()
assert main(["config", "--list", "--show-origin"]) == 0
out, _ = capsys.readouterr()
assert (
"{}\t{}\n".format(
os.path.join(".dvc", "config"),
"remote.myremote.url=s3://bucket/path",
)
in caplog.text
in out
)
assert (
"{}\t{}\n".format(
os.path.join(".dvc", "config.local"), "remote.myremote.timeout=100"
)
in caplog.text
in out
)
+17 -17
View File
@@ -475,13 +475,12 @@ def test_pipeline_file_target_ops(tmp_dir, dvc, run_copy, local_remote):
({}, "Everything is up to date"),
],
)
def test_push_stats(tmp_dir, dvc, fs, msg, caplog, local_remote):
def test_push_stats(tmp_dir, dvc, fs, msg, capsys, local_remote):
tmp_dir.dvc_gen(fs)
caplog.clear()
with caplog.at_level(level=logging.INFO, logger="dvc"):
main(["push"])
assert msg in caplog.text
main(["push"])
out, _ = capsys.readouterr()
assert msg in out
@pytest.mark.parametrize(
@@ -492,17 +491,17 @@ def test_push_stats(tmp_dir, dvc, fs, msg, caplog, local_remote):
({}, "Everything is up to date."),
],
)
def test_fetch_stats(tmp_dir, dvc, fs, msg, caplog, local_remote):
def test_fetch_stats(tmp_dir, dvc, fs, msg, capsys, local_remote):
tmp_dir.dvc_gen(fs)
dvc.push()
clean(list(fs.keys()), dvc)
caplog.clear()
with caplog.at_level(level=logging.INFO, logger="dvc"):
main(["fetch"])
assert msg in caplog.text
main(["fetch"])
out, _ = capsys.readouterr()
assert msg in out
def test_pull_stats(tmp_dir, dvc, capsys, caplog, local_remote):
def test_pull_stats(tmp_dir, dvc, capsys, local_remote):
tmp_dir.dvc_gen({"foo": "foo", "bar": "bar"})
dvc.push()
clean(["foo", "bar"], dvc)
@@ -513,12 +512,13 @@ def test_pull_stats(tmp_dir, dvc, capsys, caplog, local_remote):
out, _ = capsys.readouterr()
assert "M\tbar".expandtabs() in out
assert "A\tfoo".expandtabs() in out
assert "2 files fetched" in caplog.text
assert "1 file added" in caplog.text
assert "1 file modified" in caplog.text
with caplog.at_level(level=logging.INFO, logger="dvc"):
main(["pull"])
assert "Everything is up to date." in caplog.text
assert "2 files fetched" in out
assert "1 file added" in out
assert "1 file modified" in out
main(["pull"])
out, _ = capsys.readouterr()
assert "Everything is up to date." in out
@pytest.mark.parametrize(
+4 -4
View File
@@ -1,13 +1,13 @@
from dvc.main import main
def test_root(tmp_dir, dvc, caplog):
def test_root(tmp_dir, dvc, capsys):
assert main(["root"]) == 0
assert ".\n" in caplog.text
assert "." in capsys.readouterr()[0]
def test_root_locked(tmp_dir, dvc, caplog):
def test_root_locked(tmp_dir, dvc, capsys):
# NOTE: check that `dvc root` is not blocked with dvc lock
with dvc.lock:
assert main(["root"]) == 0
assert ".\n" in caplog.text
assert "." in capsys.readouterr()[0]
+9 -8
View File
@@ -4,13 +4,14 @@ from dvc.main import main
from tests.unit.test_info import PYTHON_VERSION_REGEX
def test_(tmp_dir, dvc, scm, caplog):
def test_(tmp_dir, dvc, scm, capsys):
assert main(["version"]) == 0
assert re.search(r"DVC version: \d+\.\d+\.\d+.*", caplog.text)
assert re.search(f"Platform: {PYTHON_VERSION_REGEX} on .*", caplog.text)
assert re.search(r"Supports: .*", caplog.text)
assert re.search(r"Cache types: .*", caplog.text)
assert re.search(r"Caches: local", caplog.text)
assert re.search(r"Remotes: None", caplog.text)
assert "Repo: dvc, git" in caplog.text
out, _ = capsys.readouterr()
assert re.search(r"DVC version: \d+\.\d+\.\d+.*", out)
assert re.search(f"Platform: {PYTHON_VERSION_REGEX} on .*", out)
assert re.search(r"Supports: .*", out)
assert re.search(r"Cache types: .*", out)
assert re.search(r"Caches: local", out)
assert re.search(r"Remotes: None", out)
assert "Repo: dvc, git" in out
+36 -41
View File
@@ -1,5 +1,4 @@
import collections
import logging
import os
import mock
@@ -21,7 +20,7 @@ def test_digest(checksum, expected):
assert expected == _digest(checksum)
def test_default(mocker, caplog):
def test_default(mocker, capsys):
args = parse_args(["diff"])
cmd = args.func(args)
diff = {
@@ -51,10 +50,10 @@ def test_default(mocker, caplog):
"\n"
"files summary: 1 added, 0 deleted, "
"1 renamed, 0 modified, 0 not in cache"
).format(sep=os.path.sep) in caplog.text
).format(sep=os.path.sep) in capsys.readouterr()[0]
def test_show_hash(mocker, caplog):
def test_show_hash(mocker, capsys):
args = parse_args(["diff", "--show-hash"])
cmd = args.func(args)
diff = {
@@ -81,6 +80,8 @@ def test_show_hash(mocker, caplog):
}
mocker.patch("dvc.repo.Repo.diff", return_value=diff)
assert 0 == cmd.run()
out, _ = capsys.readouterr()
assert (
"Deleted:\n"
" XXXXXXXX " + os.path.join("data", "") + "\n"
@@ -100,10 +101,10 @@ def test_show_hash(mocker, caplog):
"\n"
"files summary: 0 added, 2 deleted, "
"1 renamed, 2 modified, 0 not in cache"
) in caplog.text
) in out
def test_show_json(mocker, caplog):
def test_show_json(mocker, capsys):
args = parse_args(["diff", "--show-json"])
cmd = args.func(args)
diff = {
@@ -118,13 +119,14 @@ def test_show_json(mocker, caplog):
mocker.patch("dvc.repo.Repo.diff", return_value=diff)
assert 0 == cmd.run()
assert '"added": [{"path": "file1"}, {"path": "file2"}]' in caplog.text
assert '"deleted": []' in caplog.text
assert '"modified": []' in caplog.text
assert '"not in cache": []' in caplog.text
out, _ = capsys.readouterr()
assert '"added": [{"path": "file1"}, {"path": "file2"}]' in out
assert '"deleted": []' in out
assert '"modified": []' in out
assert '"not in cache": []' in out
def test_show_json_and_hash(mocker, caplog):
def test_show_json_and_hash(mocker, capsys):
args = parse_args(["diff", "--show-json", "--show-hash"])
cmd = args.func(args)
@@ -147,20 +149,21 @@ def test_show_json_and_hash(mocker, caplog):
mocker.patch("dvc.repo.Repo.diff", return_value=diff)
assert 0 == cmd.run()
out, _ = capsys.readouterr()
assert (
'"added": [{"path": "file1", "hash": "11111111"}, '
'{"path": "file2", "hash": "22222222"}]' in caplog.text
'{"path": "file2", "hash": "22222222"}]' in out
)
assert '"deleted": []' in caplog.text
assert '"modified": []' in caplog.text
assert '"deleted": []' in out
assert '"modified": []' in out
assert (
'"renamed": [{"path": {"old": "file_old", '
'"new": "file_new"}, "hash": "11111111"}]' in caplog.text
'"new": "file_new"}, "hash": "11111111"}]' in out
)
assert '"not in cache": []' in caplog.text
assert '"not in cache": []' in out
def test_show_json_hide_missing(mocker, caplog):
def test_show_json_hide_missing(mocker, capsys):
args = parse_args(["diff", "--show-json", "--hide-missing"])
cmd = args.func(args)
diff = {
@@ -181,19 +184,17 @@ def test_show_json_hide_missing(mocker, caplog):
mocker.patch("dvc.repo.Repo.diff", return_value=diff)
assert 0 == cmd.run()
assert '"added": [{"path": "file1"}, {"path": "file2"}]' in caplog.text
assert '"deleted": []' in caplog.text
assert (
'"renamed": [{"path": {"old": "file_old", "new": "file_new"}'
in caplog.text
)
assert '"modified": []' in caplog.text
assert '"not in cache": []' not in caplog.text
out, _ = capsys.readouterr()
assert '"added": [{"path": "file1"}, {"path": "file2"}]' in out
assert '"deleted": []' in out
assert '"renamed": [{"path": {"old": "file_old", "new": "file_new"}' in out
assert '"modified": []' in out
assert '"not in cache": []' not in out
@pytest.mark.parametrize("show_hash", [None, True, False])
@mock.patch("dvc.command.diff._show_md")
def test_diff_show_md_and_hash(mock_show_md, mocker, caplog, show_hash):
def test_diff_show_md_and_hash(mock_show_md, mocker, show_hash):
options = ["diff", "--show-md"] + (["--show-hash"] if show_hash else [])
args = parse_args(options)
cmd = args.func(args)
@@ -206,27 +207,20 @@ def test_diff_show_md_and_hash(mock_show_md, mocker, caplog, show_hash):
mock_show_md.assert_called_once_with(diff, show_hash, False)
def test_no_changes(mocker, caplog):
def test_no_changes(mocker, capsys):
args = parse_args(["diff", "--show-json"])
cmd = args.func(args)
mocker.patch("dvc.repo.Repo.diff", return_value={})
def info():
return [
msg
for name, level, msg in caplog.record_tuples
if name.startswith("dvc") and level == logging.INFO
]
assert 0 == cmd.run()
assert ["{}"] == info()
caplog.clear()
out, _ = capsys.readouterr()
assert "{}" in out
args = parse_args(["diff"])
cmd = args.func(args)
assert 0 == cmd.run()
assert not info()
out, _ = capsys.readouterr()
assert not out
def test_show_md(capsys):
@@ -330,7 +324,7 @@ def test_show_md_hide_missing(capsys):
).format(sep=os.path.sep)
def test_hide_missing(mocker, caplog):
def test_hide_missing(mocker, capsys):
args = parse_args(["diff", "--hide-missing"])
cmd = args.func(args)
diff = {
@@ -348,6 +342,7 @@ def test_hide_missing(mocker, caplog):
mocker.patch("dvc.repo.Repo.diff", return_value=diff)
assert 0 == cmd.run()
out, _ = capsys.readouterr()
assert (
"Added:\n"
" file\n"
@@ -356,5 +351,5 @@ def test_hide_missing(mocker, caplog):
" file_old -> file_new\n"
"\n"
"files summary: 1 added, 0 deleted, 1 renamed, 0 modified"
) in caplog.text
assert "not in cache" not in caplog.text
) in out
assert "not in cache" not in out
+3 -2
View File
@@ -28,7 +28,7 @@ def test_get(mocker):
)
def test_get_url(mocker, caplog):
def test_get_url(mocker, capsys):
cli_args = parse_args(
["get", "repo_url", "src", "--rev", "version", "--show-url"]
)
@@ -38,6 +38,7 @@ def test_get_url(mocker, caplog):
m = mocker.patch("dvc.api.get_url", return_value="resource_url")
assert cmd.run() == 0
assert "resource_url" in caplog.text
out, _ = capsys.readouterr()
assert "resource_url" in out
m.assert_called_once_with("src", repo="repo_url", rev="version")
+6 -7
View File
@@ -50,7 +50,7 @@ def test_metrics_diff(dvc, mocker, capsys):
)
def test_metrics_diff_json(dvc, mocker, caplog, capsys):
def test_metrics_diff_json(dvc, mocker, capsys):
cli_args = parse_args(
[
"metrics",
@@ -79,6 +79,7 @@ def test_metrics_diff_json(dvc, mocker, caplog, capsys):
show_diff_mock = mocker.patch("dvc.compare.show_diff")
assert cmd.run() == 0
out, _ = capsys.readouterr()
metrics_diff.assert_called_once_with(
cmd.repo,
targets=["target1", "target2"],
@@ -88,8 +89,7 @@ def test_metrics_diff_json(dvc, mocker, caplog, capsys):
all=True,
)
show_diff_mock.assert_not_called()
assert json.dumps(diff) in caplog.text
assert capsys.readouterr() == ("", "")
assert json.dumps(diff) in out
def test_metrics_show(dvc, mocker):
@@ -134,7 +134,7 @@ def test_metrics_show(dvc, mocker):
)
def test_metrics_show_json(dvc, mocker, caplog, capsys):
def test_metrics_show_json(dvc, mocker, capsys):
cli_args = parse_args(
[
"metrics",
@@ -161,7 +161,7 @@ def test_metrics_show_json(dvc, mocker, caplog, capsys):
show_metrics_mock = mocker.patch("dvc.compare.show_metrics")
assert cmd.run() == 0
out, _ = capsys.readouterr()
metrics_show.assert_called_once_with(
cmd.repo,
["target1", "target2"],
@@ -171,5 +171,4 @@ def test_metrics_show_json(dvc, mocker, caplog, capsys):
all_commits=True,
)
show_metrics_mock.assert_not_called()
assert json.dumps(d) in caplog.text
assert capsys.readouterr() == ("", "")
assert json.dumps(d) in out
+4 -8
View File
@@ -1,5 +1,3 @@
import logging
from dvc.cli import parse_args
from dvc.command.params import CmdParamsDiff
@@ -57,7 +55,7 @@ def test_params_diff_from_cli(dvc, mocker):
)
def test_params_diff_show_json(dvc, mocker, caplog, capsys):
def test_params_diff_show_json(dvc, mocker, capsys):
cli_args = parse_args(
["params", "diff", "HEAD~10", "HEAD~1", "--show-json"]
)
@@ -67,9 +65,7 @@ def test_params_diff_show_json(dvc, mocker, caplog, capsys):
)
show_diff_mock = mocker.patch("dvc.compare.show_diff")
with caplog.at_level(logging.INFO, logger="dvc"):
assert cmd.run() == 0
assert '{"params.yaml": {"a": "b"}}\n' in caplog.text
assert cmd.run() == 0
out, _ = capsys.readouterr()
assert '{"params.yaml": {"a": "b"}}\n' in out
show_diff_mock.assert_not_called()
assert capsys.readouterr() == ("", "")
+16 -12
View File
@@ -1,4 +1,3 @@
import logging
import os
import posixpath
@@ -91,7 +90,7 @@ def test_plots_show_vega(dvc, mocker):
)
def test_plots_diff_vega(dvc, mocker, caplog):
def test_plots_diff_vega(dvc, mocker, capsys):
cli_args = parse_args(
[
"plots",
@@ -108,10 +107,12 @@ def test_plots_diff_vega(dvc, mocker, caplog):
"dvc.repo.plots.diff.diff", return_value={"plots.csv": "plothtml"}
)
assert cmd.run() == 0
assert "plothtml" in caplog.text
out, _ = capsys.readouterr()
assert "plothtml" in out
def test_plots_diff_open(tmp_dir, dvc, mocker, caplog):
def test_plots_diff_open(tmp_dir, dvc, mocker, capsys):
mocked_open = mocker.patch("webbrowser.open", return_value=True)
cli_args = parse_args(["plots", "diff", "--targets", "datafile", "--open"])
cmd = cli_args.func(cli_args)
@@ -123,10 +124,12 @@ def test_plots_diff_open(tmp_dir, dvc, mocker, caplog):
mocked_open.assert_called_once_with("plots.html")
expected_url = posixpath.join(tmp_dir.as_uri(), "plots.html")
assert expected_url in caplog.text
out, _ = capsys.readouterr()
assert expected_url in out
def test_plots_diff_open_failed(tmp_dir, dvc, mocker, caplog):
def test_plots_diff_open_failed(tmp_dir, dvc, mocker, capsys):
mocked_open = mocker.patch("webbrowser.open", return_value=False)
cli_args = parse_args(["plots", "diff", "--targets", "datafile", "--open"])
cmd = cli_args.func(cli_args)
@@ -140,10 +143,9 @@ def test_plots_diff_open_failed(tmp_dir, dvc, mocker, caplog):
error_message = "Failed to open. Please try opening it manually."
expected_url = posixpath.join(tmp_dir.as_uri(), "plots.html")
assert caplog.record_tuples == [
("dvc.command.plots", logging.INFO, expected_url),
("dvc.command.plots", logging.ERROR, error_message),
]
out, err = capsys.readouterr()
assert expected_url in out
assert error_message in err
@pytest.mark.parametrize(
@@ -155,7 +157,7 @@ def test_plots_diff_open_failed(tmp_dir, dvc, mocker, caplog):
ids=["quote", "resolve"],
)
def test_plots_path_is_quoted_and_resolved_properly(
tmp_dir, dvc, mocker, caplog, output, expected_url_path
tmp_dir, dvc, mocker, capsys, output, expected_url_path
):
cli_args = parse_args(
["plots", "diff", "--targets", "datafile", "--out", output]
@@ -167,4 +169,6 @@ def test_plots_path_is_quoted_and_resolved_properly(
assert cmd.run() == 0
expected_url = posixpath.join(tmp_dir.as_uri(), expected_url_path)
assert expected_url in caplog.text
out, _ = capsys.readouterr()
assert expected_url in out
+4 -3
View File
@@ -45,16 +45,17 @@ def test_cloud_status(tmp_dir, dvc, mocker):
@pytest.mark.parametrize("status", [{}, {"a": "b", "c": [1, 2, 3]}, [1, 2, 3]])
def test_status_show_json(dvc, mocker, caplog, status):
def test_status_show_json(dvc, mocker, capsys, status):
cli_args = parse_args(["status", "--show-json"])
assert cli_args.func == CmdDataStatus
cmd = cli_args.func(cli_args)
mocker.patch.object(cmd.repo, "status", autospec=True, return_value=status)
caplog.clear()
assert cmd.run() == 0
assert caplog.messages == [json.dumps(status)]
out, _ = capsys.readouterr()
assert json.dumps(status) in out
@pytest.mark.parametrize(