Skip to content

Commit c1aa409

Browse files
committed
improvement to optional logging structure
1 parent 65df530 commit c1aa409

2 files changed

Lines changed: 52 additions & 40 deletions

File tree

src/powersensor_local/devices.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55

66
from datetime import datetime, timezone
7+
from enum import Enum
78
from pathlib import Path
89
PROJECT_ROOT = str(Path(__file__).parents[1])
910
if PROJECT_ROOT not in sys.path:
@@ -29,6 +30,13 @@
2930
]
3031

3132

33+
class _LogLevel(Enum):
34+
DEBUG = 'debug'
35+
INFO = 'info'
36+
WARNING = 'warning'
37+
ERROR = 'error'
38+
39+
3240
class _PowersensorDevicesBase:
3341
"""Shared base for PowersensorLegacyDevices and PowersensorZeroconfDevices.
3442
@@ -94,6 +102,20 @@ def __init__(
94102
self._relay_now_relaying_for = relay_now_relaying_for
95103
self._logger = logger
96104

105+
# ------------------------------------------------------------------
106+
# Internal logging helper
107+
# ------------------------------------------------------------------
108+
109+
def _maybe_log(self, level: _LogLevel, msg: str, *args) -> None:
110+
"""Emit a log message if a logger was provided at construction."""
111+
if self._logger is None:
112+
return
113+
match level:
114+
case _LogLevel.DEBUG: self._logger.debug(msg, *args)
115+
case _LogLevel.INFO: self._logger.info(msg, *args)
116+
case _LogLevel.WARNING: self._logger.warning(msg, *args)
117+
case _LogLevel.ERROR: self._logger.error(msg, *args)
118+
97119
# ------------------------------------------------------------------
98120
# Public subscription API
99121
# ------------------------------------------------------------------
@@ -173,8 +195,7 @@ async def _emit_if_subscribed(self, ev: str, mac: str, obj: dict) -> None:
173195
async def _reemit(self, ev: str, obj: dict[str, str]) -> None:
174196
mac: str|None = obj.get('mac')
175197
if mac is None:
176-
if self._logger:
177-
self._logger.warning("Received event '%s' with no MAC address — ignoring", ev)
198+
self._maybe_log(_LogLevel.WARNING, "Received event '%s' with no MAC address — ignoring", ev)
178199
return
179200
device = self._devices.get(mac)
180201
if device is not None:
@@ -290,8 +311,7 @@ async def yourcallback(event: dict) -> None
290311
Returns the number of gateway plugs found.
291312
"""
292313
if self._timer is not None:
293-
if self._logger:
294-
self._logger.warning("start() called while already running — ignoring")
314+
self._maybe_log(_LogLevel.WARNING, "start() called while already running — ignoring")
295315
return len(self._plug_apis)
296316
self._event_cb = async_event_cb
297317
await self._on_scanned(await self._discovery.scan())

src/powersensor_local/zeroconf_devices.py

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
if PROJECT_ROOT not in sys.path:
6565
sys.path.append(PROJECT_ROOT)
6666

67-
from powersensor_local.devices import _PowersensorDevicesBase
67+
from powersensor_local.devices import _PowersensorDevicesBase, _LogLevel
6868

6969
_SERVICE_TYPE_UDP = '_powersensor._udp.local.'
7070
_SERVICE_TYPE_TCP = '_powersensor._tcp.local.'
@@ -154,8 +154,7 @@ async def start(self, async_event_cb) -> None:
154154
callbacks shortly after the browser starts.
155155
"""
156156
if self._browser is not None:
157-
if self._logger:
158-
self._logger.warning("start() called while already running — ignoring")
157+
self._maybe_log(_LogLevel.WARNING, "start() called while already running — ignoring")
159158
return
160159

161160
self._event_cb = async_event_cb
@@ -230,22 +229,19 @@ def _schedule_removal(self, mac: str) -> None:
230229
mac,
231230
)
232231
self._pending_removals[mac] = handle
233-
if self._logger:
234-
self._logger.debug("Scheduled removal for %s in %.0f s", mac, self._debounce_seconds)
232+
self._maybe_log(_LogLevel.DEBUG, "Scheduled removal for %s in %.0f s", mac, self._debounce_seconds)
235233

236234
def _on_debounce_expired(self, mac: str) -> None:
237235
"""Called by the event loop when the debounce timer fires."""
238236
self._pending_removals.pop(mac, None)
239-
if self._logger:
240-
self._logger.info("Plug %s still absent after debounce — removing", mac)
237+
self._maybe_log(_LogLevel.INFO, "Plug %s still absent after debounce — removing", mac)
241238
asyncio.get_running_loop().create_task(self._plug_lost(mac))
242239

243240
def _cancel_pending_removal(self, mac: str, source: str) -> None:
244241
handle = self._pending_removals.pop(mac, None)
245242
if handle:
246243
handle.cancel()
247-
if self._logger:
248-
self._logger.debug("Cancelled pending removal for %s (%s)", mac, source)
244+
self._maybe_log(_LogLevel.DEBUG, "Cancelled pending removal for %s (%s)", mac, source)
249245

250246
# ------------------------------------------------------------------
251247
# Called from _Listener (zeroconf thread → event loop via stored loop ref)
@@ -309,46 +305,42 @@ def _extract(self, zc: Any, type_: str, name: str) -> tuple[str, str, int] | Non
309305
"""
310306
info = _zc.ServiceInfo(type_, name)
311307
if not info.load_from_cache(zc):
312-
if self._owner._logger:
313-
self._owner._logger.warning(
314-
"No cache entry for %s — device will appear on next mDNS announcement",
315-
name,
316-
)
308+
self._owner._maybe_log(
309+
_LogLevel.WARNING,
310+
"No cache entry for %s — device will appear on next mDNS announcement",
311+
name,
312+
)
317313
return None
318314

