mirror of
https://github.com/aiogram/aiogram.git
synced 2025-12-12 18:19:34 +00:00
Rework session DI and files path wrapper
This commit is contained in:
parent
1357a7a91b
commit
2620a6547c
9 changed files with 98 additions and 40 deletions
1
CHANGES/776.misc
Normal file
1
CHANGES/776.misc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Check :code:`destiny` in case of no :code:`with_destiny` enabled in RedisStorage key builder
|
||||
1
CHANGES/778.misc
Normal file
1
CHANGES/778.misc
Normal file
|
|
@ -0,0 +1 @@
|
|||
Stop using feature from #336. From now settings of client-session should be placed as initializer arguments instead of changing instance attributes.
|
||||
2
CHANGES/779.misc
Normal file
2
CHANGES/779.misc
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
Make TelegramAPIServer files wrapper in local mode bi-directional (server-client, client-server)
|
||||
Now you can convert local path to server path and server path to local path.
|
||||
|
|
@ -270,7 +270,7 @@ class Bot(ContextInstanceMixin["Bot"]):
|
|||
close_stream = False
|
||||
if self.session.api.is_local:
|
||||
stream = self.__aiofiles_reader(
|
||||
self.session.api.wrap_local_file(file_path), chunk_size=chunk_size
|
||||
str(self.session.api.wrap_local_file.to_local(file_path)), chunk_size=chunk_size
|
||||
)
|
||||
close_stream = True
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ def _prepare_connector(chain_or_plain: _ProxyType) -> Tuple[Type["TCPConnector"]
|
|||
|
||||
|
||||
class AiohttpSession(BaseSession):
|
||||
def __init__(self, proxy: Optional[_ProxyType] = None):
|
||||
super().__init__()
|
||||
def __init__(self, proxy: Optional[_ProxyType] = None, **kwargs: Any) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self._session: Optional[ClientSession] = None
|
||||
self._connector_type: Type[TCPConnector] = TCPConnector
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from typing import (
|
|||
AsyncGenerator,
|
||||
Awaitable,
|
||||
Callable,
|
||||
ClassVar,
|
||||
Final,
|
||||
List,
|
||||
Optional,
|
||||
Type,
|
||||
|
|
@ -33,7 +33,6 @@ from aiogram.exceptions import (
|
|||
TelegramServerError,
|
||||
TelegramUnauthorizedError,
|
||||
)
|
||||
from aiogram.utils.helper import Default
|
||||
|
||||
from ...methods import Response, TelegramMethod
|
||||
from ...methods.base import TelegramType
|
||||
|
|
@ -58,20 +57,29 @@ RequestMiddlewareType = Union[
|
|||
],
|
||||
]
|
||||
|
||||
DEFAULT_TIMEOUT: Final[float] = 60.0
|
||||
|
||||
|
||||
class BaseSession(abc.ABC):
|
||||
api: Default[TelegramAPIServer] = Default(PRODUCTION)
|
||||
"""Telegram Bot API URL patterns"""
|
||||
json_loads: Default[_JsonLoads] = Default(json.loads)
|
||||
"""JSON loader"""
|
||||
json_dumps: Default[_JsonDumps] = Default(json.dumps)
|
||||
"""JSON dumper"""
|
||||
default_timeout: ClassVar[float] = 60.0
|
||||
"""Default timeout"""
|
||||
timeout: Default[float] = Default(fget=lambda self: float(self.__class__.default_timeout))
|
||||
"""Session scope request timeout"""
|
||||
def __init__(
|
||||
self,
|
||||
api: TelegramAPIServer = PRODUCTION,
|
||||
json_loads: _JsonLoads = json.loads,
|
||||
json_dumps: _JsonDumps = json.dumps,
|
||||
timeout: float = DEFAULT_TIMEOUT,
|
||||
) -> None:
|
||||
"""
|
||||
|
||||
:param api: Telegram Bot API URL patterns
|
||||
:param json_loads: JSON loader
|
||||
:param json_dumps: JSON dumper
|
||||
:param timeout: Session scope request timeout
|
||||
"""
|
||||
self.api = api
|
||||
self.json_loads = json_loads
|
||||
self.json_dumps = json_dumps
|
||||
self.timeout = timeout
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.middlewares: List[RequestMiddlewareType[TelegramObject]] = []
|
||||
|
||||
def check_response(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,45 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Protocol
|
||||
from pathlib import Path
|
||||
from typing import Any, Union
|
||||
|
||||
|
||||
class WrapLocalFileCallbackCallbackProtocol(Protocol): # pragma: no cover
|
||||
def __call__(self, value: str) -> str:
|
||||
class FilesPathWrapper(ABC):
|
||||
@abstractmethod
|
||||
def to_local(self, path: Union[Path, str]) -> Union[Path, str]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def to_server(self, path: Union[Path, str]) -> Union[Path, str]:
|
||||
pass
|
||||
|
||||
|
||||
class BareFilesPathWrapper(FilesPathWrapper):
|
||||
def to_local(self, path: Union[Path, str]) -> Union[Path, str]:
|
||||
return path
|
||||
|
||||
def to_server(self, path: Union[Path, str]) -> Union[Path, str]:
|
||||
return path
|
||||
|
||||
|
||||
class SimpleFilesPathWrapper(FilesPathWrapper):
|
||||
def __init__(self, server_path: Path, local_path: Path) -> None:
|
||||
self.server_path = server_path
|
||||
self.local_path = local_path
|
||||
|
||||
@classmethod
|
||||
def _resolve(
|
||||
cls, base1: Union[Path, str], base2: Union[Path, str], value: Union[Path, str]
|
||||
) -> Path:
|
||||
relative = Path(value).relative_to(base1)
|
||||
return base2 / relative
|
||||
|
||||
def to_local(self, path: Union[Path, str]) -> Union[Path, str]:
|
||||
return self._resolve(base1=self.server_path, base2=self.local_path, value=path)
|
||||
|
||||
def to_server(self, path: Union[Path, str]) -> Union[Path, str]:
|
||||
return self._resolve(base1=self.local_path, base2=self.server_path, value=path)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TelegramAPIServer:
|
||||
|
|
@ -19,7 +53,7 @@ class TelegramAPIServer:
|
|||
"""Files URL"""
|
||||
is_local: bool = False
|
||||
"""Mark this server is in `local mode <https://core.telegram.org/bots/api#using-a-local-bot-api-server>`_."""
|
||||
wrap_local_file: WrapLocalFileCallbackCallbackProtocol = lambda v: v
|
||||
wrap_local_file: FilesPathWrapper = BareFilesPathWrapper()
|
||||
"""Callback to wrap files path in local mode"""
|
||||
|
||||
def api_url(self, token: str, method: str) -> str:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,11 @@
|
|||
from aiogram.client.telegram import PRODUCTION, TelegramAPIServer
|
||||
from pathlib import Path
|
||||
|
||||
from aiogram.client.telegram import (
|
||||
PRODUCTION,
|
||||
BareFilesPathWrapper,
|
||||
SimpleFilesPathWrapper,
|
||||
TelegramAPIServer,
|
||||
)
|
||||
|
||||
|
||||
class TestAPIServer:
|
||||
|
|
@ -19,3 +26,27 @@ class TestAPIServer:
|
|||
assert method_url == "http://localhost:8081/bot42:TEST/apiMethod"
|
||||
assert file_url == "http://localhost:8081/file/bot42:TEST/path"
|
||||
assert local_server.is_local
|
||||
|
||||
|
||||
class TestBareFilesPathWrapper:
|
||||
def test_to_local(self):
|
||||
wrapper = BareFilesPathWrapper()
|
||||
assert wrapper.to_local("/path/to/file.dat") == "/path/to/file.dat"
|
||||
|
||||
def test_to_server(self):
|
||||
wrapper = BareFilesPathWrapper()
|
||||
assert wrapper.to_server("/path/to/file.dat") == "/path/to/file.dat"
|
||||
|
||||
|
||||
class TestSimpleFilesPathWrapper:
|
||||
def test_to_local(self):
|
||||
wrapper = SimpleFilesPathWrapper(Path("/etc/telegram-bot-api/data"), Path("/opt/app/data"))
|
||||
assert wrapper.to_local("/etc/telegram-bot-api/data/documents/file.dat") == Path(
|
||||
"/opt/app/data/documents/file.dat"
|
||||
)
|
||||
|
||||
def test_to_server(self):
|
||||
wrapper = SimpleFilesPathWrapper(Path("/etc/telegram-bot-api/data"), Path("/opt/app/data"))
|
||||
assert wrapper.to_server("/opt/app/data/documents/file.dat") == Path(
|
||||
"/etc/telegram-bot-api/data/documents/file.dat"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -74,25 +74,6 @@ class TestBaseSession:
|
|||
session.json_loads = custom_loads
|
||||
assert session.json_loads == custom_loads
|
||||
|
||||
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):
|
||||
api = TelegramAPIServer(
|
||||
base="http://example.com/{token}/{method}",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue