You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b504bef
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGELOG.md
+30-28Lines changed: 30 additions & 28 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,38 +8,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
9
9
## [Unreleased]
10
10
11
-
### Changed
11
+
tbd
12
12
13
-
* base.py: `get_worst()` now accepts any number of state arguments (`*states`). Existing two-argument callers keep working unchanged, but plugins that need to combine three or more states in one call no longer have to nest the call - e.g. `get_worst(state, used_state, committed_state)` instead of `get_worst(state, get_worst(used_state, committed_state))`
14
-
* lftest.py: `test()` now accepts `args` with fewer than three elements. Plugins can be invoked as `--test=path/to/fixture` without the trailing `,,0`; stderr defaults to the empty string and the return code to `0`
15
13
16
-
### Fixed
17
-
18
-
* Fix `--require-hashes` pip installs in CI workflows by using pinned versions instead
19
-
* cache.py: treat a cache entry as valid up to and including its `expire` timestamp instead of expiring it one second early (`<` instead of `<=`). A key set with `expire=now+5` is now still served at `now+5` and first becomes unavailable at `now+6`, matching HTTP Cache-Control max-age and Redis EXPIRE semantics. Callers that relied on the old one-second-early expiry see their cached value live one second longer ([#120](https://github.com/Linuxfabrik/lib/issues/120))
20
-
* human.py: `bits2human()`, `bytes2human()` and `bps2human()` now scale negative values to a unit that matches their magnitude. Before, `bytes2human(-1048576)` returned `-1048576.0B`, now it returns `-1.0MiB`. This matters for counter deltas that can legitimately be negative (counter resets, reclaimed memory, bandwidth drops) ([#120](https://github.com/Linuxfabrik/lib/issues/120))
21
-
* shell.py: close the upstream process's `stdout` after connecting it to the next pipeline stage. Without this, the upstream process never received EOF/SIGPIPE when the downstream stage exited early, and each pipeline stage leaked a file descriptor until garbage collection caught up ([#120](https://github.com/Linuxfabrik/lib/issues/120))
22
-
* url.py: drop the dead `timeout=timeout if digest_auth_user else timeout` ternary in `fetch()`; both branches evaluated to `timeout`, so behavior is unchanged ([#120](https://github.com/Linuxfabrik/lib/issues/120))
23
-
* db_sqlite.py: pass `usedforsecurity=False` to `hashlib.sha1()` so bandit no longer flags a non-security SHA1 use as a weak hash (the hash is only used to derive sanitized SQL identifiers)
24
-
* db_sqlite.py: rename unused loop variable in `rm_db()` to silence ruff B007
25
-
* grassfish.py: remove unused `match()` helper that referenced undefined names (`re` and `compiled_custom_id_regex`); the function was never called and would have raised `NameError` at runtime
26
-
* net.py: fix `get_netinfo()` which called a non-existent `get_ip_public()` and swallowed the resulting `NameError` by returning `[]`; the function now leaves `public_address` as `None` and callers that need the public IP must use `get_public_ip()` directly
27
-
* rocket.py: `get_groups_history()` no longer mutates a shared default `params={}` dict (B006) and properly defaults `params` to `None`
28
-
* url.py: `fetch()` and `fetch_json()` no longer use mutable default arguments for `header` and `data` (B006); defaults are now `None` with initialization inside the function
29
-
30
-
### Security
31
-
32
-
* Annotate all remaining bandit low/medium findings with `# nosec BXXX` comments and a short justification (subprocess helpers with `shell=True` by design, admin-controlled URLs passed to `urlopen`, SQL built from sanitized identifiers in `db_sqlite`). Bandit now runs clean at `--severity-level=low --confidence-level=low` over the whole lib
14
+
## [v3.0.0] - 2026-04-13
33
15
34
16
### Added
35
17
36
-
* Add CONTRIBUTING
37
18
* Add GitHub Actions workflow to automatically build and deploy API documentation to GitHub Pages
38
19
* Add bandit and vulture to `.pre-commit-config.yaml` for security and dead-code checks on every commit
39
-
* Add ruff linter and formatter to pre-commit hooks ([#117](https://github.com/Linuxfabrik/lib/issues/117))
40
20
* Add pre-commit hooks
41
-
*disk.py: add `get_owner()`
21
+
*Add ruff linter and formatter to pre-commit hooks ([#117](https://github.com/Linuxfabrik/lib/issues/117))
42
22
* args.py: expand `HELP_TEXTS` with standard help texts for all common parameters (always-ok, critical, warning, insecure, no-proxy, timeout, url, ignore-regex, match, lengthy, count, test, etc.)
23
+
* disk.py: add `get_owner()`
43
24
* lftest.py: add `run()` function for declarative, data-driven unit tests using `subTest()`
44
25
* nextcloud.py: new library
45
26
* txt.py: add `exception2text()`
@@ -48,19 +29,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
48
29
49
30
### Changed
50
31
51
-
* Bump minimum Python version from 3.6 to 3.9
52
32
* base.py: `get_perfdata()` now sanitizes labels by stripping single quotes and replacing `=` with `_`
33
+
* base.py: `get_perfdata()` output no longer has trailing semicolons
34
+
* base.py: `get_table()`: document why pure ASCII delimiters are used instead of Unicode box-drawing characters
35
+
* base.py: `get_worst()` now accepts any number of state arguments (`*states`). Existing two-argument callers keep working unchanged, but plugins that need to combine three or more states in one call no longer have to nest the call - e.g. `get_worst(state, used_state, committed_state)` instead of `get_worst(state, get_worst(used_state, committed_state))`
53
36
* base.py: deduplicate `get_state()` operator logic using `operator` module
54
37
* base.py: deduplicate `sum_dict()` by delegating to `sum_lod()`
55
-
* base.py: `get_table()`: document why pure ASCII delimiters are used instead of Unicode box-drawing characters
56
38
* base.py: improve `get_table()` performance for large tables
57
39
* base.py: move `parse_range()` and state name mapping to module level
58
40
* base.py: remove unused `collections` import
59
-
* base.py: strip trailing semicolons in `get_perfdata()` output
* human.py: deduplicate `bits2human()`/`bps2human()`/`bytes2human()` via shared `_to_human()` helper
62
43
* human.py: deduplicate `humanrange2bytes()`/`humanrange2seconds()` via shared `_convert_range()` helper
63
44
* human.py: pre-compute mappings as module constants
45
+
* lftest.py: `test()` now accepts `args` with fewer than three elements. Plugins can be invoked as `--test=path/to/fixture` without the trailing `,,0`; stderr defaults to the empty string and the return code to `0`
64
46
* powershell.py: `run_ps()` now always returns a dict
65
47
* Remove pre-built documentation from the repository (now auto-deployed via GitHub Actions)
@@ -70,23 +52,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
70
52
* winrm.py: make `run_cmd()` and `run_ps()` JEA-aware
71
53
* winrm.py: make `run_cmd()` and `run_ps()` Kerberos-aware
72
54
55
+
### Removed
56
+
57
+
* Drop support for Python older than 3.9. The lib now requires Python 3.9 or newer; this matches the oldest still-supported enterprise Linux (RHEL 8) and lets the codebase use modern syntax and standard-library features
58
+
73
59
### Fixed
74
60
75
61
* base.py: `cu()` now also escapes HTML characters in the error message, not just in the traceback
76
62
* base.py: `cu()` now detects active exceptions via `sys.exc_info()` instead of string-matching the traceback
77
63
* base.py: `get_state()` no longer calls `sys.exit()` on malformed range specs, returns UNKNOWN instead
64
+
* base.py: `get_table()` no longer uses the wrong separator for the second data row when called without a header
78
65
* base.py: `oao()` now escapes HTML characters in the output message to prevent injection in web UIs
79
-
* base.py: fix `get_table()` using wrong separator for the second data row when called without a header
80
66
* base.py: fix invalid `-10` range example in `_parse_range()` docstring (correct syntax is `-10:0`)
67
+
* cache.py: treat a cache entry as valid up to and including its `expire` timestamp instead of expiring it one second early (`<` instead of `<=`). A key set with `expire=now+5` is now still served at `now+5` and first becomes unavailable at `now+6`, matching HTTP Cache-Control max-age and Redis EXPIRE semantics. Callers that relied on the old one-second-early expiry see their cached value live one second longer ([#120](https://github.com/Linuxfabrik/lib/issues/120))
68
+
* db_sqlite.py: pass `usedforsecurity=False` to `hashlib.sha1()` so bandit no longer flags a non-security SHA1 use as a weak hash (the hash is only used to derive sanitized SQL identifiers)
69
+
* db_sqlite.py: rename unused loop variable in `rm_db()` to silence ruff B007
70
+
* Fix `--require-hashes` pip installs in CI workflows by using pinned versions instead
71
+
* grassfish.py: remove unused `match()` helper that referenced undefined names (`re` and `compiled_custom_id_regex`); the function was never called and would have raised `NameError` at runtime
72
+
* human.py: `bits2human()`, `bytes2human()` and `bps2human()` now scale negative values to a unit that matches their magnitude. Before, `bytes2human(-1048576)` returned `-1048576.0B`, now it returns `-1.0MiB`. This matters for counter deltas that can legitimately be negative (counter resets, reclaimed memory, bandwidth drops) ([#120](https://github.com/Linuxfabrik/lib/issues/120))
81
73
* human.py: fix incorrect `seconds2human()` docstring example for sub-second values
74
+
* net.py: fix `get_netinfo()` which called a non-existent `get_ip_public()` and swallowed the resulting `NameError` by returning `[]`; the function now leaves `public_address` as `None` and callers that need the public IP must use `get_public_ip()` directly
82
75
* powershell.py: fix outdated shebang line
76
+
* rocket.py: `get_groups_history()` no longer mutates a shared default `params={}` dict (B006) and properly defaults `params` to `None`
83
77
* shell.py: `shell_exec()` now applies timeout to the `shell=True` path (was previously ignored)
78
+
* shell.py: close the upstream process's `stdout` after connecting it to the next pipeline stage. Without this, the upstream process never received EOF/SIGPIPE when the downstream stage exited early, and each pipeline stage leaked a file descriptor until garbage collection caught up ([#120](https://github.com/Linuxfabrik/lib/issues/120))
84
79
* txt.py: `sanitize_sensitive_data()` now also redacts JSON-style fields and HTTP Authorization headers
85
80
* txt.py: fix `exception2text()` missing `traceback` import (fallback path was dead code)
86
81
* txt.py: fix `pluralize()` not stripping whitespace from comma-separated suffix parts
87
82
* txt.py: fix `sanitize_sensitive_data()` replacing the key name instead of the secret value
83
+
* url.py: `fetch()` and `fetch_json()` no longer use mutable default arguments for `header` and `data` (B006); defaults are now `None` with initialization inside the function
84
+
* url.py: drop the dead `timeout=timeout if digest_auth_user else timeout` ternary in `fetch()`; both branches evaluated to `timeout`, so behavior is unchanged ([#120](https://github.com/Linuxfabrik/lib/issues/120))
88
85
* winrm.py: pass parameters correctly in `run_cmd()` when using pypsrp
89
86
87
+
### Security
88
+
89
+
* Annotate all remaining bandit low/medium findings with `# nosec BXXX` comments and a short justification (subprocess helpers with `shell=True` by design, admin-controlled URLs passed to `urlopen`, SQL built from sanitized identifiers in `db_sqlite`). Bandit now runs clean at `--severity-level=low --confidence-level=low` over the whole lib
90
+
90
91
91
92
## [v2.4.0] - 2025-09-17
92
93
@@ -468,7 +469,8 @@ Minor improvements, barely any changes.
0 commit comments