mirror of
https://github.com/jmagar/unraid-mcp.git
synced 2026-03-02 00:04:45 -08:00
fix: apply all PR review agent findings (silent failures, type safety, test gaps)
Addresses issues found by 4 parallel review agents (code-reviewer,
silent-failure-hunter, type-design-analyzer, pr-test-analyzer).
Source fixes:
- core/utils.py: add public safe_display_url() (moved from tools/health.py)
- core/client.py: rename _redact_sensitive → redact_sensitive (public API)
- core/types.py: add SubscriptionData.__post_init__ for tz-aware datetime
enforcement; remove 6 unused type aliases (SystemHealth, APIResponse, etc.)
- subscriptions/manager.py: add exc_info=True to both except-Exception blocks;
add except ValueError break-on-config-error before retry loop; import
redact_sensitive by new public name
- subscriptions/resources.py: re-raise in autostart_subscriptions() so
ensure_subscriptions_started() doesn't permanently set _subscriptions_started
- subscriptions/diagnostics.py: except ToolError: raise before broad except;
use safe_display_url() instead of raw URL slice
- tools/health.py: move _safe_display_url to core/utils; add exc_info=True;
raise ToolError (not return dict) on ImportError
- tools/info.py: use get_args(INFO_ACTIONS) instead of INFO_ACTIONS.__args__
- tools/{array,docker,keys,notifications,rclone,storage,virtualization}.py:
add Literal-vs-ALL_ACTIONS sync check at import time
Test fixes:
- test_health.py: import safe_display_url from core.utils; update
test_diagnose_import_error_internal to expect ToolError (not error dict)
- test_storage.py: add 3 safe_get tests for zero/False/empty-string values
- test_subscription_manager.py: add TestCapLogContentSingleMassiveLine (2 tests)
- test_client.py: rename _redact_sensitive → redact_sensitive; add tests for
new sensitive keys and is_cacheable explicit-keyword form
This commit is contained in:
@@ -47,7 +47,7 @@ class OverwriteFileHandler(logging.FileHandler):
|
||||
"""Emit a record, checking file size periodically and overwriting if needed."""
|
||||
self._emit_count += 1
|
||||
if (
|
||||
self._emit_count % self._check_interval == 0
|
||||
(self._emit_count == 1 or self._emit_count % self._check_interval == 0)
|
||||
and self.stream
|
||||
and hasattr(self.stream, "name")
|
||||
):
|
||||
@@ -249,5 +249,3 @@ if FASTMCP_AVAILABLE:
|
||||
else:
|
||||
# Fallback to our custom logger if FastMCP is not available
|
||||
logger = setup_logger()
|
||||
# Also configure FastMCP logger for consistency
|
||||
configure_fastmcp_logger_with_rich()
|
||||
|
||||
@@ -5,12 +5,13 @@ and provides all configuration constants used throughout the application.
|
||||
"""
|
||||
|
||||
import os
|
||||
from importlib.metadata import PackageNotFoundError, version
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from ..version import VERSION as APP_VERSION
|
||||
|
||||
|
||||
# Get the script directory (config module location)
|
||||
SCRIPT_DIR = Path(__file__).parent # /home/user/code/unraid-mcp/unraid_mcp/config/
|
||||
@@ -31,12 +32,6 @@ for dotenv_path in dotenv_paths:
|
||||
load_dotenv(dotenv_path=dotenv_path)
|
||||
break
|
||||
|
||||
# Application Version (single source of truth: pyproject.toml)
|
||||
try:
|
||||
VERSION = version("unraid-mcp")
|
||||
except PackageNotFoundError:
|
||||
VERSION = "0.0.0"
|
||||
|
||||
# Core API Configuration
|
||||
UNRAID_API_URL = os.getenv("UNRAID_API_URL")
|
||||
UNRAID_API_KEY = os.getenv("UNRAID_API_KEY")
|
||||
@@ -58,12 +53,18 @@ else: # Path to CA bundle
|
||||
# Logging Configuration
|
||||
LOG_LEVEL_STR = os.getenv("UNRAID_MCP_LOG_LEVEL", "INFO").upper()
|
||||
LOG_FILE_NAME = os.getenv("UNRAID_MCP_LOG_FILE", "unraid-mcp.log")
|
||||
# Use /app/logs in Docker, project-relative logs/ directory otherwise
|
||||
LOGS_DIR = Path("/app/logs") if Path("/app").is_dir() else PROJECT_ROOT / "logs"
|
||||
# Use /.dockerenv as the container indicator for robust Docker detection.
|
||||
IS_DOCKER = Path("/.dockerenv").exists()
|
||||
LOGS_DIR = Path("/app/logs") if IS_DOCKER else PROJECT_ROOT / "logs"
|
||||
LOG_FILE_PATH = LOGS_DIR / LOG_FILE_NAME
|
||||
|
||||
# Ensure logs directory exists
|
||||
LOGS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
# Ensure logs directory exists; if creation fails, fall back to /tmp.
|
||||
try:
|
||||
LOGS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
except OSError:
|
||||
LOGS_DIR = PROJECT_ROOT / ".cache" / "logs"
|
||||
LOGS_DIR.mkdir(parents=True, exist_ok=True)
|
||||
LOG_FILE_PATH = LOGS_DIR / LOG_FILE_NAME
|
||||
|
||||
# HTTP Client Configuration
|
||||
TIMEOUT_CONFIG = {
|
||||
@@ -109,3 +110,5 @@ def get_config_summary() -> dict[str, Any]:
|
||||
"config_valid": is_valid,
|
||||
"missing_config": missing if not is_valid else None,
|
||||
}
|
||||
# Re-export application version from a single source of truth.
|
||||
VERSION = APP_VERSION
|
||||
|
||||
Reference in New Issue
Block a user