Repository: dask/dask
Pull request #9936 (2023-02-10 01:49:28)

Add a CLI command to `list` and `get` a value from dask config
Adds two cli commands, `git config get` to get a value from dask config:

```yaml
> dask config get distributed.scheduler.dashboard
bokeh-application:
  allow_websocket_origin:
  - '*'
  check_unused_sessions_milliseconds: 500
  keep_alive_milliseconds: 500
status:
  task-stream-length: 1000
tasks:
  task-stream-length: 100000
tls:
  ca-file: null
  cert: null
  key: null
```

or `git config list` to print the whole config:

```yaml
> dask config list
array:
  backend: numpy
  slicing:
    split-large-chunks: null
  svg:
    size: 120
coiled:
...
```

Partially implements #9746.

- [x] Tests added / passed
- [x] Passes `pre-commit run --all-files`


j-bennet: cc @ntabris 

Patch:
diff --git a/dask/cli.py b/dask/cli.py
index 922cfabf9..21eda994c 100644
--- a/dask/cli.py
+++ b/dask/cli.py
@@ -1,8 +1,11 @@
 import warnings
+from functools import reduce
 
 import click
 import importlib_metadata
+from yaml import dump
 
+import dask
 from dask import __version__
 
 CONTEXT_SETTINGS = {
@@ -40,6 +43,42 @@ def versions():
     show_versions()
 
 
+@cli.group()
+def config():
+    """Dask config settings"""
+    pass
+
+
+@config.command(name="get")
+@click.argument("key", default=None, required=False)
+def config_get(key=None):
+    """Print config key, or the whole config."""
+    if key in (None, ""):
+        click.echo(
+            click.style(
+                """Config key not specified. Are you looking for "dask config list"?"""
+            ),
+            err=True,
+        )
+        exit(1)
+    else:
+        try:
+            data = reduce(lambda d, k: d[k], key.split("."), dask.config.config)
+            if isinstance(data, (list, dict)):
+                click.echo_via_pager(dump(data))
+            else:
+                click.echo(data)
+        except KeyError:
+            click.echo(click.style(f"Section not found: {key}", fg="red"), err=True)
+            exit(1)
+
+
+@config.command(name="list")
+def config_list():
+    """Print the whole config."""
+    click.echo_via_pager(dump(dask.config.config))
+
+
 def _register_command_ep(interface, entry_point):
     """Add `entry_point` command to `interface`.
 


Test patch:
diff --git a/dask/tests/test_cli.py b/dask/tests/test_cli.py
index 112978fc0..b94762c90 100644
--- a/dask/tests/test_cli.py
+++ b/dask/tests/test_cli.py
@@ -11,6 +11,34 @@ import dask
 import dask.cli
 
 
+def test_config_get():
+    runner = CliRunner()
+    result = runner.invoke(dask.cli.config_get)
+    assert result.exit_code == 1
+    assert result.output.startswith("Config key not specified")
+
+
+def test_config_get_value():
+    runner = CliRunner()
+    result = runner.invoke(dask.cli.config_get, ["array"])
+    assert result.exit_code == 0
+    assert result.output.startswith("backend:")
+
+
+def test_config_get_bad_value():
+    runner = CliRunner()
+    result = runner.invoke(dask.cli.config_get, ["bad_key"])
+    assert result.exit_code != 0
+    assert result.output.startswith("Section not found")
+
+
+def test_config_list():
+    runner = CliRunner()
+    result = runner.invoke(dask.cli.config_list)
+    assert result.exit_code == 0
+    assert result.output.startswith("array:")
+
+
 def test_version():
     runner = CliRunner()
     result = runner.invoke(dask.cli.cli, ["--version"])