mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-11 18:01:04 +00:00
feat(timeout):
implement (class-bound, instance-bound, request-bound) session timeout for requests. fix docs config, fix aiohttp session docs links.
This commit is contained in:
parent
2adc19724d
commit
df4ba87dfc
6 changed files with 55 additions and 16 deletions
|
|
@ -132,7 +132,9 @@ class AiohttpSession(BaseSession):
|
||||||
url = self.api.api_url(token=token, method=request.method)
|
url = self.api.api_url(token=token, method=request.method)
|
||||||
form = self.build_form_data(request)
|
form = self.build_form_data(request)
|
||||||
|
|
||||||
async with session.post(url, data=form, timeout=call.request_timeout) as resp:
|
async with session.post(
|
||||||
|
url, data=form, timeout=call.request_timeout or self.timeout
|
||||||
|
) as resp:
|
||||||
raw_result = await resp.json(loads=self.json_loads)
|
raw_result = await resp.json(loads=self.json_loads)
|
||||||
|
|
||||||
response = call.build_response(raw_result)
|
response = call.build_response(raw_result)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import abc
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import Any, AsyncGenerator, Callable, Optional, Type, TypeVar, Union
|
from typing import Any, AsyncGenerator, Callable, ClassVar, Optional, Type, TypeVar, Union
|
||||||
|
|
||||||
from aiogram.utils.exceptions import TelegramAPIError
|
from aiogram.utils.exceptions import TelegramAPIError
|
||||||
|
|
||||||
|
|
@ -12,14 +12,18 @@ from ...methods import Response, TelegramMethod
|
||||||
from ..telegram import PRODUCTION, TelegramAPIServer
|
from ..telegram import PRODUCTION, TelegramAPIServer
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
_JSON_LOADS = Callable[..., Any]
|
_JsonLoads = Callable[..., Any]
|
||||||
_JSON_DUMPS = Callable[..., str]
|
_JsonDumps = Callable[..., str]
|
||||||
|
|
||||||
|
|
||||||
class BaseSession(abc.ABC):
|
class BaseSession(abc.ABC):
|
||||||
|
# global session timeout
|
||||||
|
default_timeout: ClassVar[float] = 60.0
|
||||||
|
|
||||||
_api: TelegramAPIServer
|
_api: TelegramAPIServer
|
||||||
_json_loads: _JSON_LOADS
|
_json_loads: _JsonLoads
|
||||||
_json_dumps: _JSON_DUMPS
|
_json_dumps: _JsonDumps
|
||||||
|
_timeout: float
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api(self) -> TelegramAPIServer:
|
def api(self) -> TelegramAPIServer:
|
||||||
|
|
@ -30,21 +34,33 @@ class BaseSession(abc.ABC):
|
||||||
self._api = value
|
self._api = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def json_loads(self) -> _JSON_LOADS:
|
def json_loads(self) -> _JsonLoads:
|
||||||
return getattr(self, "_json_loads", json.loads) # type: ignore
|
return getattr(self, "_json_loads", json.loads) # type: ignore
|
||||||
|
|
||||||
@json_loads.setter
|
@json_loads.setter
|
||||||
def json_loads(self, value: _JSON_LOADS) -> None:
|
def json_loads(self, value: _JsonLoads) -> None:
|
||||||
self._json_loads = value # type: ignore
|
self._json_loads = value # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def json_dumps(self) -> _JSON_DUMPS:
|
def json_dumps(self) -> _JsonDumps:
|
||||||
return getattr(self, "_json_dumps", json.dumps) # type: ignore
|
return getattr(self, "_json_dumps", json.dumps) # type: ignore
|
||||||
|
|
||||||
@json_dumps.setter
|
@json_dumps.setter
|
||||||
def json_dumps(self, value: _JSON_DUMPS) -> None:
|
def json_dumps(self, value: _JsonDumps) -> None:
|
||||||
self._json_dumps = value # type: ignore
|
self._json_dumps = value # type: ignore
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timeout(self) -> float:
|
||||||
|
return getattr(self, "_timeout", self.__class__.default_timeout) # type: ignore
|
||||||
|
|
||||||
|
@timeout.setter
|
||||||
|
def timeout(self, value: float) -> None:
|
||||||
|
self._timeout = value
|
||||||
|
|
||||||
|
@timeout.deleter
|
||||||
|
def timeout(self) -> None:
|
||||||
|
del self._timeout
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def raise_for_status(cls, response: Response[T]) -> None:
|
def raise_for_status(cls, response: Response[T]) -> None:
|
||||||
if response.ok:
|
if response.ok:
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ if TYPE_CHECKING: # pragma: no cover
|
||||||
from ..client.bot import Bot
|
from ..client.bot import Bot
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
DEFAULT_REQUEST_TIMEOUT_SECONDS = 60.0
|
|
||||||
|
|
||||||
|
|
||||||
class Request(BaseModel):
|
class Request(BaseModel):
|
||||||
|
|
@ -56,7 +55,7 @@ class TelegramMethod(abc.ABC, BaseModel, Generic[T]):
|
||||||
def build_request(self) -> Request: # pragma: no cover
|
def build_request(self) -> Request: # pragma: no cover
|
||||||
pass
|
pass
|
||||||
|
|
||||||
request_timeout: float = DEFAULT_REQUEST_TIMEOUT_SECONDS
|
request_timeout: Optional[float] = None
|
||||||
|
|
||||||
def dict(self, **kwargs: Any) -> Any:
|
def dict(self, **kwargs: Any) -> Any:
|
||||||
# override dict of pydantic.BaseModel to overcome exporting request_timeout field
|
# override dict of pydantic.BaseModel to overcome exporting request_timeout field
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Aiohttp session
|
# Aiohttp session
|
||||||
|
|
||||||
AiohttpSession represents a wrapper-class around `ClientSession` from [aiohttp]('https://pypi.org/project/aiohttp/')
|
AiohttpSession represents a wrapper-class around `ClientSession` from [aiohttp](https://pypi.org/project/aiohttp/ "PyPi repository"){target=_blank}
|
||||||
|
|
||||||
Currently `AiohttpSession` is a default session used in `aiogram.Bot`
|
Currently `AiohttpSession` is a default session used in `aiogram.Bot`
|
||||||
|
|
||||||
|
|
@ -17,7 +17,7 @@ Bot('token', session=session)
|
||||||
|
|
||||||
## Proxy requests in AiohttpSession
|
## Proxy requests in AiohttpSession
|
||||||
|
|
||||||
In order to use AiohttpSession with proxy connector you have to install [aiohttp-socks]('https://pypi.org/project/aiohttp-socks/')
|
In order to use AiohttpSession with proxy connector you have to install [aiohttp-socks](https://pypi.org/project/aiohttp-socks/ "PyPi repository"){target=_blank}
|
||||||
|
|
||||||
Binding session to bot:
|
Binding session to bot:
|
||||||
```python
|
```python
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ markdown_extensions:
|
||||||
- pymdownx.inlinehilite
|
- pymdownx.inlinehilite
|
||||||
- markdown_include.include:
|
- markdown_include.include:
|
||||||
base_path: docs
|
base_path: docs
|
||||||
|
- attr_list
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
- index.md
|
- index.md
|
||||||
|
|
|
||||||
|
|
@ -54,12 +54,33 @@ class TestBaseSession:
|
||||||
assert session.json_loads == custom_loads == session._json_loads
|
assert session.json_loads == custom_loads == session._json_loads
|
||||||
|
|
||||||
different_session = CustomSession()
|
different_session = CustomSession()
|
||||||
assert all(not hasattr(different_session, attr) for attr in ("_json_loads", "_json_dumps", "_api"))
|
assert all(
|
||||||
|
not hasattr(different_session, attr) for attr in ("_json_loads", "_json_dumps", "_api")
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_timeout(self):
|
||||||
|
session = CustomSession()
|
||||||
|
assert session.timeout == session.default_timeout == CustomSession.default_timeout
|
||||||
|
|
||||||
|
session.default_timeout = float(65.0_0) # mypy will complain
|
||||||
|
assert session.timeout != session.default_timeout
|
||||||
|
|
||||||
|
CustomSession.default_timeout = float(68.0_0)
|
||||||
|
assert session.timeout == CustomSession.default_timeout
|
||||||
|
|
||||||
|
session.timeout = float(71.0_0)
|
||||||
|
assert session.timeout != session.default_timeout
|
||||||
|
del session.timeout
|
||||||
|
CustomSession.default_timeout = session.default_timeout + 100
|
||||||
|
assert (
|
||||||
|
session.timeout != BaseSession.default_timeout
|
||||||
|
and session.timeout == CustomSession.default_timeout
|
||||||
|
)
|
||||||
|
|
||||||
def test_init_custom_api(self):
|
def test_init_custom_api(self):
|
||||||
api = TelegramAPIServer(
|
api = TelegramAPIServer(
|
||||||
base="http://example.com/{token}/{method}",
|
base="http://example.com/{token}/{method}",
|
||||||
file="http://example.com/{token}/file/{path{",
|
file="http://example.com/{token}/file/{path}",
|
||||||
)
|
)
|
||||||
session = CustomSession()
|
session = CustomSession()
|
||||||
session.api = api
|
session.api = api
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue