Skip to content

Commit

Permalink
Merge pull request Tishka17#349 from Tishka17/feature/or_text
Browse files Browse the repository at this point in the history
Or text
  • Loading branch information
Tishka17 authored Dec 26, 2023
2 parents e492ffc + b81e129 commit e71f047
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
49 changes: 49 additions & 0 deletions src/aiogram_dialog/widgets/text/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ def __radd__(self, other: Union["Text", str]):
other = Const(other)
return Multi(other, self, sep="")

def __or__(self, other: Union["Text", str]):
if isinstance(other, str):
other = Const(other)
return Or(self, other)

def __ror__(self, other: Union["Text", str]):
if isinstance(other, str):
other = Const(other)
return Or(other, self)

def find(self, widget_id: str) -> Optional["Text"]:
# no reimplementation, just change return type
return super().find(widget_id)
Expand Down Expand Up @@ -101,3 +111,42 @@ def find(self, widget_id: str) -> Optional[Text]:
if found := text.find(widget_id):
return found
return None


class Or(Text):
def __init__(self, *texts: Text):
super().__init__()
self.texts = texts

async def _render_text(
self, data: Dict, manager: DialogManager,
) -> str:
for text in self.texts:
res = await text.render_text(data, manager)
if res:
return res
return ""

def __ior__(self, other: Union[Text, str]) -> "Or":
if isinstance(other, str):
other = Const(other)
self.texts += (other,)
return self

def __or__(self, other: Union[Text, str]) -> "Or":
if isinstance(other, str):
other = Const(other)
# reduce nesting
return Or(*self.texts, other)

def __ror__(self, other: Union[Text, str]) -> "Or":
if isinstance(other, str):
return Const(other)
# reduce nesting
return Or(other, *self.texts)

def find(self, widget_id: str) -> Optional[Text]:
for text in self.texts:
if found := text.find(widget_id):
return found
return None
82 changes: 82 additions & 0 deletions tests/widgets/text/test_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from unittest.mock import Mock

import pytest
from aiogram import F
from aiogram.fsm.state import State

from aiogram_dialog import DialogManager
from aiogram_dialog.api.entities import Context
from aiogram_dialog.widgets.text import Const


@pytest.fixture()
def mock_manager() -> DialogManager:
manager = Mock()
context = Context(
dialog_data={},
start_data={},
widget_data={},
state=State(),
_stack_id="_stack_id",
_intent_id="_intent_id",
)
manager.current_context = Mock(side_effect=lambda: context)

return manager


@pytest.mark.asyncio
async def test_add_const(mock_manager):
text = Const("Hello, ") + Const("world!")
res = await text.render_text({}, mock_manager)
assert res == "Hello, world!"


@pytest.mark.asyncio
async def test_add_add(mock_manager):
text = Const("Hello, ") + Const("world") + Const("!")
res = await text.render_text({}, mock_manager)
assert res == "Hello, world!"


@pytest.mark.asyncio
async def test_add_str(mock_manager):
text = Const("Hello, ") + "world!"
res = await text.render_text({}, mock_manager)
assert res == "Hello, world!"


@pytest.mark.asyncio
async def test_add_str_rght(mock_manager):
text = "Hello, " + Const("world!")
res = await text.render_text({}, mock_manager)
assert res == "Hello, world!"


@pytest.mark.asyncio
async def test_or(mock_manager):
text = Const("A") | Const("B")
res = await text.render_text({}, mock_manager)
assert res == "A"


@pytest.mark.asyncio
async def test_ror_str(mock_manager):
text = "A" | Const("B")
res = await text.render_text({}, mock_manager)
assert res == "A"


@pytest.mark.asyncio
async def test_or_condition(mock_manager):
text = (
Const("A", when=F["a"]) |
Const("B", when=F["b"]) |
Const("C")
)
res = await text.render_text({"a": True}, mock_manager)
assert res == "A"
res = await text.render_text({"b": True}, mock_manager)
assert res == "B"
res = await text.render_text({}, mock_manager)
assert res == "C"

0 comments on commit e71f047

Please sign in to comment.