Skip to content

Commit 3261868

Browse files
committed
Working on feedback - StatbankAuthError now takes a param into init, less aggressive about emptying the password from netrc
1 parent bd0ac05 commit 3261868

6 files changed

Lines changed: 54 additions & 39 deletions

File tree

src/statbank/api_exceptions.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,32 @@
44

55

66
class StatbankAuthError(requests.HTTPError):
7-
"""We pass up the error-response with this error up through try-excepts."""
7+
"""Raised when authentication with Statbank fails.
88
9-
def __init__(self, other_error: str | Exception) -> None:
10-
"""Initializing the error with a possibility of wrapping around an existing error.
9+
Extends ``requests.HTTPError`` with an optional ``response_content`` attribute
10+
that can hold parsed JSON from the response.
11+
12+
Args:
13+
*args: Positional arguments forwarded to ``requests.HTTPError``.
14+
response_content: Optional JSON-decoded payload to attach.
15+
**kwargs: Keyword arguments forwarded to ``requests.HTTPError``.
16+
"""
17+
18+
def __init__(
19+
self,
20+
*args: Any,
21+
response_content: dict[str, Any] | None = None,
22+
**kwargs: Any,
23+
) -> None:
24+
"""Initialize the Statbank authentication error.
1125
1226
Args:
13-
other_error: The error-string, or a different exception that we want to re-wrap in this exception.
27+
*args: Positional arguments forwarded to ``requests.HTTPError``.
28+
response_content: Optional JSON-decoded payload to attach.
29+
**kwargs: Keyword arguments forwarded to ``requests.HTTPError``.
1430
"""
15-
error_text: str = str(other_error)
16-
super().__init__(error_text)
17-
18-
self.response_content: dict[str, Any] | None = None
19-
if hasattr(
20-
other_error,
21-
"response_content",
22-
): # If we double-wrap the error, lets try to save this attribute
23-
self.response_content = other_error.response_content
31+
super().__init__(*args, **kwargs)
32+
self.response_content: dict[str, Any] | None = response_content
2433

2534

2635
class StatbankApiError(Exception):

src/statbank/auth.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,28 +212,32 @@ def _react_to_httperror_should_retry(
212212
self,
213213
e: requests.HTTPError | StatbankAuthError,
214214
) -> bool:
215-
logger.error("We got an http-error, proceding to emptying the auth.")
216-
self._cleanup_netrc()
217-
218-
default_err_msg = "Got an http-error, but it does not look like an account-lock or invalid password/username, is this something we should program for? - "
215+
default_err_msg = """Got an http-error, but it does not look like an account-lock or invalid password/username,
216+
is this something we should program for?
217+
If you want to reset the auth manually call StatbankClient().reset_auth() or
218+
StatbankAuth().reset_auth(). Alternatively edit the .netrc file directly.""".replace(
219+
"\n",
220+
"",
221+
)
219222

220223
if hasattr(e, "response_content") and e.response_content:
221224
if "ORA-28000" in e.response_content.get("ExceptionMessage", ""):
222-
err_msg = f'Your account has been locked. Contact kundeservice@ssb.no to unlock. Errortext: {e.response_content.get("ExceptionMessage", "")}'
225+
err_msg = f'Your account has been locked. Contact kundeservice@ssb.no to unlock. Resetting auth. Errortext: {e.response_content.get("ExceptionMessage", "")}'
223226
logger.error(err_msg)
224227
new_err = StatbankAuthError(err_msg)
228+
self._cleanup_netrc()
225229
raise new_err
226230
if "ORA-01017" in e.response_content.get("ExceptionMessage", ""):
227231
logger.error(
228-
f"TYPE CAREFULLY - The username and password you used may have been wrong. Errortext: {e.response_content.get('ExceptionMessage', '')}",
232+
f"TYPE CAREFULLY - The username and password you used may have been wrong. Resetting Auth. Errortext: {e.response_content.get('ExceptionMessage', '')}",
229233
)
230-
self._auth = self._get_auth()
234+
self.reset_auth()
231235
return True
232236
logger.error(
233237
f"{default_err_msg}{e.response_content.get('Exception_message', '')} - {e} ",
234238
)
235239
else:
236-
logger.error(f"{default_err_msg}{e}")
240+
logger.error(f"{default_err_msg}{e}.")
237241

238242
raise e
239243

@@ -257,7 +261,7 @@ def _encrypt_password(self: Self, password: str) -> str:
257261

258262
response.raise_for_status()
259263

260-
data = cast(dict[Literal["message"], str], response.json())
264+
data = cast('dict[Literal["message"], str]', response.json())
261265

262266
return data["message"]
263267

src/statbank/transfer.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,7 @@ def _make_transfer_request(
372372
try:
373373
result.raise_for_status()
374374
except r.HTTPError as e:
375-
e = StatbankAuthError(e) # Wrap so attribute is available
376-
e.response_content = result.json()
377-
raise
375+
raise StatbankAuthError(response_content=result.json()) from e
378376
return result
379377

380378
def _cleanup_response(self) -> None:

src/statbank/uttrekk.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,9 +602,7 @@ def _make_request(self, url: furl, params: dict[str, str | int]) -> r.Response:
602602
try:
603603
response.raise_for_status()
604604
except r.HTTPError as e:
605-
e = StatbankAuthError(e) # Wrap so attribute is available to assign to
606-
e.response_content = response.json()
607-
raise
605+
raise StatbankAuthError(response_content=response.json()) from e
608606
return response
609607

610608
@classmethod

tests/test_api_exceptions.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from statbank.api_exceptions import StatbankAuthError
22

33

4-
def test_double_wrap_is_fine():
5-
err1 = StatbankAuthError("Try adding the argument here")
6-
err1.response_content = {"ExceptionMessage": "You are using testcode bro"}
7-
err2 = StatbankAuthError(err1)
4+
def test_statbankautherror_param():
5+
err1 = StatbankAuthError(
6+
"Try adding the argument here",
7+
response_content={"ExceptionMessage": "You are using testcode bro"},
8+
)
89

9-
assert "ExceptionMessage" in err2.response_content
10+
assert "ExceptionMessage" in err1.response_content
11+
assert len(err1.response_content.get("ExceptionMessage", ""))

tests/test_auth.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,10 @@ def test_react_to_httperror_oracle_28000_raises(
198198
cleanup_mock = mock.Mock()
199199
monkeypatch.setattr(sa, "_cleanup_netrc", cleanup_mock)
200200

201-
err = StatbankAuthError("wrapped")
202-
err.response_content = {"ExceptionMessage": "ORA-28000: account locked"}
203-
201+
err = StatbankAuthError(
202+
"wrapped",
203+
response_content={"ExceptionMessage": "ORA-28000: account locked"},
204+
)
204205
with pytest.raises(StatbankAuthError) as exc:
205206
sa._react_to_httperror_should_retry(err) # noqa: SLF001
206207

@@ -224,8 +225,10 @@ def test_react_to_httperror_oracle_01017_returns_true_and_refreshes(
224225
get_auth_mock = mock.Mock(return_value=new_auth)
225226
monkeypatch.setattr(sa, "_get_auth", get_auth_mock)
226227

227-
err = StatbankAuthError("wrapped")
228-
err.response_content = {"ExceptionMessage": "ORA-01017: invalid username/password"}
228+
err = StatbankAuthError(
229+
"wrapped",
230+
response_content={"ExceptionMessage": "ORA-01017: invalid username/password"},
231+
)
229232

230233
should_retry = sa._react_to_httperror_should_retry(err) # noqa: SLF001
231234

@@ -250,7 +253,8 @@ def test_react_to_httperror_other_raises_original(
250253
with pytest.raises(StatbankAuthError) as exc:
251254
sa._react_to_httperror_should_retry(err) # noqa: SLF001
252255

253-
cleanup_mock.assert_called_once()
256+
# On a general error we dont want the cleanup to have been called, because we do not recognize the error
257+
assert not cleanup_mock.called
254258
# The method re-raises the same exception object when unhandled
255259
assert exc.value is err
256260

0 commit comments

Comments
 (0)