@@ -283,75 +283,7 @@ Defined in `.github/workflows/ci-build.yml`, runs on push to `main`, all PRs, an
283283
284284### Adding a New Block Kit Type
285285
286- Block Kit models live in ` slack_sdk/models/blocks/ ` across three files:
287-
288- | File | Contents |
289- | --- | --- |
290- | ` blocks.py ` | Layout blocks (` SectionBlock ` , ` ActionsBlock ` , ` HeaderBlock ` , etc.) |
291- | ` block_elements.py ` | Interactive elements (` ButtonElement ` , ` StaticSelectElement ` , ` DatePickerElement ` , etc.) |
292- | ` basic_components.py ` | Composition objects (` TextObject ` , ` Option ` , ` ConfirmObject ` , etc.) |
293-
294- All types are exported from ` slack_sdk/models/blocks/__init__.py ` .
295-
296- #### Base class hierarchy
297-
298- ```
299- JsonObject
300- ├── Block → layout blocks
301- ├── BlockElement → non-interactive elements
302- │ └── InteractiveElement → elements with action_id
303- │ └── InputInteractiveElement → elements usable inside InputBlock
304- ├── TextObject → PlainTextObject, MarkdownTextObject
305- ├── Option / OptionGroup
306- └── ConfirmObject, etc.
307- ```
308-
309- Choose the base class that matches the type you're adding.
310-
311- #### Steps
312-
313- 1 . ** Define the class** in the appropriate file. Follow this pattern:
314-
315- ``` python
316- class MyNewBlock (Block ):
317- type = " my_new_block"
318-
319- @ property
320- def attributes (self ) -> Set[str ]:
321- return super ().attributes.union({" text" , " optional_field" })
322-
323- def __init__ (self , * , text : Union[str , dict , TextObject], optional_field : Optional[str ] = None , block_id : Optional[str ] = None , ** others : dict ):
324- super ().__init__ (type = self .type, block_id = block_id)
325- show_unknown_key_warning(self , others)
326- self .text = TextObject.parse(text, default_type = PlainTextObject.type)
327- self .optional_field = optional_field
328-
329- @JsonValidator (" text must be provided" )
330- def _validate_text (self ):
331- return self .text is not None
332- ```
333-
334- Key conventions:
335- - Set ` type ` class attribute to the Slack API type string
336- - Override ` attributes ` to return the set of JSON field names for serialization
337- - Call ` super().__init__() ` with ` type=self.type `
338- - Call ` show_unknown_key_warning(self, others) ` to log unexpected kwargs
339- - Use ` TextObject.parse() ` , ` ConfirmObject.parse() ` , and ` BlockElement.parse() ` for nested composition objects
340- - Add ` @JsonValidator ` decorators for constraints (required fields, max lengths, enum values, date formats)
341- - Use ` @EnumValidator ` for fields restricted to a set of values
342-
343- 2 . ** Register for deserialization:**
344- - ** Elements:** Automatic — ` BlockElement.parse() ` discovers subclasses at runtime via ` __subclasses__() ` . No manual step needed.
345- - ** Blocks:** Manual — add an ` elif ` clause in ` Block.parse() ` (in ` blocks.py ` ) mapping the type string to the new class.
346-
347- 3 . ** Export the class** — add it to the imports and ` __all__ ` list in ` slack_sdk/models/blocks/__init__.py ` .
348-
349- 4 . ** Add tests** in ` tests/slack_sdk/models/test_blocks.py ` . Cover:
350- - Round-trip: ` input_dict == MyNewBlock(**input_dict).to_dict() `
351- - Validation: required fields raise ` SlackObjectFormationError ` when missing
352- - Constraints: max lengths, enum values, format patterns
353-
354- 5 . ** Validate:** ` ./scripts/run_validation.sh `
286+ See [ ` slack_sdk/models/AGENTS.md ` ] ( slack_sdk/models/AGENTS.md ) for detailed steps on defining, registering, exporting, and testing new Block Kit blocks, elements, and composition objects.
355287
356288### Fixing a Bug
357289
0 commit comments