From 37b1f043434b75b1cb8321133bc0c92dff11627d Mon Sep 17 00:00:00 2001 From: Alexandra Dolidze Date: Thu, 30 Jan 2025 15:13:11 +0300 Subject: [PATCH 1/4] feat: add conditional processing oppotunity --- chatsky/core/script_function.py | 12 ++++++++++-- tests/core/test_processing.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/chatsky/core/script_function.py b/chatsky/core/script_function.py index 3ebeeb1d9..6ab3e76e3 100644 --- a/chatsky/core/script_function.py +++ b/chatsky/core/script_function.py @@ -200,6 +200,12 @@ class BaseProcessing(BaseScriptFunc, ABC): These are used in :py:attr:`chatsky.core.script.Node.pre_transition` and :py:attr:`chatsky.core.script.Node.pre_response`. """ + + start_condition: AnyCondition = Field(default=True, validate_default=True) + """ + :py:data:`~.AnyCondition` is invoked before each component execution; + component is executed only if it returns ``True``. + """ return_type: ClassVar[Union[type, Tuple[type, ...]]] = type(None) @@ -211,8 +217,10 @@ async def wrapped_call(self, ctx: Context, *, info: str = "") -> Union[None, Exc return await super().wrapped_call(ctx, info=info) async def __call__(self, ctx: Context) -> None: - return await super().__call__(ctx) - + if await self.start_condition.is_true(ctx): + return await super().__call__(ctx) + else: + return logger.debug(f"{self.__class__.__name__} not called: self.start_condition = {self.start_condition}") class BasePriority(BaseScriptFunc, ABC): """ diff --git a/tests/core/test_processing.py b/tests/core/test_processing.py index 0c3e7c509..fadd6936b 100644 --- a/tests/core/test_processing.py +++ b/tests/core/test_processing.py @@ -1,7 +1,8 @@ -from chatsky import proc, Context, BaseResponse, MessageInitTypes, Message +from chatsky import proc, Context, BaseResponse, MessageInitTypes, Message, BaseProcessing from chatsky.core.script import Node + async def test_modify_response(): ctx = Context() ctx.framework_data.current_node = Node() @@ -22,3 +23,33 @@ async def modified_response(self, original_response: BaseResponse, ctx: Context) assert ctx.current_node.response.__class__.__name__ == "ModifiedResponse" assert await ctx.current_node.response(ctx) == Message(misc={"msg": Message("hi")}) +class TestConditionalResponce: + async def test_conditional_response(self): + ctx = Context() + ctx.framework_data.current_node = Node() + some_list = [] + + class SomeProcessing(BaseProcessing): + async def call(self, ctx: Context): + some_list.append("") + + await SomeProcessing()(ctx) + assert some_list == [""] + + await SomeProcessing().wrapped_call(ctx) + assert some_list == ["", ""] + + async def test_conditional_processing_false_condition(self): + ctx = Context() + ctx.framework_data.current_node = Node() + some_list = [] + + class SomeProcessing(BaseProcessing): + async def call(self, ctx: Context): + some_list.append("") + + await SomeProcessing(start_condition = False)(ctx) + assert some_list == [] + + await SomeProcessing(start_condition = False).wrapped_call(ctx) + assert some_list == [] \ No newline at end of file From bb263a523555e666ce2db4088ee30677f62a986b Mon Sep 17 00:00:00 2001 From: Alexandra Dolidze Date: Thu, 6 Feb 2025 16:52:51 +0300 Subject: [PATCH 2/4] feat: new conditional processing branch --- chatsky/core/script_function.py | 7 ++++--- tests/core/test_processing.py | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/chatsky/core/script_function.py b/chatsky/core/script_function.py index 6ab3e76e3..64f46eb55 100644 --- a/chatsky/core/script_function.py +++ b/chatsky/core/script_function.py @@ -200,7 +200,7 @@ class BaseProcessing(BaseScriptFunc, ABC): These are used in :py:attr:`chatsky.core.script.Node.pre_transition` and :py:attr:`chatsky.core.script.Node.pre_response`. """ - + start_condition: AnyCondition = Field(default=True, validate_default=True) """ :py:data:`~.AnyCondition` is invoked before each component execution; @@ -219,8 +219,9 @@ async def wrapped_call(self, ctx: Context, *, info: str = "") -> Union[None, Exc async def __call__(self, ctx: Context) -> None: if await self.start_condition.is_true(ctx): return await super().__call__(ctx) - else: - return logger.debug(f"{self.__class__.__name__} not called: self.start_condition = {self.start_condition}") + # else: + # return logger.debug(f"{self.__class__.__name__} not called: self.start_condition = {self.start_condition}") + class BasePriority(BaseScriptFunc, ABC): """ diff --git a/tests/core/test_processing.py b/tests/core/test_processing.py index fadd6936b..0b7ba848a 100644 --- a/tests/core/test_processing.py +++ b/tests/core/test_processing.py @@ -2,7 +2,6 @@ from chatsky.core.script import Node - async def test_modify_response(): ctx = Context() ctx.framework_data.current_node = Node() @@ -23,6 +22,8 @@ async def modified_response(self, original_response: BaseResponse, ctx: Context) assert ctx.current_node.response.__class__.__name__ == "ModifiedResponse" assert await ctx.current_node.response(ctx) == Message(misc={"msg": Message("hi")}) + + class TestConditionalResponce: async def test_conditional_response(self): ctx = Context() @@ -48,8 +49,8 @@ class SomeProcessing(BaseProcessing): async def call(self, ctx: Context): some_list.append("") - await SomeProcessing(start_condition = False)(ctx) + await SomeProcessing(start_condition=False)(ctx) assert some_list == [] - await SomeProcessing(start_condition = False).wrapped_call(ctx) - assert some_list == [] \ No newline at end of file + await SomeProcessing(start_condition=False).wrapped_call(ctx) + assert some_list == [] From ecbf04abdb8e9c2be34f797991ced0d90bc96528 Mon Sep 17 00:00:00 2001 From: Alexandra Dolidze Date: Fri, 7 Feb 2025 15:53:53 +0300 Subject: [PATCH 3/4] test for script_function.py fixed --- chatsky/core/script_function.py | 4 ++-- tests/core/test_script_function.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/chatsky/core/script_function.py b/chatsky/core/script_function.py index 64f46eb55..62e91b458 100644 --- a/chatsky/core/script_function.py +++ b/chatsky/core/script_function.py @@ -219,8 +219,8 @@ async def wrapped_call(self, ctx: Context, *, info: str = "") -> Union[None, Exc async def __call__(self, ctx: Context) -> None: if await self.start_condition.is_true(ctx): return await super().__call__(ctx) - # else: - # return logger.debug(f"{self.__class__.__name__} not called: self.start_condition = {self.start_condition}") + else: + return logger.debug(f"{self.__class__.__name__} not called: self.start_condition = {self.start_condition}") class BasePriority(BaseScriptFunc, ABC): diff --git a/tests/core/test_script_function.py b/tests/core/test_script_function.py index 0d23126a1..c099b86b6 100644 --- a/tests/core/test_script_function.py +++ b/tests/core/test_script_function.py @@ -47,8 +47,8 @@ async def call(self, ctx): raise RuntimeError() assert isinstance(await MyProc().wrapped_call(None), RuntimeError) - assert len(log_list) == 1 - assert log_list[0].levelname == "ERROR" + assert len(log_list) == 2 + assert log_list[1].levelname == "ERROR" async def test_base_exception_not_handled(self): class SpecialException(BaseException): From 28cd19c1ecd000a4bddc0d563c89e5a9e1fd86a4 Mon Sep 17 00:00:00 2001 From: Alexandra Dolidze Date: Mon, 10 Feb 2025 16:45:27 +0300 Subject: [PATCH 4/4] doc for BaseProcessing updated --- chatsky/core/script_function.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chatsky/core/script_function.py b/chatsky/core/script_function.py index 62e91b458..0dd4b54b6 100644 --- a/chatsky/core/script_function.py +++ b/chatsky/core/script_function.py @@ -203,8 +203,8 @@ class BaseProcessing(BaseScriptFunc, ABC): start_condition: AnyCondition = Field(default=True, validate_default=True) """ - :py:data:`~.AnyCondition` is invoked before each component execution; - component is executed only if it returns ``True``. + :py:data:`~.AnyCondition` is checked before __call__; + __call__ is initiated only if start_condition returns ``True``. """ return_type: ClassVar[Union[type, Tuple[type, ...]]] = type(None)