Skip to content
Open
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
18 changes: 14 additions & 4 deletions jmapc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def __init__(
auth: Optional[RequestsAuth] = None,
last_event_id: Optional[str] = None,
event_source_config: Optional[EventSourceConfig] = None,
timeout: Optional[int] = None,
) -> None:
self._host: str = host
self._auth: Optional[RequestsAuth] = auth
Expand All @@ -89,6 +90,7 @@ def __init__(
event_source_config or EventSourceConfig()
)
self._events: Optional[sseclient.SSEClient] = None
self._timeout: int = timeout or REQUEST_TIMEOUT

@property
def events(self) -> Generator[Event, None, None]:
Expand All @@ -114,7 +116,7 @@ def requests_session(self) -> requests.Session:
@functools.cached_property
def jmap_session(self) -> Session:
r = self.requests_session.get(
f"https://{self._host}/.well-known/jmap", timeout=REQUEST_TIMEOUT
f"https://{self._host}/.well-known/jmap", timeout=self._timeout
)
r.raise_for_status()
session = Session.from_dict(r.json())
Expand All @@ -132,6 +134,14 @@ def account_id(self) -> str:
raise Exception("No primary account ID found")
return primary_account_id

@property
def timeout(self) -> int:
return self._timeout

@timeout.setter
def timeout(self, new_timeout: int) -> None:
self._timeout = new_timeout if new_timeout else REQUEST_TIMEOUT

def upload_blob(self, file_name: Union[str, Path]) -> Blob:
mime_type, mime_encoding = mimetypes.guess_type(file_name)
upload_url = self.jmap_session.upload_url.format(
Expand All @@ -143,7 +153,7 @@ def upload_blob(self, file_name: Union[str, Path]) -> Blob:
stream=True,
data=f,
headers={"Content-Type": mime_type},
timeout=REQUEST_TIMEOUT,
timeout=self._timeout,
)
r.raise_for_status()
return Blob.from_dict(r.json())
Expand All @@ -163,7 +173,7 @@ def download_attachment(
type=attachment.type,
)
r = self.requests_session.get(
blob_url, stream=True, timeout=REQUEST_TIMEOUT
blob_url, stream=True, timeout=self._timeout
)
r.raise_for_status()
with open(file_name, "wb") as f:
Expand Down Expand Up @@ -279,7 +289,7 @@ def _api_request(
self.jmap_session.api_url,
headers={"Content-Type": "application/json"},
data=raw_request,
timeout=REQUEST_TIMEOUT,
timeout=self._timeout,
)
r.raise_for_status()
log.debug(f"Received JMAP response {r.text}")
Expand Down
35 changes: 35 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import responses

from jmapc import Blob, Client, ClientError, EmailBodyPart, constants
from jmapc.client import REQUEST_TIMEOUT
from jmapc.auth import BearerAuth
from jmapc.methods import (
CoreEcho,
Expand Down Expand Up @@ -140,6 +141,40 @@ def test_jmap_session_capabilities_urns(
)


@pytest.mark.parametrize(
"test_client, expected_timeout",
(
(
Client.create_with_api_token(
host="jmapserver.it", api_token="myapikey", timeout=17
),
17,
),
(
Client.create_with_password(
host="myjmaphost.com", user="user", password="pwd"
),
REQUEST_TIMEOUT,
),
(Client(host="hostforjmap.de", auth=("user", "pwd"), timeout=3), 3),
(Client(host="hostforjmap.de", auth=("user", "pwd")), REQUEST_TIMEOUT),
),
)
def test_client_timeout(test_client: Client, expected_timeout: int) -> None:
assert test_client.timeout == expected_timeout
assert test_client._timeout == expected_timeout


def test_client_timeout_property(client: Client) -> None:
client.timeout = 78
assert client.timeout == 78
assert client._timeout == 78

client.timeout = 0
assert client.timeout == REQUEST_TIMEOUT
assert client._timeout == REQUEST_TIMEOUT


def test_client_request_updated_session(
client: Client, http_responses: responses.RequestsMock
) -> None:
Expand Down