Skip to content

Commit a51126e

Browse files
authored
BUG: Make windows error warning when writing to keyring cache (#24)
1 parent fc1601c commit a51126e

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

msal_requests_auth/cache.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
44
"""
55
import os
6+
import warnings
67
from abc import ABC, abstractmethod
78
from pathlib import Path
89
from typing import Union
@@ -105,7 +106,18 @@ def write_cache(self) -> None:
105106
"""
106107
Write cache to keyring if needed.
107108
"""
108-
if self.has_state_changed:
109+
if not self.has_state_changed:
110+
return
111+
112+
try:
109113
_import_keyring().set_password(
110114
"__msal_requests_auth__", "token", self.serialize()
111115
)
116+
except Exception as error: # pylint: disable=broad-exception-caught
117+
# some windows machines have issues writing to keyring
118+
# win32ctypes.pywin32.pywintypes.error: (1783, 'CredWrite', 'The stub received bad data')
119+
if getattr(error, "winerror", None) != 1783:
120+
raise
121+
warnings.warn(
122+
f"Token cache skipped due to error writing to keyring. Error: {error}"
123+
)

test/test_cache.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from unittest.mock import patch
22

3+
import pytest
4+
35
from msal_requests_auth.cache import KeyringTokenCache, SimpleTokenCache
46

57

@@ -89,3 +91,50 @@ def test_keyring_token_cache__deserialize(deserialize_mock, keyring_mock):
8991
keyring_mock.return_value.get_password.return_value = "TEST"
9092
KeyringTokenCache()
9193
deserialize_mock.assert_called_with("TEST")
94+
95+
96+
@patch("msal_requests_auth.cache._import_keyring")
97+
@patch("msal_requests_auth.cache.KeyringTokenCache.serialize")
98+
def test_keyring_token_cache__write_cache__windows_error(serialize_mock, keyring_mock):
99+
class MyException(Exception):
100+
def __init__(self, *args, **kwargs) -> None:
101+
self.winerror = 1783
102+
super().__init__(*args, **kwargs)
103+
104+
keyring_mock.return_value.set_password.side_effect = MyException
105+
106+
serialize_mock.return_value = "TEST"
107+
keyring_mock.return_value.get_password.return_value = None
108+
with KeyringTokenCache() as cache:
109+
pass
110+
keyring_mock.return_value.get_password.assert_called_with(
111+
"__msal_requests_auth__", "token"
112+
)
113+
keyring_mock.return_value.set_password.assert_not_called()
114+
cache.has_state_changed = True
115+
with pytest.warns(match="Token cache skipped due to error writing to keyring"):
116+
with KeyringTokenCache() as cache:
117+
cache.has_state_changed = True
118+
keyring_mock.return_value.set_password.assert_called_with(
119+
"__msal_requests_auth__", "token", "TEST"
120+
)
121+
122+
123+
@patch("msal_requests_auth.cache._import_keyring")
124+
@patch("msal_requests_auth.cache.KeyringTokenCache.serialize")
125+
def test_keyring_token_cache__write_cache__error(serialize_mock, keyring_mock):
126+
keyring_mock.return_value.set_password.side_effect = RuntimeError
127+
serialize_mock.return_value = "TEST"
128+
keyring_mock.return_value.get_password.return_value = None
129+
with KeyringTokenCache() as cache:
130+
pass
131+
keyring_mock.return_value.get_password.assert_called_with(
132+
"__msal_requests_auth__", "token"
133+
)
134+
keyring_mock.return_value.set_password.assert_not_called()
135+
with pytest.raises(RuntimeError):
136+
with KeyringTokenCache() as cache:
137+
cache.has_state_changed = True
138+
keyring_mock.return_value.set_password.assert_called_with(
139+
"__msal_requests_auth__", "token", "TEST"
140+
)

0 commit comments

Comments
 (0)