Skip to content

Commit

Permalink
Merge pull request #50 from unmade/timeouts-with-timedelta
Browse files Browse the repository at this point in the history
Timeouts with timedelta
  • Loading branch information
unmade authored Mar 17, 2020
2 parents 8138f4f + 93c1f70 commit 21db90b
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 20 deletions.
8 changes: 7 additions & 1 deletion docs/drivers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,17 @@ Timeouts
You can set timeouts in seconds when creating a driver or
when making a request. The later will take precedences over driver settings.

By default timeout is ``5 minutes``.
By default timeout is ``30 seconds``.

Here is how you can change it:

.. code-block:: python
from datetime import timedelta
from apiwrappers import make_driver
driver = make_driver("requests", timeout=5)
# making a request with timeout set to 5 seconds
Expand All @@ -84,6 +87,9 @@ Here is how you can change it:
# making a request with timeout set to 2.5 seconds
driver.fetch(request, timeout=2.5)
# or more explicitly
driver.fetch(request, timeout=timedelta(minutes=1))
# timeout is disabled, wait infinitely
driver.fetch(request, timeout=None)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "apiwrappers"
version = "0.3.0"
version = "0.4.0"
description = "apiwrappers is a library for building API clients that work both with regular and async code"
keywords = ["api", "wrapper", "http", "client"]
readme = "README.rst"
Expand Down
13 changes: 8 additions & 5 deletions src/apiwrappers/drivers/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import asyncio
import ssl
from datetime import timedelta
from http.cookies import SimpleCookie
from ssl import SSLContext
from typing import Iterable, List, Optional, Tuple, Type, Union, cast
Expand All @@ -18,16 +19,14 @@
from apiwrappers.structures import CaseInsensitiveDict, NoValue
from apiwrappers.typedefs import ClientCert, Data, QueryParams, Timeout, Verify

DEFAULT_TIMEOUT = 5 * 60 # 5 minutes


class AioHttpDriver:
middleware = MiddlewareChain(Authentication)

def __init__(
self,
*middleware: Type[AsyncMiddleware],
timeout: Timeout = DEFAULT_TIMEOUT,
timeout: Timeout,
verify: Verify = True,
cert: ClientCert = None,
):
Expand Down Expand Up @@ -100,9 +99,13 @@ def _prepare_query_params(params: QueryParams) -> Tuple[Tuple[str, str], ...]:
query_params.append((key, value))
return tuple(query_params)

def _prepare_timeout(self, timeout: Union[Timeout, NoValue]) -> Timeout:
def _prepare_timeout(
self, timeout: Union[Timeout, NoValue]
) -> Union[int, float, None]:
if isinstance(timeout, NoValue):
return self.timeout
return self._prepare_timeout(self.timeout)
if isinstance(timeout, timedelta):
return timeout.total_seconds()
return timeout

@staticmethod
Expand Down
13 changes: 8 additions & 5 deletions src/apiwrappers/drivers/requests.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ssl
from datetime import timedelta
from http.cookies import SimpleCookie
from typing import Type, Union

Expand All @@ -13,16 +14,14 @@
from apiwrappers.structures import CaseInsensitiveDict, NoValue
from apiwrappers.typedefs import ClientCert, Timeout, Verify

DEFAULT_TIMEOUT = 5 * 60 # 5 minutes


class RequestsDriver:
middleware = MiddlewareChain(Authentication)

def __init__(
self,
*middleware: Type[Middleware],
timeout: Timeout = DEFAULT_TIMEOUT,
timeout: Timeout,
verify: Verify = True,
cert: ClientCert = None,
):
Expand Down Expand Up @@ -84,7 +83,11 @@ def fetch(
content=response.content,
)

def _prepare_timeout(self, timeout: Union[Timeout, NoValue]) -> Timeout:
def _prepare_timeout(
self, timeout: Union[Timeout, NoValue]
) -> Union[int, float, None]:
if isinstance(timeout, NoValue):
return self.timeout
return self._prepare_timeout(self.timeout)
if isinstance(timeout, timedelta):
return timeout.total_seconds()
return timeout
4 changes: 3 additions & 1 deletion src/apiwrappers/factories.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from __future__ import annotations

import importlib
from datetime import timedelta
from typing import Tuple, Type, Union, overload

from apiwrappers.compat import Literal
from apiwrappers.protocols import AsyncDriver, AsyncMiddleware, Driver, Middleware
from apiwrappers.typedefs import ClientCert, Timeout, Verify

DEFAULT_TIMEOUT = 5 * 60 # 5 minutes
DEFAULT_TIMEOUT = timedelta(seconds=30)

