Skip to content

Commit

Permalink
0.5.0: Do not handle relogin internally, let the user code decide wha…
Browse files Browse the repository at this point in the history
…t to do
  • Loading branch information
nanomad committed Oct 6, 2024
1 parent a6b62fe commit 01c3eb1
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 179 deletions.
301 changes: 163 additions & 138 deletions poetry.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.poetry]
name = "saic_ismart_client_ng"
homepage = "https://github.com/SAIC-iSmart-API/saic-python-client-ng"
version = "0.3.0"
version = "0.4.0"
description = "SAIC next gen client library (MG iSMART)"
authors = [
"Giovanni Condello <[email protected]>",
Expand All @@ -22,17 +22,17 @@ classifiers = [
python = "^3.11"
pycryptodome = "^3.20.0"
httpx = "^0.27.0"
tenacity = "^8.2.3"
tenacity = "^9.0.0"
dacite = "^1.8.1"


[tool.poetry.dev-dependencies]
pytest = "^8.2.2"
mock = "^5.1.0"
coverage = "^7.5.4"
ruff = "^0.4.10"
ruff = "^0.6.0"
pytest-cov = "^5.0.0"
pytest-asyncio = "^0.23.7"
pytest-asyncio = "^0.24.0"
pytest-mock = "^3.14.0"


Expand Down
33 changes: 11 additions & 22 deletions src/saic_ismart_client_ng/api/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio
import datetime
import json
import logging
Expand Down Expand Up @@ -31,7 +30,7 @@ def __init__(
self.__configuration = configuration
self.__login_client = SaicLoginClient(configuration, listener=listener)
self.__api_client = SaicApiClient(configuration, listener=listener)
self.__token_expiration = None
self.__token_expiration: Optional[datetime.datetime] = None

@property
def configuration(self) -> SaicApiConfiguration:
Expand Down Expand Up @@ -137,12 +136,9 @@ async def deserialize(
error_message = json_data.get('message', 'Unknown error')
logger.debug(f"Response code: {return_code} {response.text}")

if return_code == 401:
await self._handle_logout(
error_message=error_message,
return_code=return_code,
response=response,
)
if return_code in (401, 403) or response.status_code in (401, 403):
self.logout()
raise SaicLogoutException(response.text, return_code)

if return_code in (2, 3, 7):
logger.error(f"API call return code is not acceptable: {return_code}: {response.text}")
Expand Down Expand Up @@ -197,21 +193,14 @@ async def deserialize(
else:
raise SaicApiException(f"Failed to deserialize response: {e}. Original json was {response.text}") from e

async def _handle_logout(self, *, error_message: str, return_code: int, response: httpx.Response):
logger.error(f"API client got de-authenticated. {return_code}: {response.text}")
self.logout()
relogin_delay = self.__configuration.relogin_delay
if relogin_delay:
logger.warning(f"Waiting {relogin_delay}s since we got logged out.")
await asyncio.sleep(relogin_delay)
logger.warning("Logging in since we got logged out")
await self.login()
raise SaicApiException(error_message, return_code=return_code)

def logout(self):
self.api_client.user_token = None
self.__token_expiration = None

def is_logged_in(self) -> bool:
return self.__token_expiration is not None \
and self.__token_expiration > datetime.datetime.now()


def saic_api_after_retry(retry_state):
wrapped_exception = retry_state.outcome.exception()
Expand All @@ -231,10 +220,10 @@ def saic_api_retry_policy(retry_state):
logger.debug("Retrying since we got SaicApiRetryException")
return True
elif isinstance(wrapped_exception, SaicLogoutException):
logger.error("Retrying since we got logged out")
return True
logger.error("Not retrying since we got logged out")
return False
elif isinstance(wrapped_exception, SaicApiException):
logger.error("NOT Retrying since we got a generic exception")
logger.error("Not retrying since we got a generic exception")
return False
else:
logger.error(f"Not retrying {retry_state.args} {wrapped_exception}")
Expand Down
6 changes: 0 additions & 6 deletions src/saic_ismart_client_ng/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ def __init__(
base_uri: str = "https://gateway-mg-eu.soimt.com/api.app/v1/",
tenant_id: str = "459771",
region: str = "eu",
relogin_delay: float = None,
sms_delivery_delay: float = 3.0,
):
self.__username = username
Expand All @@ -18,7 +17,6 @@ def __init__(
self.__base_uri = base_uri
self.__tenant_id = tenant_id
self.__region = region
self.__relogin_delay = relogin_delay
self.__sms_delivery_delay = sms_delivery_delay

@property
Expand Down Expand Up @@ -49,10 +47,6 @@ def tenant_id(self):
def region(self):
return self.__region

@property
def relogin_delay(self):
return self.__relogin_delay

@property
def sms_delivery_delay(self):
return self.__sms_delivery_delay
4 changes: 2 additions & 2 deletions src/saic_ismart_client_ng/net/client/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import httpx

from saic_ismart_client_ng.exceptions import SaicApiException
from saic_ismart_client_ng.exceptions import SaicLogoutException
from saic_ismart_client_ng.listener import SaicApiListener
from saic_ismart_client_ng.model import SaicApiConfiguration
from saic_ismart_client_ng.net.client import AbstractSaicClient
Expand All @@ -20,5 +20,5 @@ def __init__(

async def encrypt_request(self, modified_request: httpx.Request):
if not self.user_token:
raise SaicApiException("Client not authenticated, please call login first")
raise SaicLogoutException("Client not authenticated, please call login first", return_code=401)
await super().encrypt_request(modified_request)
2 changes: 1 addition & 1 deletion src/saic_ismart_client_ng/net/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def encrypt_response(
response_timestamp_ms: int,
base_uri: str,
tenant_id: str,
user_token: '',
user_token: str = '',
):
request_content = ""
request_path = str(original_request_url).replace(base_uri, "/")
Expand Down
4 changes: 2 additions & 2 deletions tests/security_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async def test_a_request_should_encrypt_properly():

await encrypt_httpx_request(modified_request=original_request, request_timestamp=ts, base_uri=base_uri,
region=region, tenant_id=tenant_id)
assert original_request != None
assert original_request is not None
assert region == original_request.headers['REGION']
assert tenant_id == original_request.headers['tenant-id']
assert 'app' == original_request.headers['User-Type']
Expand Down Expand Up @@ -78,7 +78,7 @@ async def test_a_request_should_decrypt_properly():
region=region, tenant_id=tenant_id)
decrypted = await decrypt_httpx_request(original_request, base_uri=base_uri)

assert decrypted != None
assert decrypted is not None
decrypted_json = json.loads(decrypted)
assert expected_json == decrypted_json

Expand Down
4 changes: 0 additions & 4 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def setUp(self):
"https://test-uri.com",
"123456",
"test_region",
10.0,
5.0
)

Expand All @@ -37,9 +36,6 @@ def test_tenant_id(self):
def test_region(self):
self.assertEqual(self.config.region, "test_region")

def test_relogin_delay(self):
self.assertEqual(self.config.relogin_delay, 10.0)

def test_sms_delivery_delay(self):
self.assertEqual(self.config.sms_delivery_delay, 5.0)

Expand Down

0 comments on commit 01c3eb1

Please sign in to comment.