Develop: 升级 NoneBug 版本 (#1725)

This commit is contained in:
Ju4tCode 2023-02-22 23:32:48 +08:00 committed by GitHub
parent 1befd9ffc6
commit 74743e6176
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 340 additions and 408 deletions

View File

@ -38,7 +38,6 @@ FrontMatter:
""" """
import os import os
import importlib
from importlib.metadata import version from importlib.metadata import version
from typing import Any, Dict, Type, Optional from typing import Any, Dict, Type, Optional
@ -46,9 +45,9 @@ import loguru
from pydantic.env_settings import DotenvType from pydantic.env_settings import DotenvType
from nonebot.adapters import Bot from nonebot.adapters import Bot
from nonebot.utils import escape_tag
from nonebot.config import Env, Config from nonebot.config import Env, Config
from nonebot.log import logger as logger from nonebot.log import logger as logger
from nonebot.utils import escape_tag, resolve_dot_notation
from nonebot.drivers import Driver, ReverseDriver, combine_driver from nonebot.drivers import Driver, ReverseDriver, combine_driver
try: try:
@ -175,31 +174,16 @@ def get_bots() -> Dict[str, Bot]:
return get_driver().bots return get_driver().bots
def _resolve_dot_notation(
obj_str: str, default_attr: str, default_prefix: Optional[str] = None
) -> Any:
modulename, _, cls = obj_str.partition(":")
if default_prefix is not None and modulename.startswith("~"):
modulename = default_prefix + modulename[1:]
module = importlib.import_module(modulename)
if not cls:
return getattr(module, default_attr)
instance = module
for attr_str in cls.split("."):
instance = getattr(instance, attr_str)
return instance
def _resolve_combine_expr(obj_str: str) -> Type[Driver]: def _resolve_combine_expr(obj_str: str) -> Type[Driver]:
drivers = obj_str.split("+") drivers = obj_str.split("+")
DriverClass = _resolve_dot_notation( DriverClass = resolve_dot_notation(
drivers[0], "Driver", default_prefix="nonebot.drivers." drivers[0], "Driver", default_prefix="nonebot.drivers."
) )
if len(drivers) == 1: if len(drivers) == 1:
logger.trace(f"Detected driver {DriverClass} with no mixins.") logger.trace(f"Detected driver {DriverClass} with no mixins.")
return DriverClass return DriverClass
mixins = [ mixins = [
_resolve_dot_notation(mixin, "Mixin", default_prefix="nonebot.drivers.") resolve_dot_notation(mixin, "Mixin", default_prefix="nonebot.drivers.")
for mixin in drivers[1:] for mixin in drivers[1:]
] ]
logger.trace(f"Detected driver {DriverClass} with mixins {mixins}.") logger.trace(f"Detected driver {DriverClass} with mixins {mixins}.")

View File

@ -9,6 +9,7 @@ import re
import json import json
import asyncio import asyncio
import inspect import inspect
import importlib
import dataclasses import dataclasses
from pathlib import Path from pathlib import Path
from functools import wraps, partial from functools import wraps, partial
@ -167,13 +168,30 @@ def get_name(obj: Any) -> str:
def path_to_module_name(path: Path) -> str: def path_to_module_name(path: Path) -> str:
rel_path = path.resolve().relative_to(Path(".").resolve()) """转换路径为模块名"""
rel_path = path.resolve().relative_to(Path.cwd().resolve())
if rel_path.stem == "__init__": if rel_path.stem == "__init__":
return ".".join(rel_path.parts[:-1]) return ".".join(rel_path.parts[:-1])
else: else:
return ".".join(rel_path.parts[:-1] + (rel_path.stem,)) return ".".join(rel_path.parts[:-1] + (rel_path.stem,))
def resolve_dot_notation(
obj_str: str, default_attr: str, default_prefix: Optional[str] = None
) -> Any:
"""解析并导入点分表示法的对象"""
modulename, _, cls = obj_str.partition(":")
if default_prefix is not None and modulename.startswith("~"):
modulename = default_prefix + modulename[1:]
module = importlib.import_module(modulename)
if not cls:
return getattr(module, default_attr)
instance = module
for attr_str in cls.split("."):
instance = getattr(instance, attr_str)
return instance
class DataclassEncoder(json.JSONEncoder): class DataclassEncoder(json.JSONEncoder):
"""在JSON序列化 {re}`nonebot.adapters._message.Message` (List[Dataclass]) 时使用的 `JSONEncoder`""" """在JSON序列化 {re}`nonebot.adapters._message.Message` (List[Dataclass]) 时使用的 `JSONEncoder`"""

42
poetry.lock generated
View File

@ -1431,26 +1431,22 @@ setuptools = "*"
[[package]] [[package]]
name = "nonebug" name = "nonebug"
version = "0.2.3" version = "0.3.0"
description = "nonebot2 test framework" description = "nonebot2 test framework"
category = "dev" category = "dev"
optional = false optional = false
python-versions = "^3.8" python-versions = ">=3.8,<4.0"
files = [] files = [
develop = false {file = "nonebug-0.3.0-py3-none-any.whl", hash = "sha256:ba6adef16c73042ac717c840aceb0e68fe06ebca948fe69511139265752b77f9"},
{file = "nonebug-0.3.0.tar.gz", hash = "sha256:189d0d8efbcaf06dd9bdf73b48f270b60a31ec9e76b546ab6607c392929de9bd"},
]
[package.dependencies] [package.dependencies]
asgiref = "^3.4.0" asgiref = ">=3.4.0,<4.0.0"
async-asgi-testclient = "^1.4.8" async-asgi-testclient = ">=1.4.8,<2.0.0"
nonebot2 = "^2.0.0-beta.1" nonebot2 = ">=2.0.0-rc.2,<3.0.0"
pytest = "^7.0.0" pytest = ">=7.0.0,<8.0.0"
typing-extensions = "^4.0.0" typing-extensions = ">=4.0.0,<5.0.0"
[package.source]
type = "git"
url = "https://github.com/nonebot/nonebug.git"
reference = "HEAD"
resolved_reference = "9e40f5717b8f7bf3e19933f9a2b63a470db6005a"
[[package]] [[package]]
name = "nonemoji" name = "nonemoji"
@ -1571,14 +1567,14 @@ files = [
[[package]] [[package]]
name = "prompt-toolkit" name = "prompt-toolkit"
version = "3.0.36" version = "3.0.37"
description = "Library for building powerful interactive command lines in Python" description = "Library for building powerful interactive command lines in Python"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.6.2" python-versions = ">=3.7.0"
files = [ files = [
{file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"}, {file = "prompt_toolkit-3.0.37-py3-none-any.whl", hash = "sha256:6a2948ec427dfcc7c983027b1044b355db6aaa8be374f54ad2015471f7d81c5b"},
{file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"}, {file = "prompt_toolkit-3.0.37.tar.gz", hash = "sha256:d5d73d4b5eb1a92ba884a88962b157f49b71e06c4348b417dd622b25cdd3800b"},
] ]
[package.dependencies] [package.dependencies]
@ -1966,14 +1962,14 @@ idna2008 = ["idna"]
[[package]] [[package]]
name = "setuptools" name = "setuptools"
version = "67.3.2" version = "67.4.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages" description = "Easily download, build, install, upgrade, and uninstall Python packages"
category = "dev" category = "dev"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "setuptools-67.3.2-py3-none-any.whl", hash = "sha256:bb6d8e508de562768f2027902929f8523932fcd1fb784e6d573d2cafac995a48"}, {file = "setuptools-67.4.0-py3-none-any.whl", hash = "sha256:f106dee1b506dee5102cc3f3e9e68137bbad6d47b616be7991714b0c62204251"},
{file = "setuptools-67.3.2.tar.gz", hash = "sha256:95f00380ef2ffa41d9bba85d95b27689d923c93dfbafed4aecd7cf988a25e012"}, {file = "setuptools-67.4.0.tar.gz", hash = "sha256:e5fd0a713141a4a105412233c63dc4e17ba0090c8e8334594ac790ec97792330"},
] ]
[package.extras] [package.extras]
@ -2491,4 +2487,4 @@ websockets = ["websockets"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "9b82bb373f396eb553e6fcc33d26722957ff85590a1bd8b29b89cce4d7ed4489" content-hash = "d8e1468d5f5e1c5e48a7bf9717cd3f181cc05d4c0153cab3a75f429c6453766f"

View File

@ -45,10 +45,10 @@ nonemoji = "^0.1.2"
pre-commit = "^3.0.0" pre-commit = "^3.0.0"
[tool.poetry.group.test.dependencies] [tool.poetry.group.test.dependencies]
nonebug = "^0.3.0"
pytest-cov = "^4.0.0" pytest-cov = "^4.0.0"
pytest-xdist = "^3.0.2" pytest-xdist = "^3.0.2"
pytest-asyncio = "^0.20.0" pytest-asyncio = "^0.20.0"
nonebug = { git = "https://github.com/nonebot/nonebug.git" }
[tool.poetry.group.docs.dependencies] [tool.poetry.group.docs.dependencies]
nb-autodoc = { git = "https://github.com/nonebot/nb-autodoc.git" } nb-autodoc = { git = "https://github.com/nonebot/nb-autodoc.git" }
@ -63,7 +63,7 @@ all = ["fastapi", "quart", "aiohttp", "httpx", "websockets", "uvicorn"]
[tool.pytest.ini_options] [tool.pytest.ini_options]
asyncio_mode = "auto" asyncio_mode = "auto"
addopts = "--cov=nonebot --cov-report=term-missing" addopts = "--cov=nonebot --cov-append --cov-report=term-missing"
filterwarnings = [ filterwarnings = [
"error", "error",
"ignore::DeprecationWarning", "ignore::DeprecationWarning",

View File

@ -1,21 +1,30 @@
import os
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Set from typing import TYPE_CHECKING, Set
import pytest import pytest
from nonebug import NONEBOT_INIT_KWARGS
import nonebot
os.environ["CONFIG_FROM_ENV"] = '{"test": "test"}'
os.environ["CONFIG_OVERRIDE"] = "new"
if TYPE_CHECKING: if TYPE_CHECKING:
from nonebot.plugin import Plugin from nonebot.plugin import Plugin
@pytest.fixture def pytest_configure(config: pytest.Config) -> None:
def load_plugin(nonebug_init: None) -> Set["Plugin"]: config.stash[NONEBOT_INIT_KWARGS] = {"config_from_init": "init"}
import nonebot
@pytest.fixture(scope="session", autouse=True)
def load_plugin(nonebug_init: None) -> Set["Plugin"]:
# preload global plugins
return nonebot.load_plugins(str(Path(__file__).parent / "plugins")) return nonebot.load_plugins(str(Path(__file__).parent / "plugins"))
@pytest.fixture @pytest.fixture(scope="session", autouse=True)
def load_example(nonebug_init: None) -> Set["Plugin"]: def load_example(nonebug_init: None) -> Set["Plugin"]:
import nonebot # preload example plugins
return nonebot.load_plugins(str(Path(__file__).parent / "examples")) return nonebot.load_plugins(str(Path(__file__).parent / "examples"))

0
tests/dynamic/manager.py Normal file
View File

0
tests/dynamic/path.py Normal file
View File

View File

View File

0
tests/dynamic/simple.py Normal file
View File

View File

@ -1,4 +1,4 @@
{ {
"plugins": [], "plugins": [],
"plugin_dirs": ["plugins"] "plugin_dirs": []
} }

View File

@ -1,3 +1,3 @@
[tool.nonebot] [tool.nonebot]
plugins = [] plugins = []
plugin_dirs = ["plugins"] plugin_dirs = []

View File

@ -101,7 +101,7 @@ def test_message_getitem():
assert message[0] == MessageSegment.text("test") assert message[0] == MessageSegment.text("test")
assert message[0:2] == Message( assert message[:2] == Message(
[MessageSegment.text("test"), MessageSegment.image("test2")] [MessageSegment.text("test"), MessageSegment.image("test2")]
) )

View File

@ -1,9 +1,8 @@
from nonebot.adapters import MessageTemplate
from utils import escape_text, make_fake_message from utils import escape_text, make_fake_message
def test_template_basis(): def test_template_basis():
from nonebot.adapters import MessageTemplate
template = MessageTemplate("{key:.3%}") template = MessageTemplate("{key:.3%}")
formatted = template.format(key=0.123456789) formatted = template.format(key=0.123456789)
assert formatted == "12.346%" assert formatted == "12.346%"

View File

@ -5,30 +5,45 @@ from typing import cast
import pytest import pytest
from nonebug import App from nonebug import App
import nonebot
@pytest.mark.asyncio from nonebot.config import Env
@pytest.mark.parametrize( from nonebot import _resolve_combine_expr
"nonebug_init", from nonebot.exception import WebSocketClosed
[ from nonebot.drivers import (
pytest.param({"driver": "nonebot.drivers.fastapi:Driver"}, id="fastapi"),
pytest.param({"driver": "nonebot.drivers.quart:Driver"}, id="quart"),
],
indirect=True,
)
async def test_reverse_driver(app: App):
import nonebot
from nonebot.exception import WebSocketClosed
from nonebot.drivers import (
URL, URL,
Driver,
Request, Request,
Response, Response,
WebSocket, WebSocket,
ForwardDriver,
ReverseDriver, ReverseDriver,
HTTPServerSetup, HTTPServerSetup,
WebSocketServerSetup, WebSocketServerSetup,
) )
driver = cast(ReverseDriver, nonebot.get_driver())
@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.parametrize(
"driver",
[
pytest.param("nonebot.drivers.fastapi:Driver", id="fastapi"),
pytest.param("nonebot.drivers.quart:Driver", id="quart"),
],
indirect=True,
)
async def test_reverse_driver(app: App, driver: Driver):
driver = cast(ReverseDriver, driver)
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")
@ -61,7 +76,7 @@ async def test_reverse_driver(app: App):
ws_setup = WebSocketServerSetup(URL("/ws_test"), "ws_test", _handle_ws) ws_setup = WebSocketServerSetup(URL("/ws_test"), "ws_test", _handle_ws)
driver.setup_websocket_server(ws_setup) driver.setup_websocket_server(ws_setup)
async with app.test_server() as ctx: async with app.test_server(driver.asgi) as ctx:
client = ctx.get_client() client = ctx.get_client()
response = await client.post("/http_test", data="test") response = await client.post("/http_test", data="test")
assert response.status_code == 200 assert response.status_code == 200
@ -86,18 +101,15 @@ async def test_reverse_driver(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"nonebug_init", "driver",
[ [
pytest.param({"driver": "nonebot.drivers.httpx:Driver"}, id="httpx"), pytest.param("nonebot.drivers.httpx:Driver", id="httpx"),
pytest.param({"driver": "nonebot.drivers.aiohttp:Driver"}, id="aiohttp"), pytest.param("nonebot.drivers.aiohttp:Driver", id="aiohttp"),
], ],
indirect=True, indirect=True,
) )
async def test_http_driver(app: App): async def test_http_driver(driver: Driver):
import nonebot driver = cast(ForwardDriver, driver)
from nonebot.drivers import Request, ForwardDriver
driver = cast(ForwardDriver, nonebot.get_driver())
request = Request( request = Request(
"POST", "POST",
@ -140,23 +152,20 @@ async def test_http_driver(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"nonebug_init, driver_type", "driver, driver_type",
[ [
pytest.param( pytest.param(
{"driver": "nonebot.drivers.fastapi:Driver+nonebot.drivers.aiohttp:Mixin"}, "nonebot.drivers.fastapi:Driver+nonebot.drivers.aiohttp:Mixin",
"fastapi+aiohttp", "fastapi+aiohttp",
id="fastapi+aiohttp", id="fastapi+aiohttp",
), ),
pytest.param( pytest.param(
{"driver": "~httpx:Driver+~websockets"}, "~httpx:Driver+~websockets",
"none+httpx+websockets", "none+httpx+websockets",
id="httpx+websockets", id="httpx+websockets",
), ),
], ],
indirect=["nonebug_init"], indirect=["driver"],
) )
async def test_combine_driver(app: App, driver_type: str): async def test_combine_driver(driver: Driver, driver_type: str):
import nonebot
driver = nonebot.get_driver()
assert driver.type == driver_type assert driver.type == driver_type

View File

@ -1,13 +1,15 @@
import pytest import pytest
from nonebug import App from nonebug import App
from utils import make_fake_event, make_fake_message
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_weather(app: App, load_example): async def test_weather(app: App):
from examples.weather import weather from examples.weather import weather
from utils import make_fake_event, make_fake_message
# 将此处的 make_fake_message() 替换为你要发送的平台消息 Message 类型 # 将此处的 make_fake_message() 替换为你要发送的平台消息 Message 类型
# from nonebot.adapters.console import Message
Message = make_fake_message() Message = make_fake_message()
async with app.test_matcher(weather) as ctx: async with app.test_matcher(weather) as ctx:
@ -15,6 +17,8 @@ async def test_weather(app: App, load_example):
msg = Message("/天气 上海") msg = Message("/天气 上海")
# 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型 # 将此处的 make_fake_event() 替换为你要发送的平台事件 Event 类型
# from nonebot.adapters.console import MessageEvent
# event = MessageEvent(message=msg, to_me=True, ...)
event = make_fake_event(_message=msg, _to_me=True)() event = make_fake_event(_message=msg, _to_me=True)()
ctx.receive_event(bot, event) ctx.receive_event(bot, event)

View File

@ -1,30 +1,16 @@
import os
import pytest import pytest
os.environ["CONFIG_FROM_ENV"] = '{"test": "test"}' import nonebot
os.environ["CONFIG_OVERRIDE"] = "new" from nonebot.drivers import ReverseDriver
from nonebot import get_app, get_bot, get_asgi, get_bots, get_driver
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( async def test_init():
"nonebug_init", env = nonebot.get_driver().env
[
{
"config_from_init": "init",
"driver": "~fastapi+~httpx+~websockets",
},
{"config_from_init": "init", "driver": "~fastapi+~aiohttp"},
],
indirect=True,
)
async def test_init(nonebug_init):
from nonebot import get_driver
env = get_driver().env
assert env == "test" assert env == "test"
config = get_driver().config config = nonebot.get_driver().config
assert config.config_from_env == {"test": "test"} assert config.config_from_env == {"test": "test"}
assert config.config_override == "new" assert config.config_override == "new"
assert config.config_from_init == "init" assert config.config_from_init == "init"
@ -36,16 +22,12 @@ async def test_init(nonebug_init):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get(monkeypatch: pytest.MonkeyPatch, nonebug_clear): async def test_get(monkeypatch: pytest.MonkeyPatch):
import nonebot with monkeypatch.context() as m:
from nonebot.drivers import ForwardDriver, ReverseDriver m.setattr(nonebot, "_driver", None)
from nonebot import get_app, get_bot, get_asgi, get_bots, get_driver
with pytest.raises(ValueError): with pytest.raises(ValueError):
get_driver() get_driver()
nonebot.init(driver="nonebot.drivers.fastapi")
driver = get_driver() driver = get_driver()
assert isinstance(driver, ReverseDriver) assert isinstance(driver, ReverseDriver)
assert get_asgi() == driver.asgi assert get_asgi() == driver.asgi

View File

@ -1,11 +1,14 @@
import pytest import pytest
from nonebug import App from nonebug import App
from nonebot.permission import User
from nonebot.message import _check_matcher
from nonebot.matcher import Matcher, matchers
from utils import make_fake_event, make_fake_message from utils import make_fake_event, make_fake_message
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_matcher(app: App, load_plugin): async def test_matcher(app: App):
from plugins.matcher.matcher_process import ( from plugins.matcher.matcher_process import (
test_got, test_got,
test_handle, test_handle,
@ -77,7 +80,7 @@ async def test_matcher(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_type_updater(app: App, load_plugin): async def test_type_updater(app: App):
from plugins.matcher.matcher_type import test_type_updater, test_custom_updater from plugins.matcher.matcher_type import test_type_updater, test_custom_updater
event = make_fake_event()() event = make_fake_event()()
@ -98,8 +101,7 @@ async def test_type_updater(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_permission_updater(app: App, load_plugin): async def test_permission_updater(app: App):
from nonebot.permission import User
from plugins.matcher.matcher_permission import ( from plugins.matcher.matcher_permission import (
default_permission, default_permission,
test_custom_updater, test_custom_updater,
@ -143,8 +145,7 @@ async def test_permission_updater(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_run(app: App): async def test_run(app: App):
from nonebot.matcher import Matcher, matchers with app.provider.context({}):
assert not matchers assert not matchers
event = make_fake_event()() event = make_fake_event()()
@ -174,9 +175,7 @@ async def test_run(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_expire(app: App, load_plugin): async def test_expire(app: App):
from nonebot.matcher import matchers
from nonebot.message import _check_matcher
from plugins.matcher.matcher_expire import ( from plugins.matcher.matcher_expire import (
test_temp_matcher, test_temp_matcher,
test_datetime_matcher, test_datetime_matcher,

View File

@ -1,11 +1,14 @@
import pytest import pytest
from nonebug import App from nonebug import App
from nonebot.matcher import DEFAULT_PROVIDER_CLASS, matchers
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_manager(app: App, load_plugin): async def test_manager(app: App):
from nonebot.matcher import DEFAULT_PROVIDER_CLASS, matchers try:
default_provider = matchers.provider default_provider = matchers.provider
matchers.set_provider(DEFAULT_PROVIDER_CLASS) matchers.set_provider(DEFAULT_PROVIDER_CLASS)
assert matchers.provider == default_provider assert default_provider == matchers.provider
finally:
matchers.provider = app.provider

View File

@ -1,12 +1,40 @@
import pytest import pytest
from nonebug import App from nonebug import App
from nonebot.matcher import Matcher
from nonebot.exception import TypeMisMatch
from utils import make_fake_event, make_fake_message from utils import make_fake_event, make_fake_message
from nonebot.params import (
ArgParam,
BotParam,
EventParam,
StateParam,
DependParam,
DefaultParam,
MatcherParam,
ExceptionParam,
)
from nonebot.consts import (
CMD_KEY,
REGEX_STR,
PREFIX_KEY,
REGEX_DICT,
SHELL_ARGS,
SHELL_ARGV,
CMD_ARG_KEY,
KEYWORD_KEY,
RAW_CMD_KEY,
REGEX_GROUP,
ENDSWITH_KEY,
CMD_START_KEY,
FULLMATCH_KEY,
REGEX_MATCHED,
STARTSWITH_KEY,
)
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_depend(app: App, load_plugin): async def test_depend(app: App):
from nonebot.params import DependParam
from plugins.param.param_depend import ( from plugins.param.param_depend import (
ClassDependency, ClassDependency,
runned, runned,
@ -29,14 +57,14 @@ async def test_depend(app: App, load_plugin):
assert len(runned) == 2 and runned[0] == runned[1] == 1 assert len(runned) == 2 and runned[0] == runned[1] == 1
runned.clear()
async with app.test_dependent(class_depend, allow_types=[DependParam]) as ctx: async with app.test_dependent(class_depend, allow_types=[DependParam]) as ctx:
ctx.should_return(ClassDependency(x=1, y=2)) ctx.should_return(ClassDependency(x=1, y=2))
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_bot(app: App, load_plugin): async def test_bot(app: App):
from nonebot.params import BotParam
from nonebot.exception import TypeMisMatch
from plugins.param.param_bot import ( from plugins.param.param_bot import (
FooBot, FooBot,
get_bot, get_bot,
@ -82,9 +110,7 @@ async def test_bot(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_event(app: App, load_plugin): async def test_event(app: App):
from nonebot.exception import TypeMisMatch
from nonebot.params import EventParam, DependParam
from plugins.param.param_event import ( from plugins.param.param_event import (
FooEvent, FooEvent,
event, event,
@ -159,25 +185,7 @@ async def test_event(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_state(app: App, load_plugin): async def test_state(app: App):
from nonebot.params import StateParam, DependParam
from nonebot.consts import (
CMD_KEY,
REGEX_STR,
PREFIX_KEY,
REGEX_DICT,
SHELL_ARGS,
SHELL_ARGV,
CMD_ARG_KEY,
KEYWORD_KEY,
RAW_CMD_KEY,
REGEX_GROUP,
ENDSWITH_KEY,
CMD_START_KEY,
FULLMATCH_KEY,
REGEX_MATCHED,
STARTSWITH_KEY,
)
from plugins.param.param_state import ( from plugins.param.param_state import (
state, state,
command, command,
@ -318,9 +326,7 @@ async def test_state(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_matcher(app: App, load_plugin): async def test_matcher(app: App):
from nonebot.matcher import Matcher
from nonebot.params import DependParam, MatcherParam
from plugins.param.param_matcher import matcher, receive, last_receive from plugins.param.param_matcher import matcher, receive, last_receive
fake_matcher = Matcher() fake_matcher = Matcher()
@ -348,9 +354,7 @@ async def test_matcher(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_arg(app: App, load_plugin): async def test_arg(app: App):
from nonebot.matcher import Matcher
from nonebot.params import ArgParam
from plugins.param.param_arg import arg, arg_str, arg_plain_text from plugins.param.param_arg import arg, arg_str, arg_plain_text
matcher = Matcher() matcher = Matcher()
@ -371,8 +375,7 @@ async def test_arg(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_exception(app: App, load_plugin): async def test_exception(app: App):
from nonebot.params import ExceptionParam
from plugins.param.param_exception import exc from plugins.param.param_exception import exc
exception = ValueError("test") exception = ValueError("test")
@ -382,8 +385,7 @@ async def test_exception(app: App, load_plugin):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_default(app: App, load_plugin): async def test_default(app: App):
from nonebot.params import DefaultParam
from plugins.param.param_default import default from plugins.param.param_default import default
async with app.test_dependent(default, allow_types=[DefaultParam]) as ctx: async with app.test_dependent(default, allow_types=[DefaultParam]) as ctx:

View File

@ -4,13 +4,26 @@ import pytest
from nonebug import App from nonebug import App
from utils import make_fake_event from utils import make_fake_event
from nonebot.exception import SkippedException
from nonebot.permission import (
USER,
NOTICE,
MESSAGE,
REQUEST,
METAEVENT,
SUPERUSER,
User,
Notice,
Message,
Request,
MetaEvent,
SuperUser,
Permission,
)
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_permission(app: App): async def test_permission(app: App):
from nonebot.permission import Permission
from nonebot.exception import SkippedException
async def falsy(): async def falsy():
return False return False
@ -42,20 +55,8 @@ async def test_permission(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize("type, expected", [("message", True), ("notice", False)])
"type,expected", async def test_message(type: str, expected: bool):
[
("message", True),
("notice", False),
],
)
async def test_message(
app: App,
type: str,
expected: bool,
):
from nonebot.permission import MESSAGE, Message
dependent = list(MESSAGE.checkers)[0] dependent = list(MESSAGE.checkers)[0]
checker = dependent.call checker = dependent.call
@ -66,20 +67,8 @@ async def test_message(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize("type, expected", [("message", False), ("notice", True)])
"type,expected", async def test_notice(type: str, expected: bool):
[
("message", False),
("notice", True),
],
)
async def test_notice(
app: App,
type: str,
expected: bool,
):
from nonebot.permission import NOTICE, Notice
dependent = list(NOTICE.checkers)[0] dependent = list(NOTICE.checkers)[0]
checker = dependent.call checker = dependent.call
@ -90,20 +79,8 @@ async def test_notice(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize("type, expected", [("message", False), ("request", True)])
"type,expected", async def test_request(type: str, expected: bool):
[
("message", False),
("request", True),
],
)
async def test_request(
app: App,
type: str,
expected: bool,
):
from nonebot.permission import REQUEST, Request
dependent = list(REQUEST.checkers)[0] dependent = list(REQUEST.checkers)[0]
checker = dependent.call checker = dependent.call
@ -114,20 +91,8 @@ async def test_request(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize("type, expected", [("message", False), ("meta_event", True)])
"type,expected", async def test_metaevent(type: str, expected: bool):
[
("message", False),
("meta_event", True),
],
)
async def test_metaevent(
app: App,
type: str,
expected: bool,
):
from nonebot.permission import METAEVENT, MetaEvent
dependent = list(METAEVENT.checkers)[0] dependent = list(METAEVENT.checkers)[0]
checker = dependent.call checker = dependent.call
@ -139,7 +104,7 @@ async def test_metaevent(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"type,user_id,expected", "type, user_id, expected",
[ [
("message", "test", True), ("message", "test", True),
("message", "foo", False), ("message", "foo", False),
@ -148,14 +113,7 @@ async def test_metaevent(
("notice", "test", True), ("notice", "test", True),
], ],
) )
async def test_superuser( async def test_superuser(app: App, type: str, user_id: str, expected: bool):
app: App,
type: str,
user_id: str,
expected: bool,
):
from nonebot.permission import SUPERUSER, SuperUser
dependent = list(SUPERUSER.checkers)[0] dependent = list(SUPERUSER.checkers)[0]
checker = dependent.call checker = dependent.call
@ -170,7 +128,7 @@ async def test_superuser(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"session_ids,session_id,expected", "session_ids, session_id, expected",
[ [
(("user", "foo"), "user", True), (("user", "foo"), "user", True),
(("user", "foo"), "bar", False), (("user", "foo"), "bar", False),
@ -180,8 +138,6 @@ async def test_superuser(
async def test_user( async def test_user(
app: App, session_ids: Tuple[str, ...], session_id: Optional[str], expected: bool app: App, session_ids: Tuple[str, ...], session_id: Optional[str], expected: bool
): ):
from nonebot.permission import USER, User
dependent = list(USER(*session_ids).checkers)[0] dependent = list(USER(*session_ids).checkers)[0]
checker = dependent.call checker = dependent.call

View File

@ -1,16 +1,11 @@
from typing import TYPE_CHECKING, Set
import pytest import pytest
from nonebug import App
if TYPE_CHECKING: import nonebot
from nonebot.plugin import Plugin from nonebot.plugin import PluginManager, _managers
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_plugin(app: App, load_plugin: Set["Plugin"]): async def test_get_plugin():
import nonebot
# check simple plugin # check simple plugin
plugin = nonebot.get_plugin("export") plugin = nonebot.get_plugin("export")
assert plugin assert plugin
@ -28,12 +23,15 @@ async def test_get_plugin(app: App, load_plugin: Set["Plugin"]):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_available_plugin(app: App): async def test_get_available_plugin():
import nonebot old_managers = _managers.copy()
from nonebot.plugin import PluginManager, _managers _managers.clear()
try:
_managers.append(PluginManager(["plugins.export", "plugin.require"])) _managers.append(PluginManager(["plugins.export", "plugin.require"]))
# check get available plugins # check get available plugins
plugin_names = nonebot.get_available_plugin_names() plugin_names = nonebot.get_available_plugin_names()
assert plugin_names == {"export", "require"} assert plugin_names == {"export", "require"}
finally:
_managers.clear()
_managers.extend(old_managers)

View File

@ -1,38 +1,32 @@
import sys import sys
from typing import Set
from pathlib import Path from pathlib import Path
from dataclasses import asdict from dataclasses import asdict
from typing import TYPE_CHECKING, Set
import pytest import pytest
from nonebug import App
if TYPE_CHECKING: import nonebot
from nonebot.plugin import Plugin from nonebot.plugin import Plugin, PluginManager, _managers
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_load_plugin(app: App): async def test_load_plugin():
import nonebot
# check regular # check regular
assert nonebot.load_plugin("plugins.metadata") assert nonebot.load_plugin("dynamic.simple")
# check path # check path
assert nonebot.load_plugin(Path("plugins/export")) assert nonebot.load_plugin(Path("dynamic/path.py"))
# check not found # check not found
assert nonebot.load_plugin("some_plugin_not_exist") is None assert nonebot.load_plugin("some_plugin_not_exist") is None
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_load_plugins(app: App, load_plugin: Set["Plugin"]): async def test_load_plugins(load_plugin: Set[Plugin], load_example: Set[Plugin]):
import nonebot
from nonebot.plugin import PluginManager
loaded_plugins = { loaded_plugins = {
plugin for plugin in nonebot.get_loaded_plugins() if not plugin.parent_plugin plugin for plugin in nonebot.get_loaded_plugins() if not plugin.parent_plugin
} }
assert loaded_plugins == load_plugin assert loaded_plugins >= load_plugin | load_example
# check simple plugin # check simple plugin
assert "plugins.export" in sys.modules assert "plugins.export" in sys.modules
@ -51,9 +45,7 @@ async def test_load_plugins(app: App, load_plugin: Set["Plugin"]):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_load_nested_plugin(app: App, load_plugin: Set["Plugin"]): async def test_load_nested_plugin():
import nonebot
parent_plugin = nonebot.get_plugin("nested") parent_plugin = nonebot.get_plugin("nested")
sub_plugin = nonebot.get_plugin("nested_subplugin") sub_plugin = nonebot.get_plugin("nested_subplugin")
sub_plugin2 = nonebot.get_plugin("nested_subplugin2") sub_plugin2 = nonebot.get_plugin("nested_subplugin2")
@ -64,9 +56,7 @@ async def test_load_nested_plugin(app: App, load_plugin: Set["Plugin"]):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_load_json(app: App): async def test_load_json():
import nonebot
nonebot.load_from_json("./plugins.json") nonebot.load_from_json("./plugins.json")
with pytest.raises(TypeError): with pytest.raises(TypeError):
@ -74,9 +64,7 @@ async def test_load_json(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_load_toml(app: App): async def test_load_toml():
import nonebot
nonebot.load_from_toml("./plugins.toml") nonebot.load_from_toml("./plugins.toml")
with pytest.raises(ValueError): with pytest.raises(ValueError):
@ -87,35 +75,27 @@ async def test_load_toml(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_bad_plugin(app: App): async def test_bad_plugin():
import nonebot
nonebot.load_plugins("bad_plugins") nonebot.load_plugins("bad_plugins")
assert nonebot.get_plugin("bad_plugins") is None assert nonebot.get_plugin("bad_plugins") is None
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_require_loaded(app: App, monkeypatch: pytest.MonkeyPatch): async def test_require_loaded(monkeypatch: pytest.MonkeyPatch):
import nonebot
def _patched_find(name: str): def _patched_find(name: str):
assert False pytest.fail("require existing plugin should not call find_manager_by_name")
monkeypatch.setattr("nonebot.plugin.load._find_manager_by_name", _patched_find) monkeypatch.setattr("nonebot.plugin.load._find_manager_by_name", _patched_find)
nonebot.load_plugin("plugins.export")
nonebot.require("plugins.export") nonebot.require("plugins.export")
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_require_not_loaded(app: App, monkeypatch: pytest.MonkeyPatch): async def test_require_not_loaded(monkeypatch: pytest.MonkeyPatch):
import nonebot m = PluginManager(["dynamic.require_not_loaded"])
from nonebot.plugin import PluginManager, _managers
m = PluginManager(["plugins.export"])
_managers.append(m) _managers.append(m)
num_managers = len(_managers)
origin_load = PluginManager.load_plugin origin_load = PluginManager.load_plugin
@ -125,33 +105,29 @@ async def test_require_not_loaded(app: App, monkeypatch: pytest.MonkeyPatch):
monkeypatch.setattr(PluginManager, "load_plugin", _patched_load) monkeypatch.setattr(PluginManager, "load_plugin", _patched_load)
nonebot.require("plugins.export") nonebot.require("dynamic.require_not_loaded")
assert len(_managers) == 1 assert len(_managers) == num_managers
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_require_not_declared(app: App): async def test_require_not_declared():
import nonebot num_managers = len(_managers)
from nonebot.plugin import _managers
nonebot.require("plugins.export") nonebot.require("dynamic.require_not_declared")
assert len(_managers) == 1 assert len(_managers) == num_managers + 1
assert _managers[-1].plugins == {"plugins.export"} assert _managers[-1].plugins == {"dynamic.require_not_declared"}
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_require_not_found(app: App): async def test_require_not_found():
import nonebot
with pytest.raises(RuntimeError): with pytest.raises(RuntimeError):
nonebot.require("some_plugin_not_exist") nonebot.require("some_plugin_not_exist")
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_plugin_metadata(app: App, load_plugin: Set["Plugin"]): async def test_plugin_metadata():
import nonebot
from plugins.metadata import Config from plugins.metadata import Config
plugin = nonebot.get_plugin("metadata") plugin = nonebot.get_plugin("metadata")

View File

@ -1,12 +1,11 @@
import pytest import pytest
from nonebug import App
from nonebot.plugin import PluginManager
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_load_plugin_name(app: App): async def test_load_plugin_name():
from nonebot.plugin import PluginManager m = PluginManager(plugins=["dynamic.manager"])
module1 = m.load_plugin("manager")
m = PluginManager(plugins=["plugins.export"]) module2 = m.load_plugin("dynamic.manager")
module1 = m.load_plugin("export")
module2 = m.load_plugin("plugins.export")
assert module1 is module2 assert module1 is module2

View File

@ -1,16 +1,11 @@
from typing import Type, Optional from typing import Type, Optional
import pytest import pytest
from nonebug import App
import nonebot
@pytest.mark.asyncio from nonebot.typing import T_RuleChecker
async def test_on(app: App, load_plugin): from nonebot.matcher import Matcher, matchers
import nonebot from nonebot.rule import (
import plugins.plugin.matchers as module
from nonebot.typing import T_RuleChecker
from nonebot.matcher import Matcher, matchers
from nonebot.rule import (
RegexRule, RegexRule,
IsTypeRule, IsTypeRule,
CommandRule, CommandRule,
@ -19,7 +14,12 @@ async def test_on(app: App, load_plugin):
FullmatchRule, FullmatchRule,
StartswithRule, StartswithRule,
ShellCommandRule, ShellCommandRule,
) )
@pytest.mark.asyncio
async def test_on():
import plugins.plugin.matchers as module
from plugins.plugin.matchers import ( from plugins.plugin.matchers import (
TestEvent, TestEvent,
rule, rule,

View File

@ -4,14 +4,51 @@ from typing import Dict, Tuple, Union, Optional
import pytest import pytest
from nonebug import App from nonebug import App
from nonebot.typing import T_State
from utils import make_fake_event, make_fake_message from utils import make_fake_event, make_fake_message
from nonebot.exception import ParserExit, SkippedException
from nonebot.consts import (
CMD_KEY,
REGEX_STR,
PREFIX_KEY,
REGEX_DICT,
SHELL_ARGS,
SHELL_ARGV,
CMD_ARG_KEY,
KEYWORD_KEY,
REGEX_GROUP,
ENDSWITH_KEY,
FULLMATCH_KEY,
REGEX_MATCHED,
STARTSWITH_KEY,
)
from nonebot.rule import (
Rule,
ToMeRule,
Namespace,
RegexRule,
IsTypeRule,
CommandRule,
EndswithRule,
KeywordsRule,
FullmatchRule,
ArgumentParser,
StartswithRule,
ShellCommandRule,
regex,
to_me,
command,
is_type,
keyword,
endswith,
fullmatch,
startswith,
shell_command,
)
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_rule(app: App): async def test_rule(app: App):
from nonebot.rule import Rule
from nonebot.exception import SkippedException
async def falsy(): async def falsy():
return False return False
@ -44,7 +81,7 @@ async def test_rule(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"msg,ignorecase,type,text,expected", "msg, ignorecase, type, text, expected",
[ [
("prefix", False, "message", "prefix_", True), ("prefix", False, "message", "prefix_", True),
("prefix", False, "message", "Prefix_", False), ("prefix", False, "message", "Prefix_", False),
@ -58,16 +95,12 @@ async def test_rule(app: App):
], ],
) )
async def test_startswith( async def test_startswith(
app: App,
msg: Union[str, Tuple[str, ...]], msg: Union[str, Tuple[str, ...]],
ignorecase: bool, ignorecase: bool,
type: str, type: str,
text: Optional[str], text: Optional[str],
expected: bool, expected: bool,
): ):
from nonebot.consts import STARTSWITH_KEY
from nonebot.rule import StartswithRule, startswith
test_startswith = startswith(msg, ignorecase) test_startswith = startswith(msg, ignorecase)
dependent = list(test_startswith.checkers)[0] dependent = list(test_startswith.checkers)[0]
checker = dependent.call checker = dependent.call
@ -87,7 +120,7 @@ async def test_startswith(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"msg,ignorecase,type,text,expected", "msg, ignorecase, type, text, expected",
[ [
("suffix", False, "message", "_suffix", True), ("suffix", False, "message", "_suffix", True),
("suffix", False, "message", "_Suffix", False), ("suffix", False, "message", "_Suffix", False),
@ -101,16 +134,12 @@ async def test_startswith(
], ],
) )
async def test_endswith( async def test_endswith(
app: App,
msg: Union[str, Tuple[str, ...]], msg: Union[str, Tuple[str, ...]],
ignorecase: bool, ignorecase: bool,
type: str, type: str,
text: Optional[str], text: Optional[str],
expected: bool, expected: bool,
): ):
from nonebot.consts import ENDSWITH_KEY
from nonebot.rule import EndswithRule, endswith
test_endswith = endswith(msg, ignorecase) test_endswith = endswith(msg, ignorecase)
dependent = list(test_endswith.checkers)[0] dependent = list(test_endswith.checkers)[0]
checker = dependent.call checker = dependent.call
@ -130,7 +159,7 @@ async def test_endswith(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"msg,ignorecase,type,text,expected", "msg, ignorecase, type, text, expected",
[ [
("fullmatch", False, "message", "fullmatch", True), ("fullmatch", False, "message", "fullmatch", True),
("fullmatch", False, "message", "Fullmatch", False), ("fullmatch", False, "message", "Fullmatch", False),
@ -144,16 +173,12 @@ async def test_endswith(
], ],
) )
async def test_fullmatch( async def test_fullmatch(
app: App,
msg: Union[str, Tuple[str, ...]], msg: Union[str, Tuple[str, ...]],
ignorecase: bool, ignorecase: bool,
type: str, type: str,
text: Optional[str], text: Optional[str],
expected: bool, expected: bool,
): ):
from nonebot.consts import FULLMATCH_KEY
from nonebot.rule import FullmatchRule, fullmatch
test_fullmatch = fullmatch(msg, ignorecase) test_fullmatch = fullmatch(msg, ignorecase)
dependent = list(test_fullmatch.checkers)[0] dependent = list(test_fullmatch.checkers)[0]
checker = dependent.call checker = dependent.call
@ -173,7 +198,7 @@ async def test_fullmatch(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"kws,type,text,expected", "kws, type, text, expected",
[ [
(("key",), "message", "_key_", True), (("key",), "message", "_key_", True),
(("key", "foo"), "message", "_foo_", True), (("key", "foo"), "message", "_foo_", True),
@ -183,15 +208,11 @@ async def test_fullmatch(
], ],
) )
async def test_keyword( async def test_keyword(
app: App,
kws: Tuple[str, ...], kws: Tuple[str, ...],
type: str, type: str,
text: Optional[str], text: Optional[str],
expected: bool, expected: bool,
): ):
from nonebot.consts import KEYWORD_KEY
from nonebot.rule import KeywordsRule, keyword
test_keyword = keyword(*kws) test_keyword = keyword(*kws)
dependent = list(test_keyword.checkers)[0] dependent = list(test_keyword.checkers)[0]
checker = dependent.call checker = dependent.call
@ -210,10 +231,7 @@ async def test_keyword(
@pytest.mark.parametrize( @pytest.mark.parametrize(
"cmds", [(("help",),), (("help", "foo"),), (("help",), ("foo",))] "cmds", [(("help",),), (("help", "foo"),), (("help",), ("foo",))]
) )
async def test_command(app: App, cmds: Tuple[Tuple[str, ...]]): async def test_command(cmds: Tuple[Tuple[str, ...]]):
from nonebot.rule import CommandRule, command
from nonebot.consts import CMD_KEY, PREFIX_KEY
test_command = command(*cmds) test_command = command(*cmds)
dependent = list(test_command.checkers)[0] dependent = list(test_command.checkers)[0]
checker = dependent.call checker = dependent.call
@ -227,12 +245,7 @@ async def test_command(app: App, cmds: Tuple[Tuple[str, ...]]):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_shell_command(app: App): async def test_shell_command():
from nonebot.typing import T_State
from nonebot.exception import ParserExit
from nonebot.consts import CMD_KEY, PREFIX_KEY, SHELL_ARGS, SHELL_ARGV, CMD_ARG_KEY
from nonebot.rule import Namespace, ArgumentParser, ShellCommandRule, shell_command
state: T_State state: T_State
CMD = ("test",) CMD = ("test",)
Message = make_fake_message() Message = make_fake_message()
@ -328,7 +341,7 @@ async def test_shell_command(app: App):
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize( @pytest.mark.parametrize(
"pattern,type,text,expected,matched,string,group,dict", "pattern, type, text, expected, matched, string, group, dict",
[ [
( (
r"(?P<key>key\d)", r"(?P<key>key\d)",
@ -345,7 +358,6 @@ async def test_shell_command(app: App):
], ],
) )
async def test_regex( async def test_regex(
app: App,
pattern: str, pattern: str,
type: str, type: str,
text: Optional[str], text: Optional[str],
@ -355,10 +367,6 @@ async def test_regex(
group: Optional[Tuple[str, ...]], group: Optional[Tuple[str, ...]],
dict: Optional[Dict[str, str]], dict: Optional[Dict[str, str]],
): ):
from nonebot.typing import T_State
from nonebot.rule import RegexRule, regex
from nonebot.consts import REGEX_STR, REGEX_DICT, REGEX_GROUP, REGEX_MATCHED
test_regex = regex(pattern) test_regex = regex(pattern)
dependent = list(test_regex.checkers)[0] dependent = list(test_regex.checkers)[0]
checker = dependent.call checker = dependent.call
@ -378,9 +386,7 @@ async def test_regex(
@pytest.mark.asyncio @pytest.mark.asyncio
@pytest.mark.parametrize("expected", [True, False]) @pytest.mark.parametrize("expected", [True, False])
async def test_to_me(app: App, expected: bool): async def test_to_me(expected: bool):
from nonebot.rule import ToMeRule, to_me
test_to_me = to_me() test_to_me = to_me()
dependent = list(test_to_me.checkers)[0] dependent = list(test_to_me.checkers)[0]
checker = dependent.call checker = dependent.call
@ -392,9 +398,7 @@ async def test_to_me(app: App, expected: bool):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_is_type(app: App): async def test_is_type():
from nonebot.rule import IsTypeRule, is_type
Event1 = make_fake_event() Event1 = make_fake_event()
Event2 = make_fake_event() Event2 = make_fake_event()
Event3 = make_fake_event() Event3 = make_fake_event()

View File

@ -1,11 +1,10 @@
import json import json
from utils import make_fake_message from utils import make_fake_message
from nonebot.utils import DataclassEncoder
def test_dataclass_encoder(): def test_dataclass_encoder():
from nonebot.utils import DataclassEncoder
simple = json.dumps("123", cls=DataclassEncoder) simple = json.dumps("123", cls=DataclassEncoder)
assert simple == '"123"' assert simple == '"123"'

View File

@ -1,9 +1,8 @@
from typing import TYPE_CHECKING, Type, Union, Mapping, Iterable, Optional from typing import Type, Union, Mapping, Iterable, Optional
from pydantic import create_model from pydantic import create_model
if TYPE_CHECKING: from nonebot.adapters import Event, Message, MessageSegment
from nonebot.adapters import Event, Message
def escape_text(s: str, *, escape_comma: bool = True) -> str: def escape_text(s: str, *, escape_comma: bool = True) -> str:
@ -14,8 +13,6 @@ def escape_text(s: str, *, escape_comma: bool = True) -> str:
def make_fake_message(): def make_fake_message():
from nonebot.adapters import Message, MessageSegment
class FakeMessageSegment(MessageSegment): class FakeMessageSegment(MessageSegment):
@classmethod @classmethod
def get_message_class(cls): def get_message_class(cls):
@ -61,18 +58,16 @@ def make_fake_message():
def make_fake_event( def make_fake_event(
_base: Optional[Type["Event"]] = None, _base: Optional[Type[Event]] = None,
_type: str = "message", _type: str = "message",
_name: str = "test", _name: str = "test",
_description: str = "test", _description: str = "test",
_user_id: Optional[str] = "test", _user_id: Optional[str] = "test",
_session_id: Optional[str] = "test", _session_id: Optional[str] = "test",
_message: Optional["Message"] = None, _message: Optional[Message] = None,
_to_me: bool = True, _to_me: bool = True,
**fields, **fields,
) -> Type["Event"]: ) -> Type[Event]:
from nonebot.adapters import Event
_Fake = create_model("_Fake", __base__=_base or Event, **fields) _Fake = create_model("_Fake", __base__=_base or Event, **fields)
class FakeEvent(_Fake): class FakeEvent(_Fake):