DRIVER_MAP = {
"requests": ("apiwrappers.drivers.requests", "RequestsDriver"),
"aiohttp": ("apiwrappers.drivers.aiohttp", "AioHttpDriver"),
Expand Down
3 changes: 2 additions & 1 deletion src/apiwrappers/typedefs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from datetime import timedelta
from typing import (
TYPE_CHECKING,
Any,
Expand Down Expand Up @@ -29,5 +30,5 @@
Files = Optional[Dict[str, FilesValue]]
Json = Union[str, int, float, bool, None, Mapping[str, Any], List[Any]]
QueryParams = Mapping[str, Optional[Iterable[str]]]
Timeout = Union[int, float, None]
Timeout = Union[int, float, None, timedelta]
Verify = Union[bool, str]
10 changes: 7 additions & 3 deletions tests/test_drivers/test_aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import json
import ssl
from datetime import timedelta
from http.cookies import SimpleCookie
from pathlib import Path
from typing import TYPE_CHECKING, Type
Expand Down Expand Up @@ -38,6 +39,7 @@
def aiohttp_driver(*middleware: Type[AsyncMiddleware], **kwargs) -> AioHttpDriver:
from apiwrappers.drivers.aiohttp import AioHttpDriver

kwargs.setdefault("timeout", 30)
return AioHttpDriver(*middleware, **kwargs)


Expand All @@ -53,15 +55,15 @@ async def read():
async def test_representation() -> None:
driver = aiohttp_driver()
setattr(driver, "_middleware", [])
assert repr(driver) == "AioHttpDriver(timeout=300, verify=True, cert=None)"
assert repr(driver) == "AioHttpDriver(timeout=30, verify=True, cert=None)"


async def test_representation_with_middleware() -> None:
driver = aiohttp_driver(RequestMiddleware, ResponseMiddleware)
assert repr(driver) == (
"AioHttpDriver("
"Authentication, RequestMiddleware, ResponseMiddleware, "
"timeout=300, verify=True, cert=None"
"timeout=30, verify=True, cert=None"
")"
)

Expand All @@ -71,7 +73,7 @@ async def test_representation_with_verify_and_cert() -> None:
assert repr(driver) == (
"AioHttpDriver("
"Authentication, "
f"timeout=300, verify='{INVALID_CA_BUNDLE}', cert={CLIENT_CERT_PAIR}"
f"timeout=30, verify='{INVALID_CA_BUNDLE}', cert={CLIENT_CERT_PAIR}"
")"
)

Expand Down Expand Up @@ -207,6 +209,8 @@ async def test_send_json(httpbin) -> None:
(300, None, None),
(300, 1, 1),
(300, NoValue(), 300),
(timedelta(minutes=1), NoValue(), 60),
(None, timedelta(minutes=1), 60),
],
)
async def test_timeout(driver_timeout, fetch_timeout, expected) -> None:
Expand Down
10 changes: 7 additions & 3 deletions tests/test_drivers/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import json
import ssl
from datetime import timedelta
from http.cookies import SimpleCookie
from pathlib import Path
from typing import TYPE_CHECKING, Type
Expand Down Expand Up @@ -37,21 +38,22 @@
def requests_driver(*middleware: Type[Middleware], **kwargs) -> RequestsDriver:
from apiwrappers.drivers.requests import RequestsDriver

kwargs.setdefault("timeout", 30)
return RequestsDriver(*middleware, **kwargs)


def test_representation() -> None:
driver = requests_driver()
setattr(driver, "_middleware", [])
assert repr(driver) == "RequestsDriver(timeout=300, verify=True, cert=None)"
assert repr(driver) == "RequestsDriver(timeout=30, verify=True, cert=None)"


def test_representation_with_middleware() -> None:
driver = requests_driver(RequestMiddleware, ResponseMiddleware)
assert repr(driver) == (
"RequestsDriver("
"Authentication, RequestMiddleware, ResponseMiddleware, "
"timeout=300, verify=True, cert=None"
"timeout=30, verify=True, cert=None"
")"
)

Expand All @@ -61,7 +63,7 @@ def test_representation_with_verify_and_cert() -> None:
assert repr(driver) == (
"RequestsDriver("
"Authentication, "
f"timeout=300, verify='{INVALID_CA_BUNDLE}', cert={CLIENT_CERT_PAIR}"
f"timeout=30, verify='{INVALID_CA_BUNDLE}', cert={CLIENT_CERT_PAIR}"
")"
)

Expand Down Expand Up @@ -193,6 +195,8 @@ def test_send_json(httpbin) -> None:
(300, None, None),
(300, 1, 1),
(300, NoValue(), 300),
(timedelta(minutes=1), NoValue(), 60),
(None, timedelta(minutes=1), 60),
],
)
def test_timeout(driver_timeout, fetch_timeout, expected):
Expand Down

0 comments on commit 21db90b

Please sign in to comment.