fix: clear all mypy errors
Annotate untyped containers and Optional attributes, type the stdlib-shaped metric dicts in the client plugins, and add types-PyYAML/types-psutil to the dev extras plus a mypy override for nio/mattermostdriver (no stubs). Behaviour fixes found on the way: enable_kernel_timestamps() now returns False when SO_TIMESTAMP is unknown instead of raising TypeError, send_shutdown is defined at module level so cleanup() cannot hit a NameError, and a failed subprocess returncode falls back to UNKNOWN. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ import os
|
||||
try:
|
||||
import yaml
|
||||
except Exception:
|
||||
yaml = None
|
||||
yaml = None # type: ignore[assignment]
|
||||
|
||||
SERVER_DEFAULTS = {
|
||||
# Network settings
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
msgs = [] # in-memory list of recent messages for new websocket clients; also logged to file via notify.eventlog
|
||||
msgs: list = [] # in-memory list of recent messages for new websocket clients; also logged to file via notify.eventlog
|
||||
|
||||
|
||||
class Data:
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
from typing import Optional
|
||||
from typing import Any, Callable, Optional
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
@@ -79,8 +79,8 @@ async def dns_update_worker(
|
||||
hbdclass,
|
||||
cfg: dict,
|
||||
async_queue=None,
|
||||
log: Optional[callable] = None,
|
||||
pushmsg: Optional[callable] = None,
|
||||
log: Optional[Callable[..., Any]] = None,
|
||||
pushmsg: Optional[Callable[..., Any]] = None,
|
||||
loop: Optional[asyncio.AbstractEventLoop] = None,
|
||||
):
|
||||
"""Pure async DNS worker that processes updates from asyncio.Queue.
|
||||
@@ -164,7 +164,7 @@ async def dns_update_worker(
|
||||
def start_dns_worker(
|
||||
hbdclass,
|
||||
cfg: dict,
|
||||
log: Optional[callable] = None,
|
||||
log: Optional[Callable[..., Any]] = None,
|
||||
loop: Optional[asyncio.AbstractEventLoop] = None,
|
||||
):
|
||||
"""Start the async DNS worker and return the Task.
|
||||
@@ -176,7 +176,7 @@ def start_dns_worker(
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
# Create asyncio.Queue and wrap in a bridge for thread-safe puts
|
||||
async_q = asyncio.Queue()
|
||||
async_q: asyncio.Queue[Any] = asyncio.Queue()
|
||||
|
||||
class _QueueBridge:
|
||||
"""Thread-safe wrapper around asyncio.Queue for synchronous callers."""
|
||||
|
||||
@@ -8,6 +8,7 @@ import time
|
||||
import json
|
||||
import copy
|
||||
import queue
|
||||
from typing import Any, Dict
|
||||
|
||||
num = 0
|
||||
|
||||
@@ -24,7 +25,7 @@ def log(host, m):
|
||||
class Connection:
|
||||
# map of addrs to names
|
||||
|
||||
htab = {}
|
||||
htab: Dict[str, Any] = {}
|
||||
UNKNOWN = "unknown"
|
||||
UP = "up"
|
||||
DOWN = "down"
|
||||
@@ -278,8 +279,8 @@ class Connection:
|
||||
#
|
||||
class Host:
|
||||
# Table of Hosts
|
||||
hosts = {}
|
||||
dnsQ = queue.Queue()
|
||||
hosts: Dict[str, "Host"] = {}
|
||||
dnsQ: "queue.Queue[Any]" = queue.Queue()
|
||||
|
||||
def __init__(self, name):
|
||||
global num
|
||||
|
||||
@@ -11,7 +11,7 @@ import os
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, Optional, Callable, Iterable, List, Tuple, Union
|
||||
from typing import Dict, Any, Optional, Callable, Iterable, List, TextIO, Tuple, Union
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -52,7 +52,7 @@ class MessageJournal:
|
||||
self.enabled = self.config.get('journal_enabled', True)
|
||||
|
||||
# Runtime state
|
||||
self._file_handle = None
|
||||
self._file_handle: Optional[TextIO] = None
|
||||
self._current_size = 0
|
||||
self._lock = asyncio.Lock()
|
||||
self._initialized = False
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ def get_providers(config: dict) -> list[ResolvedProvider]:
|
||||
Entries with missing required fields or unknown types are skipped with
|
||||
a warning log. Order follows config declaration order.
|
||||
"""
|
||||
result = []
|
||||
result: list = []
|
||||
oauth_cfg = config.get("oauth", {})
|
||||
if not isinstance(oauth_cfg, dict):
|
||||
return result
|
||||
|
||||
@@ -53,16 +53,16 @@ class AlertState:
|
||||
self.metric_path = metric_path
|
||||
self.level = AlertLevel.OK
|
||||
self.since = time.time()
|
||||
self.last_value = None
|
||||
self.last_value: Any = None
|
||||
self.last_check = time.time()
|
||||
self.notification_count = 0
|
||||
self.last_notification = None
|
||||
self.threshold_value = None # The threshold value that triggered alert
|
||||
self.operator = None # The comparison operator (>, <, >=, etc.)
|
||||
self.last_notification: Optional[float] = None
|
||||
self.threshold_value: Optional[float] = None # The threshold value that triggered alert
|
||||
self.operator: Optional[str] = None # The comparison operator (>, <, >=, etc.)
|
||||
self.hysteresis: Optional[float] = None # Hysteresis fraction used for recovery
|
||||
self.formatted_message = None # Formatted display message for UI
|
||||
self.formatted_message: Optional[str] = None # Formatted display message for UI
|
||||
self.acknowledged = False # Whether alert has been acknowledged
|
||||
self.acknowledged_at = None # Timestamp when acknowledged
|
||||
self.acknowledged_at: Optional[float] = None # Timestamp when acknowledged
|
||||
self.consecutive_count = 0 # Consecutive exceedances while still OK (for count gating)
|
||||
self.pending_since: Optional[float] = None # non-None while waiting out grace period before notifying
|
||||
|
||||
@@ -362,13 +362,13 @@ class ThresholdChecker:
|
||||
journal: Optional MessageJournal instance for logging threshold events
|
||||
"""
|
||||
# Named threshold configurations (pre-merged: defaults + overrides): {config_name: {metric_path: ThresholdConfig}}
|
||||
self.threshold_configs = {}
|
||||
self.threshold_configs: Dict[str, Dict[str, ThresholdConfig]] = {}
|
||||
|
||||
# Raw overrides only for each named config (no defaults baked in): {config_name: {metric_path: ThresholdConfig}}
|
||||
self.threshold_raw_configs: Dict[str, Dict[str, ThresholdConfig]] = {}
|
||||
|
||||
# Single threshold set for backward compatibility: {metric_path: ThresholdConfig}
|
||||
self.thresholds = {}
|
||||
self.thresholds: Dict[str, ThresholdConfig] = {}
|
||||
|
||||
# Host to ordered list of config names: {host_name: [config_name, ...]}
|
||||
self.host_config_mapping: Dict[str, List[str]] = {}
|
||||
@@ -1276,7 +1276,7 @@ class ThresholdChecker:
|
||||
|
||||
def _format_display(
|
||||
self,
|
||||
display_format: str,
|
||||
display_format: Optional[str],
|
||||
value: Any,
|
||||
threshold_value: Optional[float],
|
||||
op_symbol: str,
|
||||
|
||||
+7
-5
@@ -5,6 +5,7 @@ import socket
|
||||
import struct
|
||||
import time
|
||||
import zlib
|
||||
from typing import Optional
|
||||
import logging
|
||||
|
||||
from platform import system as platform_system
|
||||
@@ -25,6 +26,7 @@ _STALE_INTERVAL_MULTIPLIER = 3
|
||||
# Supported on Linux, FreeBSD, and macOS. The constant is not exposed by
|
||||
# Python's socket module on all platforms
|
||||
platform = platform_system()
|
||||
_SO_TIMESTAMP: Optional[int]
|
||||
if platform == "Darwin":
|
||||
_SO_TIMESTAMP = 1024 # SO_TIMESTAMP on macOS (not in Python's socket module)
|
||||
elif platform == "Linux":
|
||||
@@ -45,6 +47,8 @@ def enable_kernel_timestamps(sock) -> bool:
|
||||
Returns True if the kernel will supply receive timestamps, False otherwise
|
||||
(unsupported platform, older kernel, or insufficient permissions).
|
||||
"""
|
||||
if _SO_TIMESTAMP is None:
|
||||
return False
|
||||
try:
|
||||
sock.setsockopt(socket.SOL_SOCKET, _SO_TIMESTAMP, 1)
|
||||
return True
|
||||
@@ -430,7 +434,7 @@ def handle_datagram(msg: dict, addr, transport, ctx: dict):
|
||||
return
|
||||
|
||||
cfg = ctx.get("config", {})
|
||||
hbdcls = ctx.get("hbdclass")
|
||||
hbdcls = ctx["hbdclass"]
|
||||
msg_to_websockets = ctx.get("msg_to_websockets")
|
||||
DEBUG = ctx.get("DEBUG", 0)
|
||||
|
||||
@@ -459,10 +463,8 @@ def handle_datagram(msg: dict, addr, transport, ctx: dict):
|
||||
newh = False
|
||||
|
||||
cid = msg.get("id", 0)
|
||||
try:
|
||||
rtt = float(msg.get("rtt"))
|
||||
except TypeError:
|
||||
rtt = None
|
||||
rtt_raw = msg.get("rtt")
|
||||
rtt = float(rtt_raw) if rtt_raw is not None else None
|
||||
|
||||
if msg.get("ID") == "HTB":
|
||||
host.doesack = msg.get("acks", -1)
|
||||
|
||||
Reference in New Issue
Block a user