Repository: iterative/dvc

Issue:
plots diff/show: configure --open flag
Enable configuration of `dvc plots diff/show --open` flag at the project level.


Discussion:
I'd prefer it to be opened directly if it can and is a tty.

Resolving patch:
diff --git a/dvc/command/plots.py b/dvc/command/plots.py
--- a/dvc/command/plots.py
+++ b/dvc/command/plots.py
@@ -94,8 +94,14 @@ def run(self):
             )
 
             ui.write(index_path.as_uri())
-
-            if self.args.open:
+            auto_open = self.repo.config["plots"].get("auto_open", False)
+            if self.args.open or auto_open:
+                if not auto_open:
+                    ui.write(
+                        "To enable auto opening, you can run:\n"
+                        "\n"
+                        "\tdvc config plots.auto_open true"
+                    )
                 return ui.open_browser(index_path)
 
             return 0
diff --git a/dvc/config_schema.py b/dvc/config_schema.py
--- a/dvc/config_schema.py
+++ b/dvc/config_schema.py
@@ -256,7 +256,10 @@ class RelPath(str):
         # enabled by default. It's of no use, kept for backward compatibility.
         Optional("parametrization", default=True): Bool,
     },
-    "plots": {"html_template": str},
+    "plots": {
+        "html_template": str,
+        Optional("auto_open", default=False): Bool,
+    },
     "exp": {
         "code": str,
         "data": str,
diff --git a/dvc/repo/live.py b/dvc/repo/live.py
--- a/dvc/repo/live.py
+++ b/dvc/repo/live.py
@@ -20,7 +20,6 @@ def webbrowser_open(url: str) -> int:
 
 
 def create_summary(out):
-
     assert out.live and out.live["html"]
 
     metrics, plots = out.repo.live.show(out.fs_path)
@@ -31,8 +30,8 @@ def create_summary(out):
     index_path = render(
         out.repo, renderers, metrics=metrics, path=html_path, refresh_seconds=5
     )
-
-    webbrowser_open(index_path)
+    if out.repo.config["plots"].get("auto_open", False):
+        webbrowser_open(index_path)
 
 
 def summary_fs_path(out: "Output") -> Optional[str]:


Test patch:
diff --git a/tests/func/test_live.py b/tests/func/test_live.py
--- a/tests/func/test_live.py
+++ b/tests/func/test_live.py
@@ -241,7 +241,14 @@ def test_live_checkpoints_resume(
     assert checkpoints_metric(results, "logs.json", "metric2") == [8, 6, 4, 2]
 
 
-def test_dvc_generates_html_during_run(tmp_dir, dvc, mocker, live_stage):
+@pytest.mark.parametrize("auto_open", [False, True])
+def test_dvc_generates_html_during_run(
+    tmp_dir, dvc, mocker, live_stage, auto_open
+):
+    if auto_open:
+        with dvc.config.edit() as conf:
+            conf["plots"]["auto_open"] = True
+
     show_spy = mocker.spy(dvc.live, "show")
     webbrowser_open = mocker.patch("dvc.repo.live.webbrowser_open")
 
@@ -265,7 +272,7 @@ def test_dvc_generates_html_during_run(tmp_dir, dvc, mocker, live_stage):
     live_stage(summary=True, live="logs", code=script)
 
     assert show_spy.call_count == 2
-    assert webbrowser_open.call_count == 2
+    assert webbrowser_open.call_count == (2 if auto_open else 0)
 
 
 def test_dvclive_stage_with_different_wdir(tmp_dir, scm, dvc):
diff --git a/tests/unit/command/test_plots.py b/tests/unit/command/test_plots.py
--- a/tests/unit/command/test_plots.py
+++ b/tests/unit/command/test_plots.py
@@ -138,11 +138,19 @@ def test_plots_diff_vega(dvc, mocker, capsys, plots_data):
     render_mock.assert_not_called()
 
 
-def test_plots_diff_open(tmp_dir, dvc, mocker, capsys, plots_data):
+@pytest.mark.parametrize("auto_open", [True, False])
+def test_plots_diff_open(tmp_dir, dvc, mocker, capsys, plots_data, auto_open):
     mocked_open = mocker.patch("webbrowser.open", return_value=True)
-    cli_args = parse_args(
-        ["plots", "diff", "--targets", "plots.csv", "--open"]
-    )
+
+    args = ["plots", "diff", "--targets", "plots.csv"]
+
+    if auto_open:
+        with dvc.config.edit() as conf:
+            conf["plots"]["auto_open"] = True
+    else:
+        args.append("--open")
+
+    cli_args = parse_args(args)
     cmd = cli_args.func(cli_args)
     mocker.patch("dvc.repo.plots.diff.diff", return_value=plots_data)