aboutsummaryrefslogtreecommitdiff
path: root/prometheus_borgmatic_exporter/cli.py
diff options
context:
space:
mode:
authorDennis Fink2026-09-06 23:24:20 +0200
committerDennis Fink2026-09-06 23:24:20 +0200
commit8fedec6a333d089e4f73838333773c74bd74e515 (patch)
tree9402581ae393c2ff6d0bba45a9c9dcabb490c079 /prometheus_borgmatic_exporter/cli.py
parent66d0fadd5e364eb8fceb39e8061cd93a01e9f210 (diff)
downloadprometheus-borgmatic-exporter-8fedec6a333d089e4f73838333773c74bd74e515.tar.gz
prometheus-borgmatic-exporter-8fedec6a333d089e4f73838333773c74bd74e515.zip
refactor(cli): extract helpers and improve option handling
Move shared CLI output helpers into a dedicated module to keep the main exporter module focused on metric collection. Also simplify the command-line option definitions, add missing help text, and allow --color values to be passed with or without an equals sign.
Diffstat (limited to 'prometheus_borgmatic_exporter/cli.py')
-rw-r--r--prometheus_borgmatic_exporter/cli.py116
1 files changed, 116 insertions, 0 deletions
diff --git a/prometheus_borgmatic_exporter/cli.py b/prometheus_borgmatic_exporter/cli.py
new file mode 100644
index 0000000..cc6f374
--- /dev/null
+++ b/prometheus_borgmatic_exporter/cli.py
@@ -0,0 +1,116 @@
+# SPDX-FileCopyrightText: 2026 Dennis Fink <me+coding@dennisfink.me>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import click_extra as click
+
+
+class FlexibleColorOption(click.ColorOption):
+ """Allow the color option value to be passed with or without ``=``."""
+
+ _gnu_optional_value = False
+
+
+def emit(prefix: str, color: str, *message: str, enabled: bool = True) -> None:
+ """Render a styled prefix and message to stdout.
+
+ Internal helper used by error(), msg(), warn(), verbose(), and debug()
+ to avoid duplicating the Click styling and echo logic. The first message
+ argument is rendered in bold, subsequent arguments are appended unstyled.
+
+ Args:
+ prefix: The prefix string shown before the message (e.g. "==>", "==> ERROR:").
+ color: A Click-compatible color name (e.g. "red", "green") applied to the prefix.
+ *message: One or more message parts to display. At least one is required.
+ enabled: If False, the function returns immediately without printing.
+ Defaults to True.
+
+ Raises:
+ TypeError: If no message arguments are provided.
+ """
+ if not message:
+ raise TypeError("emit() missing 1 required positional argument: 'message'")
+
+ if not enabled:
+ return
+
+ click.echo(
+ " ".join(
+ [
+ click.style(prefix, fg=color, bold=True),
+ click.style(message[0], bold=True),
+ *message[1:],
+ ]
+ )
+ )
+
+
+def error(*message: str) -> None:
+ """Print a formatted error message to stdout in red.
+
+ The first argument is rendered in bold, subsequent arguments are appended
+ unstyled. Always prints regardless of quiet or verbose flags.
+
+ Args:
+ *message: One or more message parts to display.
+ """
+ emit("==> ERROR:", "red", *message)
+
+
+@click.pass_obj
+def msg(obj: dict[str, bool], *message: str) -> None:
+ """Print a formatted informational message to stdout in green.
+
+ Suppressed when the quiet flag is set. The first argument is rendered
+ in bold, subsequent arguments are appended unstyled.
+
+ Args:
+ *message: One or more message parts to display.
+ """
+ emit("==>", "green", *message, enabled=not obj.get("quiet", False))
+
+
+@click.pass_obj
+def warn(obj: dict[str, bool], *message: str) -> None:
+ """Print a formatted warning message to stdout in yellow.
+
+ Suppressed when the quiet flag is set. The first argument is rendered
+ in bold, subsequent arguments are appended unstyled.
+
+ Args:
+ *message: One or more message parts to display.
+ """
+ emit("==>", "yellow", *message, enabled=not obj.get("quiet", False))
+
+
+@click.pass_obj
+def verbose(obj: dict[str, bool], *message: str) -> None:
+ """Print a formatted verbose message to stdout in blue.
+
+ Only prints when the verbose flag is set and the quiet flag is not.
+ The first argument is rendered in bold, subsequent arguments are
+ appended unstyled.
+
+ Args:
+ *message: One or more message parts to display.
+ """
+ emit(
+ "==>",
+ "blue",
+ *message,
+ enabled=obj.get("verbose", False) and not obj.get("quiet", False),
+ )
+
+
+@click.pass_obj
+def debug(obj: dict[str, bool], *message: str) -> None:
+ """Print a formatted debug message to stdout in magenta.
+
+ Only prints when the DEBUG environment variable is set to a truthy
+ value (1, true, yes). The first argument is rendered in bold,
+ subsequent arguments are appended unstyled.
+
+ Args:
+ *message: One or more message parts to display.
+ """
+ emit("==>", "magenta", *message, enabled=obj.get("debug", False))