mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-28 03:05:25 +08:00
✨ Feature: 细化 driver 职责类型 (#2296)
This commit is contained in:
parent
807a86371d
commit
2e635370bb
@ -53,7 +53,7 @@ from nonebot.config import Env, Config
|
|||||||
from nonebot.log import logger as logger
|
from nonebot.log import logger as logger
|
||||||
from nonebot.adapters import Bot, Adapter
|
from nonebot.adapters import Bot, Adapter
|
||||||
from nonebot.utils import escape_tag, resolve_dot_notation
|
from nonebot.utils import escape_tag, resolve_dot_notation
|
||||||
from nonebot.drivers import Driver, ReverseDriver, combine_driver
|
from nonebot.drivers import Driver, ASGIMixin, combine_driver
|
||||||
|
|
||||||
try:
|
try:
|
||||||
__version__ = version("nonebot2")
|
__version__ = version("nonebot2")
|
||||||
@ -149,13 +149,13 @@ def get_adapters() -> Dict[str, Adapter]:
|
|||||||
|
|
||||||
|
|
||||||
def get_app() -> Any:
|
def get_app() -> Any:
|
||||||
"""获取全局 {ref}`nonebot.drivers.ReverseDriver` 对应的 Server App 对象。
|
"""获取全局 {ref}`nonebot.drivers.ASGIMixin` 对应的 Server App 对象。
|
||||||
|
|
||||||
返回:
|
返回:
|
||||||
Server App 对象
|
Server App 对象
|
||||||
|
|
||||||
异常:
|
异常:
|
||||||
AssertionError: 全局 Driver 对象不是 {ref}`nonebot.drivers.ReverseDriver` 类型
|
AssertionError: 全局 Driver 对象不是 {ref}`nonebot.drivers.ASGIMixin` 类型
|
||||||
ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化
|
ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化
|
||||||
({ref}`nonebot.init <nonebot.init>` 尚未调用)
|
({ref}`nonebot.init <nonebot.init>` 尚未调用)
|
||||||
|
|
||||||
@ -165,21 +165,19 @@ def get_app() -> Any:
|
|||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
assert isinstance(
|
assert isinstance(driver, ASGIMixin), "app object is only available for asgi driver"
|
||||||
driver, ReverseDriver
|
|
||||||
), "app object is only available for reverse driver"
|
|
||||||
return driver.server_app
|
return driver.server_app
|
||||||
|
|
||||||
|
|
||||||
def get_asgi() -> Any:
|
def get_asgi() -> Any:
|
||||||
"""获取全局 {ref}`nonebot.drivers.ReverseDriver` 对应
|
"""获取全局 {ref}`nonebot.drivers.ASGIMixin` 对应
|
||||||
[ASGI](https://asgi.readthedocs.io/) 对象。
|
[ASGI](https://asgi.readthedocs.io/) 对象。
|
||||||
|
|
||||||
返回:
|
返回:
|
||||||
ASGI 对象
|
ASGI 对象
|
||||||
|
|
||||||
异常:
|
异常:
|
||||||
AssertionError: 全局 Driver 对象不是 {ref}`nonebot.drivers.ReverseDriver` 类型
|
AssertionError: 全局 Driver 对象不是 {ref}`nonebot.drivers.ASGIMixin` 类型
|
||||||
ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化
|
ValueError: 全局 {ref}`nonebot.drivers.Driver` 对象尚未初始化
|
||||||
({ref}`nonebot.init <nonebot.init>` 尚未调用)
|
({ref}`nonebot.init <nonebot.init>` 尚未调用)
|
||||||
|
|
||||||
@ -190,7 +188,7 @@ def get_asgi() -> Any:
|
|||||||
"""
|
"""
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
assert isinstance(
|
assert isinstance(
|
||||||
driver, ReverseDriver
|
driver, ASGIMixin
|
||||||
), "asgi object is only available for reverse driver"
|
), "asgi object is only available for reverse driver"
|
||||||
return driver.asgi
|
return driver.asgi
|
||||||
|
|
||||||
|
@ -8,30 +8,40 @@ FrontMatter:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from nonebot.internal.driver import URL as URL
|
from nonebot.internal.driver import URL as URL
|
||||||
|
from nonebot.internal.driver import Mixin as Mixin
|
||||||
from nonebot.internal.driver import Driver as Driver
|
from nonebot.internal.driver import Driver as Driver
|
||||||
from nonebot.internal.driver import Cookies as Cookies
|
from nonebot.internal.driver import Cookies as Cookies
|
||||||
from nonebot.internal.driver import Request as Request
|
from nonebot.internal.driver import Request as Request
|
||||||
from nonebot.internal.driver import Response as Response
|
from nonebot.internal.driver import Response as Response
|
||||||
|
from nonebot.internal.driver import ASGIMixin as ASGIMixin
|
||||||
from nonebot.internal.driver import WebSocket as WebSocket
|
from nonebot.internal.driver import WebSocket as WebSocket
|
||||||
from nonebot.internal.driver import HTTPVersion as HTTPVersion
|
from nonebot.internal.driver import HTTPVersion as HTTPVersion
|
||||||
from nonebot.internal.driver import ForwardMixin as ForwardMixin
|
from nonebot.internal.driver import ForwardMixin as ForwardMixin
|
||||||
|
from nonebot.internal.driver import ReverseMixin as ReverseMixin
|
||||||
from nonebot.internal.driver import ForwardDriver as ForwardDriver
|
from nonebot.internal.driver import ForwardDriver as ForwardDriver
|
||||||
from nonebot.internal.driver import ReverseDriver as ReverseDriver
|
from nonebot.internal.driver import ReverseDriver as ReverseDriver
|
||||||
from nonebot.internal.driver import combine_driver as combine_driver
|
from nonebot.internal.driver import combine_driver as combine_driver
|
||||||
|
from nonebot.internal.driver import HTTPClientMixin as HTTPClientMixin
|
||||||
from nonebot.internal.driver import HTTPServerSetup as HTTPServerSetup
|
from nonebot.internal.driver import HTTPServerSetup as HTTPServerSetup
|
||||||
|
from nonebot.internal.driver import WebSocketClientMixin as WebSocketClientMixin
|
||||||
from nonebot.internal.driver import WebSocketServerSetup as WebSocketServerSetup
|
from nonebot.internal.driver import WebSocketServerSetup as WebSocketServerSetup
|
||||||
|
|
||||||
__autodoc__ = {
|
__autodoc__ = {
|
||||||
"URL": True,
|
"URL": True,
|
||||||
"Driver": True,
|
|
||||||
"Cookies": True,
|
"Cookies": True,
|
||||||
"Request": True,
|
"Request": True,
|
||||||
"Response": True,
|
"Response": True,
|
||||||
"WebSocket": True,
|
"WebSocket": True,
|
||||||
"HTTPVersion": True,
|
"HTTPVersion": True,
|
||||||
|
"Driver": True,
|
||||||
|
"Mixin": True,
|
||||||
"ForwardMixin": True,
|
"ForwardMixin": True,
|
||||||
"ForwardDriver": True,
|
"ForwardDriver": True,
|
||||||
|
"HTTPClientMixin": True,
|
||||||
|
"WebSocketClientMixin": True,
|
||||||
|
"ReverseMixin": True,
|
||||||
"ReverseDriver": True,
|
"ReverseDriver": True,
|
||||||
|
"ASGIMixin": True,
|
||||||
"combine_driver": True,
|
"combine_driver": True,
|
||||||
"HTTPServerSetup": True,
|
"HTTPServerSetup": True,
|
||||||
"WebSocketServerSetup": True,
|
"WebSocketServerSetup": True,
|
||||||
|
@ -16,14 +16,19 @@ FrontMatter:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
from typing import Type, AsyncGenerator
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import TYPE_CHECKING, AsyncGenerator
|
||||||
|
|
||||||
from nonebot.drivers import Request, Response
|
from nonebot.drivers import Request, Response
|
||||||
from nonebot.exception import WebSocketClosed
|
from nonebot.exception import WebSocketClosed
|
||||||
from nonebot.drivers.none import Driver as NoneDriver
|
from nonebot.drivers.none import Driver as NoneDriver
|
||||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||||
from nonebot.drivers import HTTPVersion, ForwardMixin, ForwardDriver, combine_driver
|
from nonebot.drivers import (
|
||||||
|
HTTPVersion,
|
||||||
|
HTTPClientMixin,
|
||||||
|
WebSocketClientMixin,
|
||||||
|
combine_driver,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@ -34,7 +39,7 @@ except ModuleNotFoundError as e: # pragma: no cover
|
|||||||
) from e
|
) from e
|
||||||
|
|
||||||
|
|
||||||
class Mixin(ForwardMixin):
|
class Mixin(HTTPClientMixin, WebSocketClientMixin):
|
||||||
"""AIOHTTP Mixin"""
|
"""AIOHTTP Mixin"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -172,5 +177,11 @@ class WebSocket(BaseWebSocket):
|
|||||||
await self.websocket.send_bytes(data)
|
await self.websocket.send_bytes(data)
|
||||||
|
|
||||||
|
|
||||||
Driver: Type[ForwardDriver] = combine_driver(NoneDriver, Mixin) # type: ignore
|
if TYPE_CHECKING:
|
||||||
"""AIOHTTP Driver"""
|
|
||||||
|
class Driver(Mixin, NoneDriver):
|
||||||
|
...
|
||||||
|
|
||||||
|
else:
|
||||||
|
Driver = combine_driver(NoneDriver, Mixin)
|
||||||
|
"""AIOHTTP Driver"""
|
||||||
|
@ -25,12 +25,14 @@ from typing import Any, Dict, List, Tuple, Union, Optional
|
|||||||
from pydantic import BaseSettings
|
from pydantic import BaseSettings
|
||||||
|
|
||||||
from nonebot.config import Env
|
from nonebot.config import Env
|
||||||
|
from nonebot.drivers import ASGIMixin
|
||||||
from nonebot.exception import WebSocketClosed
|
from nonebot.exception import WebSocketClosed
|
||||||
from nonebot.internal.driver import FileTypes
|
from nonebot.internal.driver import FileTypes
|
||||||
|
from nonebot.drivers import Driver as BaseDriver
|
||||||
from nonebot.config import Config as NoneBotConfig
|
from nonebot.config import Config as NoneBotConfig
|
||||||
from nonebot.drivers import Request as BaseRequest
|
from nonebot.drivers import Request as BaseRequest
|
||||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||||
from nonebot.drivers import ReverseDriver, HTTPServerSetup, WebSocketServerSetup
|
from nonebot.drivers import HTTPServerSetup, WebSocketServerSetup
|
||||||
|
|
||||||
from ._lifespan import LIFESPAN_FUNC, Lifespan
|
from ._lifespan import LIFESPAN_FUNC, Lifespan
|
||||||
|
|
||||||
@ -87,7 +89,7 @@ class Config(BaseSettings):
|
|||||||
extra = "ignore"
|
extra = "ignore"
|
||||||
|
|
||||||
|
|
||||||
class Driver(ReverseDriver):
|
class Driver(BaseDriver, ASGIMixin):
|
||||||
"""FastAPI 驱动框架。"""
|
"""FastAPI 驱动框架。"""
|
||||||
|
|
||||||
def __init__(self, env: Env, config: NoneBotConfig):
|
def __init__(self, env: Env, config: NoneBotConfig):
|
||||||
@ -179,7 +181,7 @@ class Driver(ReverseDriver):
|
|||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
"""使用 `uvicorn` 启动 FastAPI"""
|
"""使用 `uvicorn` 启动 FastAPI"""
|
||||||
super().run(host, port, app, **kwargs)
|
super().run(host, port, app=app, **kwargs)
|
||||||
LOGGING_CONFIG = {
|
LOGGING_CONFIG = {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"disable_existing_loggers": False,
|
"disable_existing_loggers": False,
|
||||||
|
@ -15,18 +15,15 @@ FrontMatter:
|
|||||||
description: nonebot.drivers.httpx 模块
|
description: nonebot.drivers.httpx 模块
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
from typing import Type, AsyncGenerator
|
|
||||||
from contextlib import asynccontextmanager
|
|
||||||
|
|
||||||
from nonebot.drivers.none import Driver as NoneDriver
|
from nonebot.drivers.none import Driver as NoneDriver
|
||||||
from nonebot.drivers import (
|
from nonebot.drivers import (
|
||||||
Request,
|
Request,
|
||||||
Response,
|
Response,
|
||||||
WebSocket,
|
|
||||||
HTTPVersion,
|
HTTPVersion,
|
||||||
ForwardMixin,
|
HTTPClientMixin,
|
||||||
ForwardDriver,
|
|
||||||
combine_driver,
|
combine_driver,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,7 +36,7 @@ except ModuleNotFoundError as e: # pragma: no cover
|
|||||||
) from e
|
) from e
|
||||||
|
|
||||||
|
|
||||||
class Mixin(ForwardMixin):
|
class Mixin(HTTPClientMixin):
|
||||||
"""HTTPX Mixin"""
|
"""HTTPX Mixin"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -72,12 +69,12 @@ class Mixin(ForwardMixin):
|
|||||||
request=setup,
|
request=setup,
|
||||||
)
|
)
|
||||||
|
|
||||||
@override
|
|
||||||
@asynccontextmanager
|
|
||||||
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
|
|
||||||
async with super().websocket(setup) as ws:
|
|
||||||
yield ws
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
Driver: Type[ForwardDriver] = combine_driver(NoneDriver, Mixin) # type: ignore
|
class Driver(Mixin, NoneDriver):
|
||||||
"""HTTPX Driver"""
|
...
|
||||||
|
|
||||||
|
else:
|
||||||
|
Driver = combine_driver(NoneDriver, Mixin)
|
||||||
|
"""HTTPX Driver"""
|
||||||
|
@ -34,12 +34,14 @@ from typing import (
|
|||||||
from pydantic import BaseSettings
|
from pydantic import BaseSettings
|
||||||
|
|
||||||
from nonebot.config import Env
|
from nonebot.config import Env
|
||||||
|
from nonebot.drivers import ASGIMixin
|
||||||
from nonebot.exception import WebSocketClosed
|
from nonebot.exception import WebSocketClosed
|
||||||
from nonebot.internal.driver import FileTypes
|
from nonebot.internal.driver import FileTypes
|
||||||
|
from nonebot.drivers import Driver as BaseDriver
|
||||||
from nonebot.config import Config as NoneBotConfig
|
from nonebot.config import Config as NoneBotConfig
|
||||||
from nonebot.drivers import Request as BaseRequest
|
from nonebot.drivers import Request as BaseRequest
|
||||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||||
from nonebot.drivers import ReverseDriver, HTTPServerSetup, WebSocketServerSetup
|
from nonebot.drivers import HTTPServerSetup, WebSocketServerSetup
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import uvicorn
|
import uvicorn
|
||||||
@ -89,7 +91,7 @@ class Config(BaseSettings):
|
|||||||
extra = "ignore"
|
extra = "ignore"
|
||||||
|
|
||||||
|
|
||||||
class Driver(ReverseDriver):
|
class Driver(BaseDriver, ASGIMixin):
|
||||||
"""Quart 驱动框架"""
|
"""Quart 驱动框架"""
|
||||||
|
|
||||||
def __init__(self, env: Env, config: NoneBotConfig):
|
def __init__(self, env: Env, config: NoneBotConfig):
|
||||||
|
@ -19,14 +19,14 @@ import logging
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from typing_extensions import ParamSpec, override
|
from typing_extensions import ParamSpec, override
|
||||||
from typing import Type, Union, TypeVar, Callable, Awaitable, AsyncGenerator
|
from typing import TYPE_CHECKING, Union, TypeVar, Callable, Awaitable, AsyncGenerator
|
||||||
|
|
||||||
|
from nonebot.drivers import Request
|
||||||
from nonebot.log import LoguruHandler
|
from nonebot.log import LoguruHandler
|
||||||
from nonebot.drivers import Request, Response
|
|
||||||
from nonebot.exception import WebSocketClosed
|
from nonebot.exception import WebSocketClosed
|
||||||
from nonebot.drivers.none import Driver as NoneDriver
|
from nonebot.drivers.none import Driver as NoneDriver
|
||||||
from nonebot.drivers import WebSocket as BaseWebSocket
|
from nonebot.drivers import WebSocket as BaseWebSocket
|
||||||
from nonebot.drivers import ForwardMixin, ForwardDriver, combine_driver
|
from nonebot.drivers import WebSocketClientMixin, combine_driver
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from websockets.exceptions import ConnectionClosed
|
from websockets.exceptions import ConnectionClosed
|
||||||
@ -58,7 +58,7 @@ def catch_closed(func: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]:
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
class Mixin(ForwardMixin):
|
class Mixin(WebSocketClientMixin):
|
||||||
"""Websockets Mixin"""
|
"""Websockets Mixin"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -66,10 +66,6 @@ class Mixin(ForwardMixin):
|
|||||||
def type(self) -> str:
|
def type(self) -> str:
|
||||||
return "websockets"
|
return "websockets"
|
||||||
|
|
||||||
@override
|
|
||||||
async def request(self, setup: Request) -> Response:
|
|
||||||
return await super().request(setup)
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def websocket(self, setup: Request) -> AsyncGenerator["WebSocket", None]:
|
async def websocket(self, setup: Request) -> AsyncGenerator["WebSocket", None]:
|
||||||
@ -133,5 +129,11 @@ class WebSocket(BaseWebSocket):
|
|||||||
await self.websocket.send(data)
|
await self.websocket.send(data)
|
||||||
|
|
||||||
|
|
||||||
Driver: Type[ForwardDriver] = combine_driver(NoneDriver, Mixin) # type: ignore
|
if TYPE_CHECKING:
|
||||||
"""Websockets Driver"""
|
|
||||||
|
class Driver(Mixin, NoneDriver):
|
||||||
|
...
|
||||||
|
|
||||||
|
else:
|
||||||
|
Driver = combine_driver(NoneDriver, Mixin)
|
||||||
|
"""Websockets Driver"""
|
||||||
|
@ -7,10 +7,11 @@ from nonebot.internal.driver import (
|
|||||||
Driver,
|
Driver,
|
||||||
Request,
|
Request,
|
||||||
Response,
|
Response,
|
||||||
|
ASGIMixin,
|
||||||
WebSocket,
|
WebSocket,
|
||||||
ForwardDriver,
|
HTTPClientMixin,
|
||||||
ReverseDriver,
|
|
||||||
HTTPServerSetup,
|
HTTPServerSetup,
|
||||||
|
WebSocketClientMixin,
|
||||||
WebSocketServerSetup,
|
WebSocketServerSetup,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -72,26 +73,26 @@ class Adapter(abc.ABC):
|
|||||||
|
|
||||||
def setup_http_server(self, setup: HTTPServerSetup):
|
def setup_http_server(self, setup: HTTPServerSetup):
|
||||||
"""设置一个 HTTP 服务器路由配置"""
|
"""设置一个 HTTP 服务器路由配置"""
|
||||||
if not isinstance(self.driver, ReverseDriver):
|
if not isinstance(self.driver, ASGIMixin):
|
||||||
raise TypeError("Current driver does not support http server")
|
raise TypeError("Current driver does not support http server")
|
||||||
self.driver.setup_http_server(setup)
|
self.driver.setup_http_server(setup)
|
||||||
|
|
||||||
def setup_websocket_server(self, setup: WebSocketServerSetup):
|
def setup_websocket_server(self, setup: WebSocketServerSetup):
|
||||||
"""设置一个 WebSocket 服务器路由配置"""
|
"""设置一个 WebSocket 服务器路由配置"""
|
||||||
if not isinstance(self.driver, ReverseDriver):
|
if not isinstance(self.driver, ASGIMixin):
|
||||||
raise TypeError("Current driver does not support websocket server")
|
raise TypeError("Current driver does not support websocket server")
|
||||||
self.driver.setup_websocket_server(setup)
|
self.driver.setup_websocket_server(setup)
|
||||||
|
|
||||||
async def request(self, setup: Request) -> Response:
|
async def request(self, setup: Request) -> Response:
|
||||||
"""进行一个 HTTP 客户端请求"""
|
"""进行一个 HTTP 客户端请求"""
|
||||||
if not isinstance(self.driver, ForwardDriver):
|
if not isinstance(self.driver, HTTPClientMixin):
|
||||||
raise TypeError("Current driver does not support http client")
|
raise TypeError("Current driver does not support http client")
|
||||||
return await self.driver.request(setup)
|
return await self.driver.request(setup)
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
|
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
|
||||||
"""建立一个 WebSocket 客户端连接请求"""
|
"""建立一个 WebSocket 客户端连接请求"""
|
||||||
if not isinstance(self.driver, ForwardDriver):
|
if not isinstance(self.driver, WebSocketClientMixin):
|
||||||
raise TypeError("Current driver does not support websocket client")
|
raise TypeError("Current driver does not support websocket client")
|
||||||
async with self.driver.websocket(setup) as ws:
|
async with self.driver.websocket(setup) as ws:
|
||||||
yield ws
|
yield ws
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from .model import URL as URL
|
from .model import URL as URL
|
||||||
|
from .driver import Mixin as Mixin
|
||||||
from .model import RawURL as RawURL
|
from .model import RawURL as RawURL
|
||||||
from .driver import Driver as Driver
|
from .driver import Driver as Driver
|
||||||
from .model import Cookies as Cookies
|
from .model import Cookies as Cookies
|
||||||
@ -8,6 +9,7 @@ from .model import Response as Response
|
|||||||
from .model import DataTypes as DataTypes
|
from .model import DataTypes as DataTypes
|
||||||
from .model import FileTypes as FileTypes
|
from .model import FileTypes as FileTypes
|
||||||
from .model import WebSocket as WebSocket
|
from .model import WebSocket as WebSocket
|
||||||
|
from .driver import ASGIMixin as ASGIMixin
|
||||||
from .model import FilesTypes as FilesTypes
|
from .model import FilesTypes as FilesTypes
|
||||||
from .model import QueryTypes as QueryTypes
|
from .model import QueryTypes as QueryTypes
|
||||||
from .model import CookieTypes as CookieTypes
|
from .model import CookieTypes as CookieTypes
|
||||||
@ -17,9 +19,12 @@ from .model import HeaderTypes as HeaderTypes
|
|||||||
from .model import SimpleQuery as SimpleQuery
|
from .model import SimpleQuery as SimpleQuery
|
||||||
from .model import ContentTypes as ContentTypes
|
from .model import ContentTypes as ContentTypes
|
||||||
from .driver import ForwardMixin as ForwardMixin
|
from .driver import ForwardMixin as ForwardMixin
|
||||||
|
from .driver import ReverseMixin as ReverseMixin
|
||||||
from .model import QueryVariable as QueryVariable
|
from .model import QueryVariable as QueryVariable
|
||||||
from .driver import ForwardDriver as ForwardDriver
|
from .driver import ForwardDriver as ForwardDriver
|
||||||
from .driver import ReverseDriver as ReverseDriver
|
from .driver import ReverseDriver as ReverseDriver
|
||||||
from .driver import combine_driver as combine_driver
|
from .driver import combine_driver as combine_driver
|
||||||
from .model import HTTPServerSetup as HTTPServerSetup
|
from .model import HTTPServerSetup as HTTPServerSetup
|
||||||
|
from .driver import HTTPClientMixin as HTTPClientMixin
|
||||||
from .model import WebSocketServerSetup as WebSocketServerSetup
|
from .model import WebSocketServerSetup as WebSocketServerSetup
|
||||||
|
from .driver import WebSocketClientMixin as WebSocketClientMixin
|
||||||
|
@ -1,7 +1,19 @@
|
|||||||
import abc
|
import abc
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from typing_extensions import TypeAlias
|
||||||
from contextlib import AsyncExitStack, asynccontextmanager
|
from contextlib import AsyncExitStack, asynccontextmanager
|
||||||
from typing import TYPE_CHECKING, Any, Set, Dict, Type, Callable, AsyncGenerator
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
|
Any,
|
||||||
|
Set,
|
||||||
|
Dict,
|
||||||
|
Type,
|
||||||
|
Union,
|
||||||
|
TypeVar,
|
||||||
|
Callable,
|
||||||
|
AsyncGenerator,
|
||||||
|
overload,
|
||||||
|
)
|
||||||
|
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot.config import Env, Config
|
from nonebot.config import Env, Config
|
||||||
@ -21,11 +33,15 @@ if TYPE_CHECKING:
|
|||||||
from nonebot.internal.adapter import Bot, Adapter
|
from nonebot.internal.adapter import Bot, Adapter
|
||||||
|
|
||||||
|
|
||||||
|
D = TypeVar("D", bound="Driver")
|
||||||
|
|
||||||
BOT_HOOK_PARAMS = [DependParam, BotParam, DefaultParam]
|
BOT_HOOK_PARAMS = [DependParam, BotParam, DefaultParam]
|
||||||
|
|
||||||
|
|
||||||
class Driver(abc.ABC):
|
class Driver(abc.ABC):
|
||||||
"""Driver 基类。
|
"""驱动器基类。
|
||||||
|
|
||||||
|
驱动器控制框架的启动和停止,适配器的注册,以及机器人生命周期管理。
|
||||||
|
|
||||||
参数:
|
参数:
|
||||||
env: 包含环境信息的 Env 对象
|
env: 包含环境信息的 Env 对象
|
||||||
@ -45,6 +61,7 @@ class Driver(abc.ABC):
|
|||||||
self.config: Config = config
|
self.config: Config = config
|
||||||
"""全局配置对象"""
|
"""全局配置对象"""
|
||||||
self._bots: Dict[str, "Bot"] = {}
|
self._bots: Dict[str, "Bot"] = {}
|
||||||
|
self._bot_tasks: Set[asyncio.Task] = set()
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return (
|
return (
|
||||||
@ -94,6 +111,8 @@ class Driver(abc.ABC):
|
|||||||
f"<g>Loaded adapters: {escape_tag(', '.join(self._adapters))}</g>"
|
f"<g>Loaded adapters: {escape_tag(', '.join(self._adapters))}</g>"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.on_shutdown(self._cleanup)
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def on_startup(self, func: Callable) -> Callable:
|
def on_startup(self, func: Callable) -> Callable:
|
||||||
"""注册一个在驱动器启动时执行的函数"""
|
"""注册一个在驱动器启动时执行的函数"""
|
||||||
@ -156,7 +175,9 @@ class Driver(abc.ABC):
|
|||||||
"</bg #f8bbd0></r>"
|
"</bg #f8bbd0></r>"
|
||||||
)
|
)
|
||||||
|
|
||||||
asyncio.create_task(_run_hook(bot))
|
task = asyncio.create_task(_run_hook(bot))
|
||||||
|
task.add_done_callback(self._bot_tasks.discard)
|
||||||
|
self._bot_tasks.add(task)
|
||||||
|
|
||||||
def _bot_disconnect(self, bot: "Bot") -> None:
|
def _bot_disconnect(self, bot: "Bot") -> None:
|
||||||
"""在连接断开后,调用该函数来注销 bot 对象"""
|
"""在连接断开后,调用该函数来注销 bot 对象"""
|
||||||
@ -183,23 +204,49 @@ class Driver(abc.ABC):
|
|||||||
"</bg #f8bbd0></r>"
|
"</bg #f8bbd0></r>"
|
||||||
)
|
)
|
||||||
|
|
||||||
asyncio.create_task(_run_hook(bot))
|
task = asyncio.create_task(_run_hook(bot))
|
||||||
|
task.add_done_callback(self._bot_tasks.discard)
|
||||||
|
self._bot_tasks.add(task)
|
||||||
|
|
||||||
|
async def _cleanup(self) -> None:
|
||||||
|
"""清理驱动器资源"""
|
||||||
|
if self._bot_tasks:
|
||||||
|
logger.opt(colors=True).debug(
|
||||||
|
"<y>Waiting for running bot connection hooks...</y>"
|
||||||
|
)
|
||||||
|
await asyncio.gather(*self._bot_tasks, return_exceptions=True)
|
||||||
|
|
||||||
|
|
||||||
class ForwardMixin(abc.ABC):
|
class Mixin(abc.ABC):
|
||||||
"""客户端混入基类。"""
|
"""可与其他驱动器共用的混入基类。"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def type(self) -> str:
|
def type(self) -> str:
|
||||||
"""客户端驱动类型名称"""
|
"""混入驱动类型名称"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class ForwardMixin(Mixin):
|
||||||
|
"""客户端混入基类。"""
|
||||||
|
|
||||||
|
|
||||||
|
class ReverseMixin(Mixin):
|
||||||
|
"""服务端混入基类。"""
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPClientMixin(ForwardMixin):
|
||||||
|
"""HTTP 客户端混入基类。"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
async def request(self, setup: Request) -> Response:
|
async def request(self, setup: Request) -> Response:
|
||||||
"""发送一个 HTTP 请求"""
|
"""发送一个 HTTP 请求"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class WebSocketClientMixin(ForwardMixin):
|
||||||
|
"""WebSocket 客户端混入基类。"""
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
|
async def websocket(self, setup: Request) -> AsyncGenerator[WebSocket, None]:
|
||||||
@ -208,12 +255,11 @@ class ForwardMixin(abc.ABC):
|
|||||||
yield # used for static type checking's generator detection
|
yield # used for static type checking's generator detection
|
||||||
|
|
||||||
|
|
||||||
class ForwardDriver(Driver, ForwardMixin):
|
class ASGIMixin(ReverseMixin):
|
||||||
"""客户端基类。将客户端框架封装,以满足适配器使用。"""
|
"""ASGI 服务端基类。
|
||||||
|
|
||||||
|
将后端框架封装,以满足适配器使用。
|
||||||
class ReverseDriver(Driver):
|
"""
|
||||||
"""服务端基类。将后端框架封装,以满足适配器使用。"""
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
@ -238,18 +284,49 @@ class ReverseDriver(Driver):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
def combine_driver(driver: Type[Driver], *mixins: Type[ForwardMixin]) -> Type[Driver]:
|
ForwardDriver: TypeAlias = ForwardMixin
|
||||||
|
"""支持客户端请求的驱动器。
|
||||||
|
|
||||||
|
**Deprecated**,请使用 {ref}`nonebot.drivers.ForwardMixin` 或其子类代替。
|
||||||
|
"""
|
||||||
|
|
||||||
|
ReverseDriver: TypeAlias = ReverseMixin
|
||||||
|
"""支持服务端请求的驱动器。
|
||||||
|
|
||||||
|
**Deprecated**,请使用 {ref}`nonebot.drivers.ReverseMixin` 或其子类代替。
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
|
class CombinedDriver(Driver, Mixin):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def combine_driver(driver: Type[D]) -> Type[D]:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@overload
|
||||||
|
def combine_driver(driver: Type[D], *mixins: Type[Mixin]) -> Type["CombinedDriver"]:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
def combine_driver(
|
||||||
|
driver: Type[D], *mixins: Type[Mixin]
|
||||||
|
) -> Union[Type[D], Type["CombinedDriver"]]:
|
||||||
"""将一个驱动器和多个混入类合并。"""
|
"""将一个驱动器和多个混入类合并。"""
|
||||||
# check first
|
# check first
|
||||||
assert issubclass(driver, Driver), "`driver` must be subclass of Driver"
|
assert issubclass(driver, Driver), "`driver` must be subclass of Driver"
|
||||||
assert all(
|
assert all(
|
||||||
issubclass(m, ForwardMixin) for m in mixins
|
issubclass(m, Mixin) for m in mixins
|
||||||
), "`mixins` must be subclass of ForwardMixin"
|
), "`mixins` must be subclass of Mixin"
|
||||||
|
|
||||||
if not mixins:
|
if not mixins:
|
||||||
return driver
|
return driver
|
||||||
|
|
||||||
def type_(self: ForwardDriver) -> str:
|
def type_(self: "CombinedDriver") -> str:
|
||||||
return (
|
return (
|
||||||
driver.type.__get__(self)
|
driver.type.__get__(self)
|
||||||
+ "+"
|
+ "+"
|
||||||
@ -257,5 +334,5 @@ def combine_driver(driver: Type[Driver], *mixins: Type[ForwardMixin]) -> Type[Dr
|
|||||||
)
|
)
|
||||||
|
|
||||||
return type(
|
return type(
|
||||||
"CombinedDriver", (*mixins, driver, ForwardDriver), {"type": property(type_)}
|
"CombinedDriver", (*mixins, driver), {"type": property(type_)}
|
||||||
) # type: ignore
|
) # type: ignore
|
||||||
|
302
poetry.lock
generated
302
poetry.lock
generated
@ -16,13 +16,13 @@ pycares = ">=4.0.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aiofiles"
|
name = "aiofiles"
|
||||||
version = "23.1.0"
|
version = "23.2.1"
|
||||||
description = "File support for asyncio."
|
description = "File support for asyncio."
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7,<4.0"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "aiofiles-23.1.0-py3-none-any.whl", hash = "sha256:9312414ae06472eb6f1d163f555e466a23aed1c8f60c30cccf7121dba2e53eb2"},
|
{file = "aiofiles-23.2.1-py3-none-any.whl", hash = "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107"},
|
||||||
{file = "aiofiles-23.1.0.tar.gz", hash = "sha256:edd247df9a19e0db16534d4baaf536d6609a43e1de5401d7a4c1c148753a1635"},
|
{file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -204,13 +204,13 @@ requests = ">=2.21,<3.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-timeout"
|
name = "async-timeout"
|
||||||
version = "4.0.2"
|
version = "4.0.3"
|
||||||
description = "Timeout context manager for asyncio programs"
|
description = "Timeout context manager for asyncio programs"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"},
|
{file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
|
||||||
{file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"},
|
{file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -506,13 +506,13 @@ pycparser = "*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfgv"
|
name = "cfgv"
|
||||||
version = "3.3.1"
|
version = "3.4.0"
|
||||||
description = "Validate configuration and produce human readable error messages."
|
description = "Validate configuration and produce human readable error messages."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6.1"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
|
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
||||||
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
|
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -601,13 +601,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.6"
|
version = "8.1.7"
|
||||||
description = "Composable command line interface toolkit"
|
description = "Composable command line interface toolkit"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "click-8.1.6-py3-none-any.whl", hash = "sha256:fa244bb30b3b5ee2cae3da8f55c9e5e0c0e86093306301fb418eb9dc40fbded5"},
|
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||||
{file = "click-8.1.6.tar.gz", hash = "sha256:48ee849951919527a045bfe3bf7baa8a959c423134e1a5b98c05c20ba75a1cbd"},
|
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -626,71 +626,63 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coverage"
|
name = "coverage"
|
||||||
version = "7.2.7"
|
version = "7.3.0"
|
||||||
description = "Code coverage measurement for Python"
|
description = "Code coverage measurement for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
|
{file = "coverage-7.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db76a1bcb51f02b2007adacbed4c88b6dee75342c37b05d1822815eed19edee5"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
|
{file = "coverage-7.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c02cfa6c36144ab334d556989406837336c1d05215a9bdf44c0bc1d1ac1cb637"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
|
{file = "coverage-7.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477c9430ad5d1b80b07f3c12f7120eef40bfbf849e9e7859e53b9c93b922d2af"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
|
{file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2ee86ca75f9f96072295c5ebb4ef2a43cecf2870b0ca5e7a1cbdd929cf67e1"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
|
{file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68d8a0426b49c053013e631c0cdc09b952d857efa8f68121746b339912d27a12"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
|
{file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3eb0c93e2ea6445b2173da48cb548364f8f65bf68f3d090404080d338e3a689"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
|
{file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:90b6e2f0f66750c5a1178ffa9370dec6c508a8ca5265c42fbad3ccac210a7977"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
|
{file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96d7d761aea65b291a98c84e1250cd57b5b51726821a6f2f8df65db89363be51"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
|
{file = "coverage-7.3.0-cp310-cp310-win32.whl", hash = "sha256:63c5b8ecbc3b3d5eb3a9d873dec60afc0cd5ff9d9f1c75981d8c31cfe4df8527"},
|
||||||
{file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
|
{file = "coverage-7.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:97c44f4ee13bce914272589b6b41165bbb650e48fdb7bd5493a38bde8de730a1"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
|
{file = "coverage-7.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74c160285f2dfe0acf0f72d425f3e970b21b6de04157fc65adc9fd07ee44177f"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
|
{file = "coverage-7.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b543302a3707245d454fc49b8ecd2c2d5982b50eb63f3535244fd79a4be0c99d"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
|
{file = "coverage-7.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad0f87826c4ebd3ef484502e79b39614e9c03a5d1510cfb623f4a4a051edc6fd"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
|
{file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13c6cbbd5f31211d8fdb477f0f7b03438591bdd077054076eec362cf2207b4a7"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
|
{file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
|
{file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3c9834d5e3df9d2aba0275c9f67989c590e05732439b3318fa37a725dff51e74"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
|
{file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4c8e31cf29b60859876474034a83f59a14381af50cbe8a9dbaadbf70adc4b214"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
|
{file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7a9baf8e230f9621f8e1d00c580394a0aa328fdac0df2b3f8384387c44083c0f"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
|
{file = "coverage-7.3.0-cp311-cp311-win32.whl", hash = "sha256:ccc51713b5581e12f93ccb9c5e39e8b5d4b16776d584c0f5e9e4e63381356482"},
|
||||||
{file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
|
{file = "coverage-7.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:887665f00ea4e488501ba755a0e3c2cfd6278e846ada3185f42d391ef95e7e70"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
|
{file = "coverage-7.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d000a739f9feed900381605a12a61f7aaced6beae832719ae0d15058a1e81c1b"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
|
{file = "coverage-7.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59777652e245bb1e300e620ce2bef0d341945842e4eb888c23a7f1d9e143c446"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
|
{file = "coverage-7.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9737bc49a9255d78da085fa04f628a310c2332b187cd49b958b0e494c125071"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
|
{file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5247bab12f84a1d608213b96b8af0cbb30d090d705b6663ad794c2f2a5e5b9fe"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
|
{file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
|
{file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:85b7335c22455ec12444cec0d600533a238d6439d8d709d545158c1208483873"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
|
{file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:36ce5d43a072a036f287029a55b5c6a0e9bd73db58961a273b6dc11a2c6eb9c2"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
|
{file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:211a4576e984f96d9fce61766ffaed0115d5dab1419e4f63d6992b480c2bd60b"},
|
||||||
{file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
|
{file = "coverage-7.3.0-cp312-cp312-win32.whl", hash = "sha256:56afbf41fa4a7b27f6635bc4289050ac3ab7951b8a821bca46f5b024500e6321"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
|
{file = "coverage-7.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f297e0c1ae55300ff688568b04ff26b01c13dfbf4c9d2b7d0cb688ac60df479"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
|
{file = "coverage-7.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac0dec90e7de0087d3d95fa0533e1d2d722dcc008bc7b60e1143402a04c117c1"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
|
{file = "coverage-7.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:438856d3f8f1e27f8e79b5410ae56650732a0dcfa94e756df88c7e2d24851fcd"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
|
{file = "coverage-7.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1084393c6bda8875c05e04fce5cfe1301a425f758eb012f010eab586f1f3905e"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
|
{file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49ab200acf891e3dde19e5aa4b0f35d12d8b4bd805dc0be8792270c71bd56c54"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
|
{file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67e6bbe756ed458646e1ef2b0778591ed4d1fcd4b146fc3ba2feb1a7afd4254"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
|
{file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f39c49faf5344af36042b293ce05c0d9004270d811c7080610b3e713251c9b0"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
|
{file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7df91fb24c2edaabec4e0eee512ff3bc6ec20eb8dccac2e77001c1fe516c0c84"},
|
||||||
{file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
|
{file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:34f9f0763d5fa3035a315b69b428fe9c34d4fc2f615262d6be3d3bf3882fb985"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
|
{file = "coverage-7.3.0-cp38-cp38-win32.whl", hash = "sha256:bac329371d4c0d456e8d5f38a9b0816b446581b5f278474e416ea0c68c47dcd9"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
|
{file = "coverage-7.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b859128a093f135b556b4765658d5d2e758e1fae3e7cc2f8c10f26fe7005e543"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
|
{file = "coverage-7.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
|
{file = "coverage-7.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
|
{file = "coverage-7.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97af9554a799bd7c58c0179cc8dbf14aa7ab50e1fd5fa73f90b9b7215874ba28"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
|
{file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3558e5b574d62f9c46b76120a5c7c16c4612dc2644c3d48a9f4064a705eaee95"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
|
{file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37d5576d35fcb765fca05654f66aa71e2808d4237d026e64ac8b397ffa66a56a"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
|
{file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07ea61bcb179f8f05ffd804d2732b09d23a1238642bf7e51dad62082b5019b34"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
|
{file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80501d1b2270d7e8daf1b64b895745c3e234289e00d5f0e30923e706f110334e"},
|
||||||
{file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
|
{file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4eddd3153d02204f22aef0825409091a91bf2a20bce06fe0f638f5c19a85de54"},
|
||||||
{file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
|
{file = "coverage-7.3.0-cp39-cp39-win32.whl", hash = "sha256:2d22172f938455c156e9af2612650f26cceea47dc86ca048fa4e0b2d21646ad3"},
|
||||||
{file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
|
{file = "coverage-7.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:60f64e2007c9144375dd0f480a54d6070f00bb1a28f65c408370544091c9bc9e"},
|
||||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
|
{file = "coverage-7.3.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:5492a6ce3bdb15c6ad66cb68a0244854d9917478877a25671d70378bdc8562d0"},
|
||||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
|
{file = "coverage-7.3.0.tar.gz", hash = "sha256:49dbb19cdcafc130f597d9e04a29d0a032ceedf729e41b181f51cd170e6ee865"},
|
||||||
{file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
|
|
||||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
|
|
||||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
|
|
||||||
{file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
|
|
||||||
{file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
|
|
||||||
{file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
|
|
||||||
{file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
|
|
||||||
{file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -728,13 +720,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "exceptiongroup"
|
name = "exceptiongroup"
|
||||||
version = "1.1.2"
|
version = "1.1.3"
|
||||||
description = "Backport of PEP 654 (exception groups)"
|
description = "Backport of PEP 654 (exception groups)"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"},
|
{file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"},
|
||||||
{file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"},
|
{file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -756,17 +748,17 @@ testing = ["hatch", "pre-commit", "pytest", "tox"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastapi"
|
name = "fastapi"
|
||||||
version = "0.100.0"
|
version = "0.101.1"
|
||||||
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "fastapi-0.100.0-py3-none-any.whl", hash = "sha256:271662daf986da8fa98dc2b7c7f61c4abdfdccfb4786d79ed8b2878f172c6d5f"},
|
{file = "fastapi-0.101.1-py3-none-any.whl", hash = "sha256:aef5f8676eb1b8389952e1fe734abe20f04b71f6936afcc53b320ba79b686a4b"},
|
||||||
{file = "fastapi-0.100.0.tar.gz", hash = "sha256:acb5f941ea8215663283c10018323ba7ea737c571b67fc7e88e9469c7eb1d12e"},
|
{file = "fastapi-0.101.1.tar.gz", hash = "sha256:7b32000d14ca9992f7461117b81e4ef9ff0c07936af641b4fe40e67d5f9d63cb"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0"
|
pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
|
||||||
starlette = ">=0.27.0,<0.28.0"
|
starlette = ">=0.27.0,<0.28.0"
|
||||||
typing-extensions = ">=4.5.0"
|
typing-extensions = ">=4.5.0"
|
||||||
|
|
||||||
@ -1024,13 +1016,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "identify"
|
name = "identify"
|
||||||
version = "2.5.26"
|
version = "2.5.27"
|
||||||
description = "File identification library for Python"
|
description = "File identification library for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "identify-2.5.26-py2.py3-none-any.whl", hash = "sha256:c22a8ead0d4ca11f1edd6c9418c3220669b3b7533ada0a0ffa6cc0ef85cf9b54"},
|
{file = "identify-2.5.27-py2.py3-none-any.whl", hash = "sha256:fdb527b2dfe24602809b2201e033c2a113d7bdf716db3ca8e3243f735dcecaba"},
|
||||||
{file = "identify-2.5.26.tar.gz", hash = "sha256:7243800bce2f58404ed41b7c002e53d4d22bcf3ae1b7900c2d7aefd95394bf7f"},
|
{file = "identify-2.5.27.tar.gz", hash = "sha256:287b75b04a0e22d727bc9a41f0d4f3c1bcada97490fa6eabb5b28f0e9097e733"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -1324,13 +1316,13 @@ setuptools = "*"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nonebug"
|
name = "nonebug"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
description = "nonebot2 test framework"
|
description = "nonebot2 test framework"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8,<4.0"
|
python-versions = ">=3.8,<4.0"
|
||||||
files = [
|
files = [
|
||||||
{file = "nonebug-0.3.4-py3-none-any.whl", hash = "sha256:d6ebbde934d463141497e3162e26371b7e266d39f8cac0aa1bccc0e4542dd48b"},
|
{file = "nonebug-0.3.5-py3-none-any.whl", hash = "sha256:588831b08b3ea42d058874214bedae646e2ab8c1ec4ae1540ff789873107a8fa"},
|
||||||
{file = "nonebug-0.3.4.tar.gz", hash = "sha256:11d106dff3fe0d5fa029b9745f701770bcc484be048e72722bb17bb00f84753d"},
|
{file = "nonebug-0.3.5.tar.gz", hash = "sha256:4d4bf9448cd1cbfaaabaab73dbe4ac8757e86dd92a41ef79cdece8dd61e724e2"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -1381,29 +1373,29 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pathspec"
|
name = "pathspec"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
description = "Utility library for gitignore style pattern matching of file paths."
|
description = "Utility library for gitignore style pattern matching of file paths."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
|
{file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"},
|
||||||
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
|
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "3.9.1"
|
version = "3.10.0"
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "platformdirs-3.9.1-py3-none-any.whl", hash = "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f"},
|
{file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"},
|
||||||
{file = "platformdirs-3.9.1.tar.gz", hash = "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421"},
|
{file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
|
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
|
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
@ -1543,47 +1535,47 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "1.10.11"
|
version = "1.10.12"
|
||||||
description = "Data validation and settings management using python type hints"
|
description = "Data validation and settings management using python type hints"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"},
|
{file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"},
|
||||||
{file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"},
|
{file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"},
|
||||||
{file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"},
|
{file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"},
|
||||||
{file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"},
|
{file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"},
|
||||||
{file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"},
|
{file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"},
|
||||||
{file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"},
|
{file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"},
|
||||||
{file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"},
|
{file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"},
|
||||||
{file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"},
|
{file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"},
|
||||||
{file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"},
|
{file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"},
|
||||||
{file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"},
|
{file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"},
|
||||||
{file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"},
|
{file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"},
|
||||||
{file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"},
|
{file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"},
|
||||||
{file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"},
|
{file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"},
|
||||||
{file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"},
|
{file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"},
|
||||||
{file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"},
|
{file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"},
|
||||||
{file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"},
|
{file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"},
|
||||||
{file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"},
|
{file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"},
|
||||||
{file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"},
|
{file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"},
|
||||||
{file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"},
|
{file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"},
|
||||||
{file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"},
|
{file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"},
|
||||||
{file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"},
|
{file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"},
|
||||||
{file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"},
|
{file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"},
|
||||||
{file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"},
|
{file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"},
|
||||||
{file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"},
|
{file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"},
|
||||||
{file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"},
|
{file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"},
|
||||||
{file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"},
|
{file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"},
|
||||||
{file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"},
|
{file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"},
|
||||||
{file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"},
|
{file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"},
|
||||||
{file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"},
|
{file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"},
|
||||||
{file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"},
|
{file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"},
|
||||||
{file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"},
|
{file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"},
|
||||||
{file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"},
|
{file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"},
|
||||||
{file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"},
|
{file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"},
|
||||||
{file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"},
|
{file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"},
|
||||||
{file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"},
|
{file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"},
|
||||||
{file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"},
|
{file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -1821,18 +1813,18 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "68.0.0"
|
version = "68.1.2"
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"},
|
{file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"},
|
||||||
{file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"},
|
{file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||||
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1905,13 +1897,13 @@ zstd = ["zstandard (>=0.18.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uvicorn"
|
name = "uvicorn"
|
||||||
version = "0.23.1"
|
version = "0.23.2"
|
||||||
description = "The lightning-fast ASGI server."
|
description = "The lightning-fast ASGI server."
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "uvicorn-0.23.1-py3-none-any.whl", hash = "sha256:1d55d46b83ee4ce82b4e82f621f2050adb3eb7b5481c13f9af1744951cae2f1f"},
|
{file = "uvicorn-0.23.2-py3-none-any.whl", hash = "sha256:1f9be6558f01239d4fdf22ef8126c39cb1ad0addf76c40e760549d2c2f43ab53"},
|
||||||
{file = "uvicorn-0.23.1.tar.gz", hash = "sha256:da9b0c8443b2d7ee9db00a345f1eee6db7317432c9d4400f5049cc8d358383be"},
|
{file = "uvicorn-0.23.2.tar.gz", hash = "sha256:4d3cc12d7727ba72b64d12d3cc7743124074c0a69f7b201512fc50c3e3f1569a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -1975,23 +1967,23 @@ test = ["Cython (>=0.29.32,<0.30.0)", "aiohttp", "flake8 (>=3.9.2,<3.10.0)", "my
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "virtualenv"
|
name = "virtualenv"
|
||||||
version = "20.24.1"
|
version = "20.24.3"
|
||||||
description = "Virtual Python Environment builder"
|
description = "Virtual Python Environment builder"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "virtualenv-20.24.1-py3-none-any.whl", hash = "sha256:01aacf8decd346cf9a865ae85c0cdc7f64c8caa07ff0d8b1dfc1733d10677442"},
|
{file = "virtualenv-20.24.3-py3-none-any.whl", hash = "sha256:95a6e9398b4967fbcb5fef2acec5efaf9aa4972049d9ae41f95e0972a683fd02"},
|
||||||
{file = "virtualenv-20.24.1.tar.gz", hash = "sha256:2ef6a237c31629da6442b0bcaa3999748108c7166318d1f55cc9f8d7294e97bd"},
|
{file = "virtualenv-20.24.3.tar.gz", hash = "sha256:e5c3b4ce817b0b328af041506a2a299418c98747c4b1e68cb7527e74ced23efc"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
distlib = ">=0.3.6,<1"
|
distlib = ">=0.3.7,<1"
|
||||||
filelock = ">=3.12,<4"
|
filelock = ">=3.12.2,<4"
|
||||||
platformdirs = ">=3.5.1,<4"
|
platformdirs = ">=3.9.1,<4"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||||
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezer (>=0.4.6)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.8)", "time-machine (>=2.9)"]
|
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "watchfiles"
|
name = "watchfiles"
|
||||||
@ -2119,13 +2111,13 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "werkzeug"
|
name = "werkzeug"
|
||||||
version = "2.3.6"
|
version = "2.3.7"
|
||||||
description = "The comprehensive WSGI web application library."
|
description = "The comprehensive WSGI web application library."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "Werkzeug-2.3.6-py3-none-any.whl", hash = "sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890"},
|
{file = "werkzeug-2.3.7-py3-none-any.whl", hash = "sha256:effc12dba7f3bd72e605ce49807bbe692bd729c3bb122a3b91747a6ae77df528"},
|
||||||
{file = "Werkzeug-2.3.6.tar.gz", hash = "sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330"},
|
{file = "werkzeug-2.3.7.tar.gz", hash = "sha256:2b8c0e447b4b9dbcc85dd97b6eeb4dcbaf6c8b6c3be0bd654e25553e0a2157d8"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -2275,4 +2267,4 @@ websockets = ["websockets"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.8"
|
python-versions = "^3.8"
|
||||||
content-hash = "e125baa8903fb84e5955cf4e3d6f666496fa1d2c2b77b36309f81e4a6c02e242"
|
content-hash = "0fe5200eab7eb8fe06e86f9aa727297ba96646093dfe4940f8c0d93949956582"
|
||||||
|
@ -14,11 +14,9 @@ classifiers = [
|
|||||||
"Framework :: Robot Framework",
|
"Framework :: Robot Framework",
|
||||||
"Framework :: Robot Framework :: Library",
|
"Framework :: Robot Framework :: Library",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Programming Language :: Python :: 3"
|
"Programming Language :: Python :: 3",
|
||||||
]
|
|
||||||
packages = [
|
|
||||||
{ include = "nonebot" },
|
|
||||||
]
|
]
|
||||||
|
packages = [{ include = "nonebot" }]
|
||||||
include = ["nonebot/py.typed"]
|
include = ["nonebot/py.typed"]
|
||||||
|
|
||||||
[tool.poetry.urls]
|
[tool.poetry.urls]
|
||||||
@ -31,7 +29,7 @@ python = "^3.8"
|
|||||||
yarl = "^1.7.2"
|
yarl = "^1.7.2"
|
||||||
pygtrie = "^2.4.1"
|
pygtrie = "^2.4.1"
|
||||||
loguru = ">=0.6.0,<1.0.0"
|
loguru = ">=0.6.0,<1.0.0"
|
||||||
typing-extensions = ">=4.0.0,<5.0.0"
|
typing-extensions = ">=4.4.0,<5.0.0"
|
||||||
tomli = { version = "^2.0.1", python = "<3.11" }
|
tomli = { version = "^2.0.1", python = "<3.11" }
|
||||||
pydantic = { version = "^1.10.0", extras = ["dotenv"] }
|
pydantic = { version = "^1.10.0", extras = ["dotenv"] }
|
||||||
|
|
||||||
@ -40,7 +38,9 @@ Quart = { version = ">=0.18.0,<1.0.0", optional = true }
|
|||||||
fastapi = { version = ">=0.93.0,<1.0.0", optional = true }
|
fastapi = { version = ">=0.93.0,<1.0.0", optional = true }
|
||||||
aiohttp = { version = "^3.7.4", extras = ["speedups"], optional = true }
|
aiohttp = { version = "^3.7.4", extras = ["speedups"], optional = true }
|
||||||
httpx = { version = ">=0.20.0,<1.0.0", extras = ["http2"], optional = true }
|
httpx = { version = ">=0.20.0,<1.0.0", extras = ["http2"], optional = true }
|
||||||
uvicorn = { version = ">=0.20.0,<1.0.0", extras = ["standard"], optional = true }
|
uvicorn = { version = ">=0.20.0,<1.0.0", extras = [
|
||||||
|
"standard",
|
||||||
|
], optional = true }
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
isort = "^5.10.1"
|
isort = "^5.10.1"
|
||||||
@ -71,10 +71,7 @@ all = ["fastapi", "quart", "aiohttp", "httpx", "websockets", "uvicorn"]
|
|||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
asyncio_mode = "strict"
|
asyncio_mode = "strict"
|
||||||
addopts = "--cov=nonebot --cov-append --cov-report=term-missing"
|
addopts = "--cov=nonebot --cov-append --cov-report=term-missing"
|
||||||
filterwarnings = [
|
filterwarnings = ["error", "ignore::DeprecationWarning"]
|
||||||
"error",
|
|
||||||
"ignore::DeprecationWarning",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 88
|
line-length = 88
|
||||||
@ -107,7 +104,9 @@ mark-parentheses = false
|
|||||||
pythonVersion = "3.8"
|
pythonVersion = "3.8"
|
||||||
pythonPlatform = "All"
|
pythonPlatform = "All"
|
||||||
executionEnvironments = [
|
executionEnvironments = [
|
||||||
{ root = "./tests", extraPaths = ["./"] },
|
{ root = "./tests", extraPaths = [
|
||||||
|
"./",
|
||||||
|
] },
|
||||||
{ root = "./" },
|
{ root = "./" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -8,8 +8,10 @@ from nonebug import NONEBOT_INIT_KWARGS
|
|||||||
from werkzeug.serving import BaseWSGIServer, make_server
|
from werkzeug.serving import BaseWSGIServer, make_server
|
||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
from nonebot.drivers import URL
|
from nonebot.config import Env
|
||||||
from fake_server import request_handler
|
from fake_server import request_handler
|
||||||
|
from nonebot.drivers import URL, Driver
|
||||||
|
from nonebot import _resolve_combine_expr
|
||||||
|
|
||||||
os.environ["CONFIG_FROM_ENV"] = '{"test": "test"}'
|
os.environ["CONFIG_FROM_ENV"] = '{"test": "test"}'
|
||||||
os.environ["CONFIG_OVERRIDE"] = "new"
|
os.environ["CONFIG_OVERRIDE"] = "new"
|
||||||
@ -22,6 +24,17 @@ def pytest_configure(config: pytest.Config) -> None:
|
|||||||
config.stash[NONEBOT_INIT_KWARGS] = {"config_from_init": "init"}
|
config.stash[NONEBOT_INIT_KWARGS] = {"config_from_init": "init"}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="driver")
|
||||||
|
def load_driver(request: pytest.FixtureRequest) -> Driver:
|
||||||
|
driver_name = getattr(request, "param", None)
|
||||||
|
global_driver = nonebot.get_driver()
|
||||||
|
if driver_name is None:
|
||||||
|
return global_driver
|
||||||
|
|
||||||
|
DriverClass = _resolve_combine_expr(driver_name)
|
||||||
|
return DriverClass(Env(environment=global_driver.env), global_driver.config)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session", autouse=True)
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
def load_plugin(nonebug_init: None) -> Set["Plugin"]:
|
def load_plugin(nonebug_init: None) -> Set["Plugin"]:
|
||||||
# preload global plugins
|
# preload global plugins
|
||||||
|
211
tests/test_adapters/test_adapter.py
Normal file
211
tests/test_adapters/test_adapter.py
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
from typing import Optional
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from nonebug import App
|
||||||
|
|
||||||
|
from utils import FakeAdapter
|
||||||
|
from nonebot.adapters import Bot
|
||||||
|
from nonebot.drivers import (
|
||||||
|
URL,
|
||||||
|
Driver,
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
WebSocket,
|
||||||
|
HTTPServerSetup,
|
||||||
|
WebSocketServerSetup,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_adapter_connect(app: App, driver: Driver):
|
||||||
|
last_connect_bot: Optional[Bot] = None
|
||||||
|
last_disconnect_bot: Optional[Bot] = None
|
||||||
|
|
||||||
|
def _fake_bot_connect(bot: Bot):
|
||||||
|
nonlocal last_connect_bot
|
||||||
|
last_connect_bot = bot
|
||||||
|
|
||||||
|
def _fake_bot_disconnect(bot: Bot):
|
||||||
|
nonlocal last_disconnect_bot
|
||||||
|
last_disconnect_bot = bot
|
||||||
|
|
||||||
|
with pytest.MonkeyPatch.context() as m:
|
||||||
|
m.setattr(driver, "_bot_connect", _fake_bot_connect)
|
||||||
|
m.setattr(driver, "_bot_disconnect", _fake_bot_disconnect)
|
||||||
|
|
||||||
|
adapter = FakeAdapter(driver)
|
||||||
|
|
||||||
|
async with app.test_api() as ctx:
|
||||||
|
bot = ctx.create_bot(adapter=adapter)
|
||||||
|
assert last_connect_bot is bot
|
||||||
|
assert adapter.bots[bot.self_id] is bot
|
||||||
|
|
||||||
|
assert last_disconnect_bot is bot
|
||||||
|
assert bot.self_id not in adapter.bots
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"driver",
|
||||||
|
[
|
||||||
|
pytest.param("nonebot.drivers.fastapi:Driver", id="fastapi"),
|
||||||
|
pytest.param("nonebot.drivers.quart:Driver", id="quart"),
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.httpx:Driver",
|
||||||
|
id="httpx",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a server", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.websockets:Driver",
|
||||||
|
id="websockets",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a server", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.aiohttp:Driver",
|
||||||
|
id="aiohttp",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a server", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
indirect=True,
|
||||||
|
)
|
||||||
|
async def test_adapter_server(driver: Driver):
|
||||||
|
last_http_setup: Optional[HTTPServerSetup] = None
|
||||||
|
last_ws_setup: Optional[WebSocketServerSetup] = None
|
||||||
|
|
||||||
|
def _fake_setup_http_server(setup: HTTPServerSetup):
|
||||||
|
nonlocal last_http_setup
|
||||||
|
last_http_setup = setup
|
||||||
|
|
||||||
|
def _fake_setup_websocket_server(setup: WebSocketServerSetup):
|
||||||
|
nonlocal last_ws_setup
|
||||||
|
last_ws_setup = setup
|
||||||
|
|
||||||
|
with pytest.MonkeyPatch.context() as m:
|
||||||
|
m.setattr(driver, "setup_http_server", _fake_setup_http_server, raising=False)
|
||||||
|
m.setattr(
|
||||||
|
driver,
|
||||||
|
"setup_websocket_server",
|
||||||
|
_fake_setup_websocket_server,
|
||||||
|
raising=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def handle_http(request: Request):
|
||||||
|
return Response(200, content="test")
|
||||||
|
|
||||||
|
async def handle_ws(ws: WebSocket):
|
||||||
|
...
|
||||||
|
|
||||||
|
adapter = FakeAdapter(driver)
|
||||||
|
|
||||||
|
setup = HTTPServerSetup(URL("/test"), "GET", "test", handle_http)
|
||||||
|
adapter.setup_http_server(setup)
|
||||||
|
assert last_http_setup is setup
|
||||||
|
|
||||||
|
setup = WebSocketServerSetup(URL("/test"), "test", handle_ws)
|
||||||
|
adapter.setup_websocket_server(setup)
|
||||||
|
assert last_ws_setup is setup
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"driver",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.fastapi:Driver",
|
||||||
|
id="fastapi",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a http client", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.quart:Driver",
|
||||||
|
id="quart",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a http client", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param("nonebot.drivers.httpx:Driver", id="httpx"),
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.websockets:Driver",
|
||||||
|
id="websockets",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a http client", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param("nonebot.drivers.aiohttp:Driver", id="aiohttp"),
|
||||||
|
],
|
||||||
|
indirect=True,
|
||||||
|
)
|
||||||
|
async def test_adapter_http_client(driver: Driver):
|
||||||
|
last_request: Optional[Request] = None
|
||||||
|
|
||||||
|
async def _fake_request(request: Request):
|
||||||
|
nonlocal last_request
|
||||||
|
last_request = request
|
||||||
|
|
||||||
|
with pytest.MonkeyPatch.context() as m:
|
||||||
|
m.setattr(driver, "request", _fake_request, raising=False)
|
||||||
|
|
||||||
|
adapter = FakeAdapter(driver)
|
||||||
|
|
||||||
|
request = Request("GET", URL("/test"))
|
||||||
|
await adapter.request(request)
|
||||||
|
assert last_request is request
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"driver",
|
||||||
|
[
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.fastapi:Driver",
|
||||||
|
id="fastapi",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a websocket client", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.quart:Driver",
|
||||||
|
id="quart",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a websocket client", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param(
|
||||||
|
"nonebot.drivers.httpx:Driver",
|
||||||
|
id="httpx",
|
||||||
|
marks=pytest.mark.xfail(
|
||||||
|
reason="not a websocket client", raises=TypeError, strict=True
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pytest.param("nonebot.drivers.websockets:Driver", id="websockets"),
|
||||||
|
pytest.param("nonebot.drivers.aiohttp:Driver", id="aiohttp"),
|
||||||
|
],
|
||||||
|
indirect=True,
|
||||||
|
)
|
||||||
|
async def test_adapter_websocket_client(driver: Driver):
|
||||||
|
_fake_ws = object()
|
||||||
|
_last_request: Optional[Request] = None
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def _fake_websocket(setup: Request):
|
||||||
|
nonlocal _last_request
|
||||||
|
_last_request = setup
|
||||||
|
yield _fake_ws
|
||||||
|
|
||||||
|
with pytest.MonkeyPatch.context() as m:
|
||||||
|
m.setattr(driver, "websocket", _fake_websocket, raising=False)
|
||||||
|
|
||||||
|
adapter = FakeAdapter(driver)
|
||||||
|
|
||||||
|
request = Request("GET", URL("/test"))
|
||||||
|
async with adapter.websocket(request) as ws:
|
||||||
|
assert _last_request is request
|
||||||
|
assert ws is _fake_ws
|
@ -1,15 +1,12 @@
|
|||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Any, Set, Optional, cast
|
from typing import Any, Set, Optional
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from nonebug import App
|
from nonebug import App
|
||||||
|
|
||||||
import nonebot
|
|
||||||
from nonebot.config import Env
|
|
||||||
from nonebot.adapters import Bot
|
from nonebot.adapters import Bot
|
||||||
from nonebot.params import Depends
|
from nonebot.params import Depends
|
||||||
from nonebot import _resolve_combine_expr
|
|
||||||
from nonebot.dependencies import Dependent
|
from nonebot.dependencies import Dependent
|
||||||
from nonebot.exception import WebSocketClosed
|
from nonebot.exception import WebSocketClosed
|
||||||
from nonebot.drivers._lifespan import Lifespan
|
from nonebot.drivers._lifespan import Lifespan
|
||||||
@ -18,25 +15,15 @@ from nonebot.drivers import (
|
|||||||
Driver,
|
Driver,
|
||||||
Request,
|
Request,
|
||||||
Response,
|
Response,
|
||||||
|
ASGIMixin,
|
||||||
WebSocket,
|
WebSocket,
|
||||||
ForwardDriver,
|
HTTPClientMixin,
|
||||||
ReverseDriver,
|
|
||||||
HTTPServerSetup,
|
HTTPServerSetup,
|
||||||
|
WebSocketClientMixin,
|
||||||
WebSocketServerSetup,
|
WebSocketServerSetup,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(name="driver")
|
|
||||||
def load_driver(request: pytest.FixtureRequest) -> Driver:
|
|
||||||
driver_name = getattr(request, "param", None)
|
|
||||||
global_driver = nonebot.get_driver()
|
|
||||||
if driver_name is None:
|
|
||||||
return global_driver
|
|
||||||
|
|
||||||
DriverClass = _resolve_combine_expr(driver_name)
|
|
||||||
return DriverClass(Env(environment=global_driver.env), global_driver.config)
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_lifespan():
|
async def test_lifespan():
|
||||||
lifespan = Lifespan()
|
lifespan = Lifespan()
|
||||||
@ -80,7 +67,7 @@ async def test_lifespan():
|
|||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
async def test_http_server(app: App, driver: Driver):
|
async def test_http_server(app: App, driver: Driver):
|
||||||
driver = cast(ReverseDriver, driver)
|
assert isinstance(driver, ASGIMixin)
|
||||||
|
|
||||||
async def _handle_http(request: Request) -> Response:
|
async def _handle_http(request: Request) -> Response:
|
||||||
assert request.content in (b"test", "test")
|
assert request.content in (b"test", "test")
|
||||||
@ -108,7 +95,7 @@ async def test_http_server(app: App, driver: Driver):
|
|||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
async def test_websocket_server(app: App, driver: Driver):
|
async def test_websocket_server(app: App, driver: Driver):
|
||||||
driver = cast(ReverseDriver, driver)
|
assert isinstance(driver, ASGIMixin)
|
||||||
|
|
||||||
async def _handle_ws(ws: WebSocket) -> None:
|
async def _handle_ws(ws: WebSocket) -> None:
|
||||||
await ws.accept()
|
await ws.accept()
|
||||||
@ -164,7 +151,7 @@ async def test_websocket_server(app: App, driver: Driver):
|
|||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
async def test_cross_context(app: App, driver: Driver):
|
async def test_cross_context(app: App, driver: Driver):
|
||||||
driver = cast(ReverseDriver, driver)
|
assert isinstance(driver, ASGIMixin)
|
||||||
|
|
||||||
ws: Optional[WebSocket] = None
|
ws: Optional[WebSocket] = None
|
||||||
ws_ready = asyncio.Event()
|
ws_ready = asyncio.Event()
|
||||||
@ -221,7 +208,7 @@ async def test_cross_context(app: App, driver: Driver):
|
|||||||
indirect=True,
|
indirect=True,
|
||||||
)
|
)
|
||||||
async def test_http_client(driver: Driver, server_url: URL):
|
async def test_http_client(driver: Driver, server_url: URL):
|
||||||
driver = cast(ForwardDriver, driver)
|
assert isinstance(driver, HTTPClientMixin)
|
||||||
|
|
||||||
# simple post with query, headers, cookies and content
|
# simple post with query, headers, cookies and content
|
||||||
request = Request(
|
request = Request(
|
||||||
@ -303,6 +290,19 @@ async def test_http_client(driver: Driver, server_url: URL):
|
|||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"driver",
|
||||||
|
[
|
||||||
|
pytest.param("nonebot.drivers.websockets:Driver", id="websockets"),
|
||||||
|
pytest.param("nonebot.drivers.aiohttp:Driver", id="aiohttp"),
|
||||||
|
],
|
||||||
|
indirect=True,
|
||||||
|
)
|
||||||
|
async def test_websocket_client(driver: Driver):
|
||||||
|
assert isinstance(driver, WebSocketClientMixin)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("driver", "driver_type"),
|
("driver", "driver_type"),
|
||||||
|
@ -2,7 +2,7 @@ import pytest
|
|||||||
from nonebug import App
|
from nonebug import App
|
||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
from nonebot.drivers import Driver, ReverseDriver
|
from nonebot.drivers import Driver, ASGIMixin, ReverseDriver
|
||||||
from nonebot import (
|
from nonebot import (
|
||||||
get_app,
|
get_app,
|
||||||
get_bot,
|
get_bot,
|
||||||
@ -47,6 +47,7 @@ async def test_get_driver(app: App, monkeypatch: pytest.MonkeyPatch):
|
|||||||
async def test_get_asgi(app: App, monkeypatch: pytest.MonkeyPatch):
|
async def test_get_asgi(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
assert isinstance(driver, ReverseDriver)
|
assert isinstance(driver, ReverseDriver)
|
||||||
|
assert isinstance(driver, ASGIMixin)
|
||||||
assert get_asgi() == driver.asgi
|
assert get_asgi() == driver.asgi
|
||||||
|
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ async def test_get_asgi(app: App, monkeypatch: pytest.MonkeyPatch):
|
|||||||
async def test_get_app(app: App, monkeypatch: pytest.MonkeyPatch):
|
async def test_get_app(app: App, monkeypatch: pytest.MonkeyPatch):
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
assert isinstance(driver, ReverseDriver)
|
assert isinstance(driver, ReverseDriver)
|
||||||
|
assert isinstance(driver, ASGIMixin)
|
||||||
assert get_app() == driver.server_app
|
assert get_app() == driver.server_app
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
from typing_extensions import override
|
||||||
from typing import Type, Union, Mapping, Iterable, Optional
|
from typing import Type, Union, Mapping, Iterable, Optional
|
||||||
|
|
||||||
from pydantic import Extra, create_model
|
from pydantic import Extra, create_model
|
||||||
|
|
||||||
from nonebot.adapters import Event, Message, MessageSegment
|
from nonebot.adapters import Bot, Event, Adapter, Message, MessageSegment
|
||||||
|
|
||||||
|
|
||||||
def escape_text(s: str, *, escape_comma: bool = True) -> str:
|
def escape_text(s: str, *, escape_comma: bool = True) -> str:
|
||||||
@ -12,11 +13,24 @@ def escape_text(s: str, *, escape_comma: bool = True) -> str:
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
class FakeAdapter(Adapter):
|
||||||
|
@classmethod
|
||||||
|
@override
|
||||||
|
def get_name(cls) -> str:
|
||||||
|
return "fake"
|
||||||
|
|
||||||
|
@override
|
||||||
|
async def _call_api(self, bot: Bot, api: str, **data):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class FakeMessageSegment(MessageSegment["FakeMessage"]):
|
class FakeMessageSegment(MessageSegment["FakeMessage"]):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@override
|
||||||
def get_message_class(cls):
|
def get_message_class(cls):
|
||||||
return FakeMessage
|
return FakeMessage
|
||||||
|
|
||||||
|
@override
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.data["text"] if self.type == "text" else f"[fake:{self.type}]"
|
return self.data["text"] if self.type == "text" else f"[fake:{self.type}]"
|
||||||
|
|
||||||
@ -32,16 +46,19 @@ class FakeMessageSegment(MessageSegment["FakeMessage"]):
|
|||||||
def nested(content: "FakeMessage"):
|
def nested(content: "FakeMessage"):
|
||||||
return FakeMessageSegment("node", {"content": content})
|
return FakeMessageSegment("node", {"content": content})
|
||||||
|
|
||||||
|
@override
|
||||||
def is_text(self) -> bool:
|
def is_text(self) -> bool:
|
||||||
return self.type == "text"
|
return self.type == "text"
|
||||||
|
|
||||||
|
|
||||||
class FakeMessage(Message[FakeMessageSegment]):
|
class FakeMessage(Message[FakeMessageSegment]):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@override
|
||||||
def get_segment_class(cls):
|
def get_segment_class(cls):
|
||||||
return FakeMessageSegment
|
return FakeMessageSegment
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@override
|
||||||
def _construct(msg: Union[str, Iterable[Mapping]]):
|
def _construct(msg: Union[str, Iterable[Mapping]]):
|
||||||
if isinstance(msg, str):
|
if isinstance(msg, str):
|
||||||
yield FakeMessageSegment.text(msg)
|
yield FakeMessageSegment.text(msg)
|
||||||
@ -50,6 +67,7 @@ class FakeMessage(Message[FakeMessageSegment]):
|
|||||||
yield FakeMessageSegment(**seg)
|
yield FakeMessageSegment(**seg)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@override
|
||||||
def __add__(
|
def __add__(
|
||||||
self, other: Union[str, FakeMessageSegment, Iterable[FakeMessageSegment]]
|
self, other: Union[str, FakeMessageSegment, Iterable[FakeMessageSegment]]
|
||||||
):
|
):
|
||||||
@ -71,30 +89,37 @@ def make_fake_event(
|
|||||||
Base = _base or Event
|
Base = _base or Event
|
||||||
|
|
||||||
class FakeEvent(Base, extra=Extra.forbid):
|
class FakeEvent(Base, extra=Extra.forbid):
|
||||||
|
@override
|
||||||
def get_type(self) -> str:
|
def get_type(self) -> str:
|
||||||
return _type
|
return _type
|
||||||
|
|
||||||
|
@override
|
||||||
def get_event_name(self) -> str:
|
def get_event_name(self) -> str:
|
||||||
return _name
|
return _name
|
||||||
|
|
||||||
|
@override
|
||||||
def get_event_description(self) -> str:
|
def get_event_description(self) -> str:
|
||||||
return _description
|
return _description
|
||||||
|
|
||||||
|
@override
|
||||||
def get_user_id(self) -> str:
|
def get_user_id(self) -> str:
|
||||||
if _user_id is not None:
|
if _user_id is not None:
|
||||||
return _user_id
|
return _user_id
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@override
|
||||||
def get_session_id(self) -> str:
|
def get_session_id(self) -> str:
|
||||||
if _session_id is not None:
|
if _session_id is not None:
|
||||||
return _session_id
|
return _session_id
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@override
|
||||||
def get_message(self) -> "Message":
|
def get_message(self) -> "Message":
|
||||||
if _message is not None:
|
if _message is not None:
|
||||||
return _message
|
return _message
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@override
|
||||||
def is_tome(self) -> bool:
|
def is_tome(self) -> bool:
|
||||||
return _to_me
|
return _to_me
|
||||||
|
|
||||||
|
@ -22,21 +22,22 @@ options:
|
|||||||
|
|
||||||
## 驱动器类型
|
## 驱动器类型
|
||||||
|
|
||||||
驱动器的类型有两种:
|
驱动器类型大体上可以分为两种:
|
||||||
|
|
||||||
- `ForwardDriver`:即客户端型驱动器,多用于使用 HTTP 轮询,连接 WebSocket 服务器等情形。
|
- `Forward`:即客户端型驱动器,多用于使用 HTTP 轮询,连接 WebSocket 服务器等情形。
|
||||||
- `ReverseDriver`:即服务端型驱动器,多用于使用 WebHook,接收 WebSocket 客户端连接等情形。
|
- `Reverse`:即服务端型驱动器,多用于使用 WebHook,接收 WebSocket 客户端连接等情形。
|
||||||
|
|
||||||
客户端型驱动器具有以下两种功能:
|
客户端型驱动器可以分为以下两种:
|
||||||
|
|
||||||
1. 异步发送 HTTP 请求,自定义 `HTTP Method`、`URL`、`Header`、`Body`、`Cookie`、`Proxy`、`Timeout` 等。
|
1. 异步发送 HTTP 请求,自定义 `HTTP Method`、`URL`、`Header`、`Body`、`Cookie`、`Proxy`、`Timeout` 等。
|
||||||
2. 异步建立 WebSocket 连接上下文,自定义 `WebSocket URL`、`Header`、`Cookie`、`Proxy`、`Timeout` 等。
|
2. 异步建立 WebSocket 连接上下文,自定义 `WebSocket URL`、`Header`、`Cookie`、`Proxy`、`Timeout` 等。
|
||||||
|
|
||||||
服务端型驱动器通常为 ASGI 应用框架,具有以下功能:
|
服务端型驱动器目前有:
|
||||||
|
|
||||||
1. 协议适配器自定义 HTTP 上报地址以及对上报数据处理的回调函数。
|
1. ASGI 应用框架,具有以下功能:
|
||||||
2. 协议适配器自定义 WebSocket 连接请求地址以及对 WebSocket 请求处理的回调函数。
|
- 协议适配器自定义 HTTP 上报地址以及对上报数据处理的回调函数。
|
||||||
3. 用户可以向 ASGI 应用添加任何服务端相关功能,如:[添加自定义路由](./routing.md)。
|
- 协议适配器自定义 WebSocket 连接请求地址以及对 WebSocket 请求处理的回调函数。
|
||||||
|
- 用户可以向 ASGI 应用添加任何服务端相关功能,如:[添加自定义路由](./routing.md)。
|
||||||
|
|
||||||
## 配置驱动器
|
## 配置驱动器
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ DRIVER=~none
|
|||||||
|
|
||||||
### FastAPI(默认)
|
### FastAPI(默认)
|
||||||
|
|
||||||
**类型:**服务端驱动器
|
**类型:**ASGI 服务端驱动器
|
||||||
|
|
||||||
> FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
> FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
|
||||||
|
|
||||||
@ -185,7 +186,7 @@ nonebot.run(app="bot:app")
|
|||||||
|
|
||||||
### Quart
|
### Quart
|
||||||
|
|
||||||
**类型:**`ReverseDriver`
|
**类型:**ASGI 服务端驱动器
|
||||||
|
|
||||||
> Quart is an asyncio reimplementation of the popular Flask microframework API.
|
> Quart is an asyncio reimplementation of the popular Flask microframework API.
|
||||||
|
|
||||||
@ -249,7 +250,7 @@ nonebot.run(app="bot:app")
|
|||||||
|
|
||||||
### HTTPX
|
### HTTPX
|
||||||
|
|
||||||
**类型:**`ForwardDriver`
|
**类型:**HTTP 客户端驱动器
|
||||||
|
|
||||||
:::warning 注意
|
:::warning 注意
|
||||||
本驱动器仅支持 HTTP 请求,不支持 WebSocket 连接请求。
|
本驱动器仅支持 HTTP 请求,不支持 WebSocket 连接请求。
|
||||||
@ -263,7 +264,7 @@ DRIVER=~httpx
|
|||||||
|
|
||||||
### websockets
|
### websockets
|
||||||
|
|
||||||
**类型:**`ForwardDriver`
|
**类型:**WebSocket 客户端驱动器
|
||||||
|
|
||||||
:::warning 注意
|
:::warning 注意
|
||||||
本驱动器仅支持 WebSocket 连接请求,不支持 HTTP 请求。
|
本驱动器仅支持 WebSocket 连接请求,不支持 HTTP 请求。
|
||||||
@ -277,7 +278,7 @@ DRIVER=~websockets
|
|||||||
|
|
||||||
### AIOHTTP
|
### AIOHTTP
|
||||||
|
|
||||||
**类型:**`ForwardDriver`
|
**类型:**HTTP/WebSocket 客户端驱动器
|
||||||
|
|
||||||
> [AIOHTTP](https://docs.aiohttp.org/): Asynchronous HTTP Client/Server for asyncio and Python.
|
> [AIOHTTP](https://docs.aiohttp.org/): Asynchronous HTTP Client/Server for asyncio and Python.
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ options:
|
|||||||
|
|
||||||
在[驱动器](./driver.md)一节中,我们了解了驱动器的两种类型。既然驱动器可以作为服务端运行,那么我们就可以向驱动器添加路由规则,从而实现自定义的 API 接口等功能。在添加路由规则时,我们需要注意驱动器的类型,详情可以参考[选择驱动器](./driver.md#配置驱动器)。
|
在[驱动器](./driver.md)一节中,我们了解了驱动器的两种类型。既然驱动器可以作为服务端运行,那么我们就可以向驱动器添加路由规则,从而实现自定义的 API 接口等功能。在添加路由规则时,我们需要注意驱动器的类型,详情可以参考[选择驱动器](./driver.md#配置驱动器)。
|
||||||
|
|
||||||
NoneBot 中,我们可以通过两种途径向驱动器添加路由规则:
|
NoneBot 中,我们可以通过两种途径向 ASGI 驱动器添加路由规则:
|
||||||
|
|
||||||
1. 通过 NoneBot 的兼容层建立路由规则。
|
1. 通过 NoneBot 的兼容层建立路由规则。
|
||||||
2. 直接向 ASGI 应用添加路由规则。
|
2. 直接向 ASGI 应用添加路由规则。
|
||||||
@ -23,9 +23,9 @@ NoneBot 中,我们可以通过两种途径向驱动器添加路由规则:
|
|||||||
|
|
||||||
```python {3}
|
```python {3}
|
||||||
from nonebot import get_driver
|
from nonebot import get_driver
|
||||||
from nonebot.drivers import ReverseDriver
|
from nonebot.drivers import ASGIMixin
|
||||||
|
|
||||||
can_use = isinstance(get_driver(), ReverseDriver)
|
can_use = isinstance(get_driver(), ASGIMixin)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 通过兼容层添加路由
|
## 通过兼容层添加路由
|
||||||
@ -45,12 +45,12 @@ NoneBot 兼容层定义了两个数据类 `HTTPServerSetup` 和 `WebSocketServer
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from nonebot import get_driver
|
from nonebot import get_driver
|
||||||
from nonebot.drivers import URL, Request, Response, HTTPServerSetup
|
from nonebot.drivers import URL, Request, Response, ASGIMixin, HTTPServerSetup
|
||||||
|
|
||||||
async def hello(request: Request) -> Response:
|
async def hello(request: Request) -> Response:
|
||||||
return Response(200, content="Hello, world!")
|
return Response(200, content="Hello, world!")
|
||||||
|
|
||||||
if isinstance((driver := get_driver()), ReverseDriver):
|
if isinstance((driver := get_driver()), ASGIMixin):
|
||||||
driver.setup_http_server(
|
driver.setup_http_server(
|
||||||
HTTPServerSetup(
|
HTTPServerSetup(
|
||||||
path=URL("/hello"),
|
path=URL("/hello"),
|
||||||
@ -75,7 +75,7 @@ if isinstance((driver := get_driver()), ReverseDriver):
|
|||||||
|
|
||||||
```python
|
```python
|
||||||
from nonebot import get_driver
|
from nonebot import get_driver
|
||||||
from nonebot.drivers import URL, WebSocket, WebSocketServerSetup
|
from nonebot.drivers import URL, ASGIMixin, WebSocket, WebSocketServerSetup
|
||||||
|
|
||||||
async def ws_handler(ws: WebSocket):
|
async def ws_handler(ws: WebSocket):
|
||||||
await ws.accept()
|
await ws.accept()
|
||||||
@ -91,7 +91,7 @@ async def ws_handler(ws: WebSocket):
|
|||||||
await websocket.close()
|
await websocket.close()
|
||||||
# do some cleanup
|
# do some cleanup
|
||||||
|
|
||||||
if isinstance((driver := get_driver()), ReverseDriver):
|
if isinstance((driver := get_driver()), ASGIMixin):
|
||||||
driver.setup_websocket_server(
|
driver.setup_websocket_server(
|
||||||
WebSocketServerSetup(
|
WebSocketServerSetup(
|
||||||
path=URL("/ws"),
|
path=URL("/ws"),
|
||||||
|
@ -125,8 +125,8 @@ NoneBot 提供了多种 [Driver](../advanced/driver) 来帮助适配器进行网
|
|||||||
import asyncio
|
import asyncio
|
||||||
from typing_extensions import override
|
from typing_extensions import override
|
||||||
|
|
||||||
from nonebot.drivers import Request, ForwardDriver
|
|
||||||
from nonebot.exception import WebSocketClosed
|
from nonebot.exception import WebSocketClosed
|
||||||
|
from nonebot.drivers import Request, WebSocketClientMixin
|
||||||
|
|
||||||
class Adapter(BaseAdapter):
|
class Adapter(BaseAdapter):
|
||||||
@override
|
@override
|
||||||
@ -137,11 +137,11 @@ class Adapter(BaseAdapter):
|
|||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
if not isinstance(self.driver, ForwardDriver):
|
if not isinstance(self.driver, WebSocketClientMixin):
|
||||||
# 判断用户配置的Driver类型是否符合适配器要求,不符合时应抛出异常
|
# 判断用户配置的Driver类型是否符合适配器要求,不符合时应抛出异常
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Current driver {self.config.driver} doesn't support forward connections!"
|
f"Current driver {self.config.driver} doesn't support websocket client connections!"
|
||||||
f"{self.get_name()} Adapter need a ForwardDriver to work."
|
f"{self.get_name()} Adapter need a WebSocket Client Driver to work."
|
||||||
)
|
)
|
||||||
# 在 NoneBot 启动和关闭时进行相关操作
|
# 在 NoneBot 启动和关闭时进行相关操作
|
||||||
self.driver.on_startup(self.startup)
|
self.driver.on_startup(self.startup)
|
||||||
@ -202,8 +202,8 @@ class Adapter(BaseAdapter):
|
|||||||
```python {30,38} title=adapter.py
|
```python {30,38} title=adapter.py
|
||||||
from nonebot.drivers import (
|
from nonebot.drivers import (
|
||||||
Request,
|
Request,
|
||||||
|
ASGIMixin,
|
||||||
WebSocket,
|
WebSocket,
|
||||||
ReverseDriver,
|
|
||||||
HTTPServerSetup,
|
HTTPServerSetup,
|
||||||
WebSocketServerSetup
|
WebSocketServerSetup
|
||||||
)
|
)
|
||||||
@ -216,10 +216,10 @@ class Adapter(BaseAdapter):
|
|||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
def setup(self) -> None:
|
def setup(self) -> None:
|
||||||
if not isinstance(self.driver, ReverseDriver):
|
if not isinstance(self.driver, ASGIMixin):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Current driver {self.config.driver} doesn't support forward connections!"
|
f"Current driver {self.config.driver} doesn't support asgi server!"
|
||||||
f"{self.get_name()} Adapter need a ReverseDriver to work."
|
f"{self.get_name()} Adapter need a asgi server driver to work."
|
||||||
)
|
)
|
||||||
# 建立服务端路由
|
# 建立服务端路由
|
||||||
# HTTP Webhook 路由
|
# HTTP Webhook 路由
|
||||||
|
Loading…
Reference in New Issue
Block a user