From 853b72f38d284c9af61fbda80f8a2952752b1a4d Mon Sep 17 00:00:00 2001 From: Alex Root Junior Date: Sun, 16 Jul 2023 23:04:06 +0300 Subject: [PATCH] Added possibility to use HashTag/CashTag elements without prefixing content, added `sep: str` argument to the `as_line` function. --- aiogram/utils/formatting.py | 31 +++++++++++++++++-- tests/test_utils/test_formatting.py | 46 +++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/aiogram/utils/formatting.py b/aiogram/utils/formatting.py index 049db003..132e04f2 100644 --- a/aiogram/utils/formatting.py +++ b/aiogram/utils/formatting.py @@ -226,6 +226,15 @@ class HashTag(Text): type = MessageEntityType.HASHTAG + def __init__(self, *body: NodeType, **params: Any) -> None: + if len(body) != 1: + raise ValueError("Hashtag can contain only one element") + if not isinstance(body[0], str): + raise ValueError("Hashtag can contain only string") + if not body[0].startswith("#"): + body = ("#" + body[0],) + super().__init__(*body, **params) + class CashTag(Text): """ @@ -241,6 +250,15 @@ class CashTag(Text): type = MessageEntityType.CASHTAG + def __init__(self, *body: NodeType, **params: Any) -> None: + if len(body) != 1: + raise ValueError("Cashtag can contain only one element") + if not isinstance(body[0], str): + raise ValueError("Cashtag can contain only string") + if not body[0].startswith("$"): + body = ("$" + body[0],) + super().__init__(*body, **params) + class BotCommand(Text): """ @@ -474,15 +492,24 @@ def _unparse_entities( yield remove_surrogates(text[offset:length]) -def as_line(*items: NodeType, end: str = "\n") -> Text: +def as_line(*items: NodeType, end: str = "\n", sep: str = "") -> Text: """ Wrap multiple nodes into line with :code:`\\\\n` at the end of line. :param items: Text or Any :param end: ending of the line, by default is :code:`\\\\n` + :param sep: separator between items, by default is empty string :return: Text """ - return Text(*items, end) + if sep: + nodes = [] + for item in items[:-1]: + nodes.extend([item, sep]) + nodes.append(items[-1]) + nodes.append(end) + else: + nodes = [*items, end] + return Text(*nodes) def as_list(*items: NodeType, sep: str = "\n") -> Text: diff --git a/tests/test_utils/test_formatting.py b/tests/test_utils/test_formatting.py index 5e14c4dc..f135aca6 100644 --- a/tests/test_utils/test_formatting.py +++ b/tests/test_utils/test_formatting.py @@ -276,6 +276,42 @@ class TestNode: ) +class TestHashTag: + def test_only_one_element_in_body(self): + with pytest.raises(ValueError): + HashTag("test", "test") + + def test_body_is_not_str(self): + with pytest.raises(ValueError): + HashTag(Text("test")) + + def test_with_no_prefix(self): + node = HashTag("test") + assert node._body == ("#test",) + + def test_with_prefix(self): + node = HashTag("#test") + assert node._body == ("#test",) + + +class TestCashTag: + def test_only_one_element_in_body(self): + with pytest.raises(ValueError): + CashTag("test", "test") + + def test_body_is_not_str(self): + with pytest.raises(ValueError): + CashTag(Text("test")) + + def test_with_no_prefix(self): + node = CashTag("USD") + assert node._body == ("$USD",) + + def test_with_prefix(self): + node = CashTag("$USD") + assert node._body == ("$USD",) + + class TestUtils: def test_apply_entity(self): node = _apply_entity( @@ -289,6 +325,16 @@ class TestUtils: assert isinstance(node, Text) assert len(node._body) == 4 # 3 + '\n' + def test_line_with_sep(self): + node = as_line("test", "test", "test", sep=" ") + assert isinstance(node, Text) + assert len(node._body) == 6 # 3 + 2 * ' ' + '\n' + + def test_as_line_single_element_with_sep(self): + node = as_line("test", sep=" ") + assert isinstance(node, Text) + assert len(node._body) == 2 # 1 + '\n' + def test_as_list(self): node = as_list("test", "test", "test") assert isinstance(node, Text)