docs: add comprehensive docstrings and inline comments

Add docstrings to all handler functions in daemon/handlers/firewall.py, covering
params, return values, and raised exceptions. Add inline comments to
_config_apply() reconciliation steps and the request body merge order.

Add docstrings across lib/ modules for emit helpers (_emit_str, _emit_int, etc.),
volatile stripping logic, two-layer diff strategy, sync event dispatch, and all
cross-subsystem sync subscribers (DnsToFirewall, WgToFirewall, FirewallToDhcp,
NetworkToAllSync).

Document WireGuard/networkd config parsers and key-value mappers in
system_import.py. Add docstrings to _ep(), Registry.decorator,
setup_logging, and _replace helper across daemon/ and lib/.
This commit is contained in:
2026-07-13 17:26:45 +00:00
parent 2e49dec633
commit c21639b7f1
10 changed files with 510 additions and 17 deletions
+27 -11
View File
@@ -277,16 +277,21 @@ def _strip_volatile(
for k in pop_keys:
stripped.pop(k, None)
for vpath in volatile:
# Determine if this is a list-of-dicts pattern
# Determine if this path uses list-of-dicts pattern (e.g. "peers[].transfer").
# The [] marker signals that the parent key holds a list of dicts, and we
# must strip the volatile sub-key from each dict in the list.
list_marker = vpath.index("[]") if "[]" in vpath else -1
if list_marker != -1:
# Split into prefix (before []), item keys (after [])
# Split into prefix (path before []), item keys (path after []).
# e.g. "status.peers[].transfer_received" → prefix=["status","peers"],
# item_keys=["transfer_received"]
prefix = vpath[:list_marker].split(".")
item_keys = (
vpath[list_marker + 3 :].split(".")
if list_marker + 3 < len(vpath)
else []
)
# Navigate to the list container via the prefix path
parent = stripped
for seg in prefix:
if isinstance(parent, dict) and seg in parent:
@@ -305,6 +310,7 @@ def _strip_volatile(
continue
for item in items:
# parent should now be a list; iterate each dict and strip sub-keys
if isinstance(item, dict):
curr = item
for i, ik in enumerate(item_keys):
@@ -316,7 +322,7 @@ def _strip_volatile(
else:
break
else:
# Scalar/dict path
# Scalar/dict path: navigate via segments and set final key to None
segments = vpath.split(".")
parent = stripped
for i, seg in enumerate(segments):
@@ -338,26 +344,36 @@ def _diff_layers(
) -> tuple[bool, bool]:
"""Compare *old* and *new* state using two-layer diff.
Strips ``timestamp`` from both before comparing.
The two-layer strategy distinguishes between:
1. Structural changes (config, topology) → triggers full client re-fetch
2. Volatile changes (byte counters, timestamps) → triggers lightweight tick
If structural data changed, volatile is suppressed (False) because the
structural change already triggers a full re-fetch, making the volatile
signal redundant.
Args:
old: Previous state data, or ``None`` if not yet populated.
new: New state data from collector.
volatile: Frozenset of volatile field paths.
Returns:
``(structural_changed, volatile_changed)``
``True`` means that layer differs between old and new.
If structural data changed, volatile is always ``False``
(the structural change already triggers a full re-fetch, so
the volatile signal is suppressed).
``(structural_changed, volatile_changed)``.
"""
if old is None:
return (True, True)
# Structural diff: compare with volatile/timestamp fields zeroed
# Structural diff: compare with volatile fields zeroed out, plus timestamp
# removed. If these differ, the configuration or topology has changed.
pop_keys = frozenset(("timestamp",))
old_struct = _strip_volatile(old, volatile, pop_keys)
new_struct = _strip_volatile(new, volatile, pop_keys)
structural = old_struct != new_struct
# Volatile diff: compare without timestamp
# Volatile diff: only relevant if structural is unchanged. Compare full
# data (minus timestamp). If this differs, only volatile fields changed
# (e.g. WireGuard transfer counters), and a lightweight tick suffices.
volatile_changed = False
if not structural:
old_no_ts = {k: v for k, v in old.items() if k != "timestamp"}