diff --git a/slack_sdk/models/basic_objects.py b/slack_sdk/models/basic_objects.py index 232ec21e..bd9ffe58 100644 --- a/slack_sdk/models/basic_objects.py +++ b/slack_sdk/models/basic_objects.py @@ -12,6 +12,15 @@ def __str__(self): return f"" +# 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""" @@ -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 diff --git a/tests/slack_sdk/models/test_blocks.py b/tests/slack_sdk/models/test_blocks.py index 65f0bafd..940669b0 100644 --- a/tests/slack_sdk/models/test_blocks.py +++ b/tests/slack_sdk/models/test_blocks.py @@ -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"))