Skip to content

Commit 736bfd0

Browse files
committed
refactor(tools): add _common.py with REPO_ROOT and print helpers
First commit of a larger tools/ modernisation pass. Introduces a tiny shared module that every tool under tools/ can import so the top-of-file boilerplate stays identical across tools: - REPO_ROOT, CHECK_PLUGINS_DIR, TOOLS_DIR as pathlib.Path constants resolved from _common.py's own location - SKIP_PLUGINS = {'example'} so walkers all skip the plugin skeleton by default - err() / die() helpers that print to stderr so tool stdout stays clean for piping or CI log capture - iter_check_plugins() that walks check-plugins/ in sorted order and yields pathlib.Path objects (instead of string paths) Follow-up commits will migrate each tool off its own REPO_ROOT / os.path.dirname(__file__) duplicate onto this module and off the optional colorama dependency (basket-compare / basket-join) onto the plain stderr print helpers.
1 parent 4da4e0d commit 736bfd0

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

tools/_common.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#! /usr/bin/env python3
2+
# -*- coding: utf-8; py-indent-offset: 4 -*-
3+
#
4+
# Author: Linuxfabrik GmbH, Zurich, Switzerland
5+
# Contact: info (at) linuxfabrik (dot) ch
6+
# https://www.linuxfabrik.ch/
7+
# License: The Unlicense, see LICENSE file.
8+
9+
# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.md
10+
11+
"""Shared helpers for the `tools/` scripts.
12+
13+
Kept deliberately small. Every tool under `tools/` imports `REPO_ROOT`
14+
and the `err()` / `die()` / `iter_check_plugins()` helpers from here so
15+
the top of each tool looks identical; anything specific to a single
16+
tool lives next to its caller.
17+
18+
The shebang-named tools under `tools/` (`run-unit-tests`, `build-docs`,
19+
...) import this module as `_common`. Python's default `sys.path[0]`
20+
when running a script is the directory containing that script, so the
21+
relative import works without any PYTHONPATH gymnastics.
22+
"""
23+
24+
import sys
25+
from pathlib import Path
26+
27+
__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
28+
__version__ = '2026041301'
29+
30+
31+
# Resolve the repository root from this file's location. Any tool that
32+
# sits next to `_common.py` inside `tools/` inherits the same value.
33+
REPO_ROOT = Path(__file__).resolve().parent.parent
34+
CHECK_PLUGINS_DIR = REPO_ROOT / 'check-plugins'
35+
TOOLS_DIR = REPO_ROOT / 'tools'
36+
37+
# The `example` plugin is a code skeleton that new plugins are based
38+
# on; it is not meant to be discovered, tested or shipped. Tools that
39+
# walk the check-plugins tree should skip it by default.
40+
SKIP_PLUGINS = frozenset({'example'})
41+
42+
43+
def err(msg):
44+
"""Print a message to stderr.
45+
46+
Used for warnings and errors so the stdout of a tool stays clean
47+
for piping into other tools or for CI log capture. Callers that
48+
want to abort after printing should use `die()` instead.
49+
"""
50+
print(msg, file=sys.stderr, flush=True)
51+
52+
53+
def die(msg, code=1):
54+
"""Print a message to stderr and exit with the given code.
55+
56+
Convenience wrapper around `err()` + `sys.exit()` so the call-site
57+
reads as one statement. The default exit code `1` matches the Unix
58+
convention for a generic failure.
59+
"""
60+
err(msg)
61+
sys.exit(code)
62+
63+
64+
def iter_check_plugins(skip=SKIP_PLUGINS):
65+
"""Yield every `check-plugins/<name>` directory in sorted order.
66+
67+
Skips any plugin whose name is in `skip` (default: the `example`
68+
skeleton). Tools that need a different skip set - for example, to
69+
rerun a single plugin that is normally skipped - can pass
70+
`skip=frozenset()` to walk the entire tree.
71+
72+
Yields `pathlib.Path` objects, so callers can chain the usual
73+
`.name`, `.is_dir()`, `/ "sub"` operations without dragging `os`
74+
and `os.path` imports into the caller.
75+
"""
76+
for entry in sorted(CHECK_PLUGINS_DIR.iterdir()):
77+
if not entry.is_dir():
78+
continue
79+
if entry.name in skip:
80+
continue
81+
yield entry

0 commit comments

Comments
 (0)