319315
addresses = info.parsed_addresses()
320316
if not addresses:
321-
if self._owner._logger:
322-
self._owner._logger.warning("No addresses in zeroconf cache record for %s", name)
317+
self._owner._maybe_log(_LogLevel.WARNING, "No addresses in zeroconf cache record for %s", name)
323318
return None
324319

325320
try:
326321
raw_id = info.properties[b'id']
327322
except KeyError:
328-
if self._owner._logger:
329-
self._owner._logger.error("Missing 'id' property in zeroconf record for %s", name)
323+
self._owner._maybe_log(_LogLevel.ERROR, "Missing 'id' property in zeroconf record for %s", name)
330324
return None
331325

332326
if raw_id is None:
333-
if self._owner._logger:
334-
self._owner._logger.error("'id' property in zeroconf record for %s has no value", name)
327+
self._owner._maybe_log(_LogLevel.ERROR, "'id' property in zeroconf record for %s has no value", name)
335328
return None
336329

337330
if info.port is None:
338-
if self._owner._logger:
339-
self._owner._logger.error("No port in zeroconf record for %s", name)
331+
self._owner._maybe_log(_LogLevel.ERROR, "No port in zeroconf record for %s", name)
340332
return None
341333

342334
return raw_id.decode('utf-8'), addresses[0], info.port
343335

344336
def add_service(self, zc: Any, type_: str, name: str) -> None:
345337
result = self._extract(zc, type_, name)
346338
if result is None:
347-
if self._owner._logger:
348-
self._owner._logger.warning(
349-
"add_service: no info available for %s — will retry on next announcement",
350-
name,
351-
)
339+
self._owner._maybe_log(
340+
_LogLevel.WARNING,
341+
"add_service: no info available for %s — will retry on next announcement",
342+
name,
343+
)
352344
return
353345
mac, ip, port = result
354346
self._name_to_mac[name] = mac
@@ -357,11 +349,11 @@ def add_service(self, zc: Any, type_: str, name: str) -> None:
357349
def update_service(self, zc: Any, type_: str, name: str) -> None:
358350
result = self._extract(zc, type_, name)
359351
if result is None:
360-
if self._owner._logger:
361-
self._owner._logger.warning(
362-
"update_service: no info available for %s — will retry on next announcement",
363-
name,
364-
)
352+
self._owner._maybe_log(
353+
_LogLevel.WARNING,
354+
"update_service: no info available for %s — will retry on next announcement",
355+
name,
356+
)
365357
return
366358
mac, ip, port = result
367359
self._name_to_mac[name] = mac
@@ -370,10 +362,10 @@ def update_service(self, zc: Any, type_: str, name: str) -> None:
370362
def remove_service(self, zc: Any, type_: str, name: str) -> None:
371363
mac = self._name_to_mac.pop(name, None)
372364
if mac is None:
373-
if self._owner._logger:
374-
self._owner._logger.warning(
375-
"remove_service for %s: MAC not in cache — removal ignored", name
376-
)
365+
self._owner._maybe_log(
366+
_LogLevel.WARNING,
367+
"remove_service for %s: MAC not in cache — removal ignored", name,
368+
)
377369
return
378370
self._owner._on_zc_remove(mac, self._loop)
379371

0 commit comments

Comments
 (0)