From 67f5b87492952423f5f9a5200164c7dd78be0f64 Mon Sep 17 00:00:00 2001 From: AkiraXie Date: Thu, 20 Jan 2022 02:05:57 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=90=9B=20fix=20single=5Fsession=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot/plugins/single_session.py | 41 +++++++++++++++---------------- tests/test_single_session.py | 28 +++++++++++++++++++++ 2 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 tests/test_single_session.py diff --git a/nonebot/plugins/single_session.py b/nonebot/plugins/single_session.py index e76e1a1b..3bed8ea1 100644 --- a/nonebot/plugins/single_session.py +++ b/nonebot/plugins/single_session.py @@ -1,34 +1,33 @@ -from typing import Dict - +from typing import Generator, Dict from nonebot.adapters import Event from nonebot.message import ( IgnoredException, - run_preprocessor, - run_postprocessor, + event_preprocessor ) +from nonebot.params import Depends _running_matcher: Dict[str, int] = {} -@run_preprocessor -async def preprocess(event: Event): +async def matcher_mutex(event: Event) -> Generator[bool, None, None]: + result = False try: session_id = event.get_session_id() except Exception: - return - current_event_id = id(event) - event_id = _running_matcher.get(session_id, None) - if event_id and event_id != current_event_id: + yield result + else: + current_event_id = id(event) + event_id = _running_matcher.get(session_id, None) + if event_id : + result = event_id != current_event_id + else: + _running_matcher[session_id] = current_event_id + yield result + if result: + del _running_matcher[session_id] + +@event_preprocessor +async def preprocess(mutex: bool = Depends(matcher_mutex)): + if mutex: raise IgnoredException("Another matcher running") - _running_matcher[session_id] = current_event_id - - -@run_postprocessor -async def postprocess(event: Event): - try: - session_id = event.get_session_id() - except Exception: - return - if session_id in _running_matcher: - del _running_matcher[session_id] diff --git a/tests/test_single_session.py b/tests/test_single_session.py new file mode 100644 index 00000000..f0a696d5 --- /dev/null +++ b/tests/test_single_session.py @@ -0,0 +1,28 @@ +from contextlib import asynccontextmanager + +import pytest + +from utils import make_fake_event + + +@pytest.mark.asyncio +async def test_matcher_mutex(): + from nonebot.plugins.single_session import matcher_mutex + + am = asynccontextmanager(matcher_mutex) + event = make_fake_event()() + event_1 = make_fake_event()() + event_2 = make_fake_event(_session_id="test1")() + + async with am(event) as ctx: + assert ctx == False + + async with am(event) as ctx: + async with am(event_1) as ctx_1: + assert ctx == False + assert ctx_1 == True + + async with am(event) as ctx: + async with am(event_2) as ctx_2: + assert ctx == False + assert ctx_2 == False From b3d0e7c5480786b671b40437caf74b4b3425e90f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 19 Jan 2022 18:10:30 +0000 Subject: [PATCH 2/3] :rotating_light: auto fix by pre-commit hooks --- nonebot/plugins/single_session.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/nonebot/plugins/single_session.py b/nonebot/plugins/single_session.py index 3bed8ea1..d0e5b4a6 100644 --- a/nonebot/plugins/single_session.py +++ b/nonebot/plugins/single_session.py @@ -1,10 +1,8 @@ -from typing import Generator, Dict +from typing import Dict, Generator + from nonebot.adapters import Event -from nonebot.message import ( - IgnoredException, - event_preprocessor -) from nonebot.params import Depends +from nonebot.message import IgnoredException, event_preprocessor _running_matcher: Dict[str, int] = {} @@ -18,7 +16,7 @@ async def matcher_mutex(event: Event) -> Generator[bool, None, None]: else: current_event_id = id(event) event_id = _running_matcher.get(session_id, None) - if event_id : + if event_id: result = event_id != current_event_id else: _running_matcher[session_id] = current_event_id @@ -26,8 +24,8 @@ async def matcher_mutex(event: Event) -> Generator[bool, None, None]: if result: del _running_matcher[session_id] + @event_preprocessor async def preprocess(mutex: bool = Depends(matcher_mutex)): if mutex: raise IgnoredException("Another matcher running") - From f6308916ad37b3638895a246b90e54836ac5567d Mon Sep 17 00:00:00 2001 From: AkiraXie Date: Thu, 20 Jan 2022 03:16:04 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=90=9B=20fix=20bug=20and=20improve=20?= =?UTF-8?q?test=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot/plugins/single_session.py | 2 +- tests/test_single_session.py | 10 +++++++++- tests/utils.py | 6 ++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/nonebot/plugins/single_session.py b/nonebot/plugins/single_session.py index d0e5b4a6..11b5b6cc 100644 --- a/nonebot/plugins/single_session.py +++ b/nonebot/plugins/single_session.py @@ -21,7 +21,7 @@ async def matcher_mutex(event: Event) -> Generator[bool, None, None]: else: _running_matcher[session_id] = current_event_id yield result - if result: + if not result: del _running_matcher[session_id] diff --git a/tests/test_single_session.py b/tests/test_single_session.py index f0a696d5..1a2bc67f 100644 --- a/tests/test_single_session.py +++ b/tests/test_single_session.py @@ -7,22 +7,30 @@ from utils import make_fake_event @pytest.mark.asyncio async def test_matcher_mutex(): - from nonebot.plugins.single_session import matcher_mutex + from nonebot.plugins.single_session import matcher_mutex, _running_matcher am = asynccontextmanager(matcher_mutex) event = make_fake_event()() event_1 = make_fake_event()() event_2 = make_fake_event(_session_id="test1")() + event_3 = make_fake_event(_session_id=None)() async with am(event) as ctx: assert ctx == False + assert not _running_matcher async with am(event) as ctx: async with am(event_1) as ctx_1: assert ctx == False assert ctx_1 == True + assert not _running_matcher async with am(event) as ctx: async with am(event_2) as ctx_2: assert ctx == False assert ctx_2 == False + assert not _running_matcher + + async with am(event_3) as ctx_3: + assert ctx_3 == False + assert not _running_matcher diff --git a/tests/utils.py b/tests/utils.py index 711c7c05..e82ad7d9 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -50,7 +50,7 @@ def make_fake_event( _name: str = "test", _description: str = "test", _user_id: str = "test", - _session_id: str = "test", + _session_id: Optional[str] = "test", _message: Optional["Message"] = None, _to_me: bool = True, **fields, @@ -73,7 +73,9 @@ def make_fake_event( return _user_id def get_session_id(self) -> str: - return _session_id + if _session_id is not None: + return _session_id + raise NotImplementedError def get_message(self) -> "Message": if _message is not None: