Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/saic_ismart_client_ng/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ class SaicLogoutException(SaicApiException):
pass


class SaicApiClosedException(SaicApiException):
pass


class SaicApiRetryException(SaicApiException):
def __init__(
self, msg: str, *, event_id: str, return_code: int | None = None
Expand Down
6 changes: 6 additions & 0 deletions src/saic_ismart_client_ng/net/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import httpx
from httpx import Request, Response, Timeout

from saic_ismart_client_ng.exceptions import SaicApiClosedException
from saic_ismart_client_ng.net.httpx import (
decrypt_httpx_response,
encrypt_httpx_request,
Expand All @@ -27,6 +28,7 @@ def __init__(
self.__listener = listener
self.__logger = logging.getLogger(__name__)
self.__user_token: str = ""
self.__closed = False
self.__client = httpx.AsyncClient(
timeout=Timeout(timeout=configuration.read_timeout),
event_hooks={
Expand All @@ -36,9 +38,13 @@ def __init__(
)

async def send(self, request: Request) -> Response:
if self.__closed:
msg = "The API client has been closed and cannot be reused"
raise SaicApiClosedException(msg)
return await self.__client.send(request)

async def close(self) -> None:
self.__closed = True
await self.__client.aclose()

@property
Expand Down
21 changes: 18 additions & 3 deletions tests/test_close.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
from __future__ import annotations

import unittest

import pytest

from saic_ismart_client_ng import SaicApi
from saic_ismart_client_ng.exceptions import SaicApiClosedException
from saic_ismart_client_ng.model import SaicApiConfiguration


def _build_api() -> SaicApi:
return SaicApi(
SaicApiConfiguration(username="user", password="pass"), # noqa: S106
)


class TestClose(unittest.IsolatedAsyncioTestCase):
async def test_close_is_idempotent(self) -> None:
api = SaicApi(
SaicApiConfiguration(username="user", password="pass"),
)
api = _build_api()
await api.close()
await api.close()

async def test_login_after_close_raises(self) -> None:
api = _build_api()
await api.close()
with pytest.raises(SaicApiClosedException):
await api.login()
Loading