diff --git a/src/mcp_synology_container/cli.py b/src/mcp_synology_container/cli.py index 7471040..1e57aac 100644 --- a/src/mcp_synology_container/cli.py +++ b/src/mcp_synology_container/cli.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio +import contextlib import json import logging import sys @@ -144,10 +145,8 @@ async def _run_setup() -> None: client.sid = sid click.echo(click.style("Login successful!", fg="green")) # Logout cleanly - try: + with contextlib.suppress(SynologyError): await client.request("SYNO.API.Auth", "logout", version=6, params={}) - except SynologyError: - pass else: click.echo(click.style("Login failed: no session ID returned.", fg="red"), err=True) sys.exit(1) diff --git a/src/mcp_synology_container/modules/compose.py b/src/mcp_synology_container/modules/compose.py index bc41f61..f0b02af 100644 --- a/src/mcp_synology_container/modules/compose.py +++ b/src/mcp_synology_container/modules/compose.py @@ -268,7 +268,7 @@ def register_compose(mcp: FastMCP, config: AppConfig, client: DsmClient) -> None # Determine previous value and build description old_value: str | None = None if isinstance(env_list, list): - for i, entry in enumerate(env_list): + for entry in env_list: if isinstance(entry, str) and entry.startswith(f"{var_name}="): old_value = entry.split("=", 1)[1] break @@ -325,8 +325,9 @@ def register_compose(mcp: FastMCP, config: AppConfig, client: DsmClient) -> None except Exception as e: return f"Error writing compose file: {e}" + verb = "Updated" if action == "update" else "Added" return ( - f"{'Updated' if action == 'update' else 'Added'} env var in '{service_name}' ({project_name}):\n" + f"{verb} env var in '{service_name}' ({project_name}):\n" f" {var_name}={var_value}\n\n" f"Tip: Run redeploy_project('{project_name}', confirmed=True) to apply the change." ) diff --git a/src/mcp_synology_container/modules/images.py b/src/mcp_synology_container/modules/images.py index 386ffdf..a32b9fb 100644 --- a/src/mcp_synology_container/modules/images.py +++ b/src/mcp_synology_container/modules/images.py @@ -233,8 +233,10 @@ def register_images(mcp: FastMCP, config: AppConfig, client: DsmClient) -> None: ) if in_use_stopped: + stopped_name = in_use_stopped[0] return ( - f"Cannot delete '{display_name}': image is used by stopped container '{in_use_stopped[0]}'.\n" + f"Cannot delete '{display_name}': image is used by stopped container " + f"'{stopped_name}'.\n" f"Delete the container first or run system_prune to clean up stopped containers." ) diff --git a/tests/test_auth.py b/tests/test_auth.py index fa4ec30..c2a467f 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -35,9 +35,11 @@ def test_resolve_credentials_no_credentials(monkeypatch): config = make_config() auth = AuthManager(config) - with patch("keyring.get_password", return_value=None): - with pytest.raises(AuthenticationError, match="No credentials found"): - auth.resolve_credentials() + with ( + patch("keyring.get_password", return_value=None), + pytest.raises(AuthenticationError, match="No credentials found"), + ): + auth.resolve_credentials() def test_resolve_credentials_from_keyring(monkeypatch): @@ -124,9 +126,11 @@ async def test_login_2fa_required(): mock_client = AsyncMock() mock_client.request.side_effect = SynologyError("2FA required", code=403) - with patch.object(auth, "resolve_credentials", return_value=("user", "pass", None)): - with pytest.raises(AuthenticationError, match="2FA is required"): - await auth.login(mock_client) + with ( + patch.object(auth, "resolve_credentials", return_value=("user", "pass", None)), + pytest.raises(AuthenticationError, match="2FA is required"), + ): + await auth.login(mock_client) @pytest.mark.asyncio @@ -137,9 +141,11 @@ async def test_login_no_sid_returned(): mock_client = AsyncMock() mock_client.request.return_value = {} # No 'sid' key - with patch.object(auth, "resolve_credentials", return_value=("user", "pass", None)): - with pytest.raises(AuthenticationError, match="no session ID"): - await auth.login(mock_client) + with ( + patch.object(auth, "resolve_credentials", return_value=("user", "pass", None)), + pytest.raises(AuthenticationError, match="no session ID"), + ): + await auth.login(mock_client) @pytest.mark.asyncio