Skip to content

Commit

Permalink
Enable rich_text_* elements to have an empty 'elements' property (#1576)
Browse files Browse the repository at this point in the history
  • Loading branch information
seratch authored Oct 30, 2024
1 parent 7e586bd commit 39d9704
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
17 changes: 17 additions & 0 deletions slack_sdk/models/basic_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ def __str__(self):
return f"<slack_sdk.{self.__class__.__name__}>"


# Usually, Block Kit components do not allow an empty array for a property value, but there are some exceptions.
EMPTY_ALLOWED_TYPE_AND_PROPERTY_LIST = [
{"type": "rich_text_section", "property": "elements"},
{"type": "rich_text_list", "property": "elements"},
{"type": "rich_text_preformatted", "property": "elements"},
{"type": "rich_text_quote", "property": "elements"},
]


class JsonObject(BaseObject, metaclass=ABCMeta):
"""The base class for JSON serializable class objects"""

Expand Down Expand Up @@ -51,6 +60,14 @@ def is_not_empty(self, key: str) -> bool:
value = getattr(self, key, None)
if value is None:
return False

# Usually, Block Kit components do not allow an empty array for a property value, but there are some exceptions.
# The following code deals with these exceptions:
type_value = getattr(self, "type", None)
for empty_allowed in EMPTY_ALLOWED_TYPE_AND_PROPERTY_LIST:
if type_value == empty_allowed["type"] and key == empty_allowed["property"]:
return True

has_len = getattr(value, "__len__", None) is not None
if has_len: # skipcq: PYL-R1705
return len(value) > 0
Expand Down
24 changes: 24 additions & 0 deletions tests/slack_sdk/models/test_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1143,3 +1143,27 @@ def test_elements_are_parsed(self):
self.assertIsInstance(block.elements[3], RichTextListElement)
self.assertIsInstance(block.elements[3].elements[0], RichTextSectionElement)
self.assertIsInstance(block.elements[3].elements[0].elements[0], RichTextElementParts.Text)

def test_parsing_empty_block_elements(self):
empty_element_block = {
"block_id": "my-block",
"type": "rich_text",
"elements": [
{"type": "rich_text_section", "elements": []},
{"type": "rich_text_list", "style": "bullet", "elements": []},
{"type": "rich_text_preformatted", "elements": []},
{"type": "rich_text_quote", "elements": []},
],
}
block = RichTextBlock(**empty_element_block)
self.assertIsInstance(block.elements[0], RichTextSectionElement)
self.assertIsNotNone(block.elements[0].elements)
self.assertIsNotNone(block.elements[1].elements)
self.assertIsNotNone(block.elements[2].elements)
self.assertIsNotNone(block.elements[3].elements)

block_dict = block.to_dict()
self.assertIsNotNone(block_dict["elements"][0].get("elements"))
self.assertIsNotNone(block_dict["elements"][1].get("elements"))
self.assertIsNotNone(block_dict["elements"][2].get("elements"))
self.assertIsNotNone(block_dict["elements"][3].get("elements"))

0 comments on commit 39d9704

Please sign in to comment.