From 7eb8f265cb58a5c2cf78157afb7b15997356f198 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 5 Aug 2026 10:41:10 +0000 Subject: [PATCH] Add a logout method to blueapi client --- src/blueapi/client/client.py | 11 +++++++++++ tests/unit_tests/client/test_client.py | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/blueapi/client/client.py b/src/blueapi/client/client.py index 20de158929..f3486fead4 100644 --- a/src/blueapi/client/client.py +++ b/src/blueapi/client/client.py @@ -774,6 +774,17 @@ def login(self, token_path: Path | None = None): else: print("Server is not configured to use authentication!") + def logout(self, token_path: Path | None = None): + try: + auth: SessionManager = SessionManager.from_cache(token_path) + auth.logout() + except FileNotFoundError: + print("Logged out") + except ValueError as e: + print(f"Invalid login token: {e}") + except Exception as e: + print(f"Failed to logout from blueapi with error: {e}") + class PlanFailedError(Exception): def __init__(self, typ: str, message: str): diff --git a/tests/unit_tests/client/test_client.py b/tests/unit_tests/client/test_client.py index eaf96a3b2d..aa0295e592 100644 --- a/tests/unit_tests/client/test_client.py +++ b/tests/unit_tests/client/test_client.py @@ -1000,3 +1000,19 @@ def test_client_login_no_oidc( client.login() mock_session_manager.assert_not_called() + + +@patch("blueapi.client.client.SessionManager") +def test_client_logout(mock_session_manager: Mock, client: BlueapiClient): + client.logout() + + mock_session_manager.from_cache.assert_called_once() + mock_session_manager.from_cache.return_value.logout.assert_called_once() + + +@patch("blueapi.client.client.SessionManager") +def test_client_logout_invalid_token(mock_session_manager: Mock, client: BlueapiClient): + mock_session_manager.from_cache.side_effect = ValueError("No token") + + client.logout() + mock_session_manager.from_cache.return_value.logout.assert_not_called()