From 910cf8cd05bfa25011d6200a026244665dfe668f Mon Sep 17 00:00:00 2001 From: ryche Date: Thu, 16 May 2024 12:30:25 +0200 Subject: [PATCH] add support for URLTextInput and EmailTextInput elements --- blockkit/elements.py | 59 +++++++++++++++++++++++++++++++++++++++++- blockkit/validators.py | 3 ++- requirements.txt | 2 +- setup.py | 4 +-- tests/test_elements.py | 59 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 122 insertions(+), 5 deletions(-) diff --git a/blockkit/elements.py b/blockkit/elements.py index 7640fa3..e206b54 100644 --- a/blockkit/elements.py +++ b/blockkit/elements.py @@ -2,7 +2,7 @@ from datetime import date, datetime, time from typing import List, Optional, Union -from pydantic import AnyUrl, Field, model_validator +from pydantic import AnyUrl, EmailStr, Field, model_validator from pydantic.networks import HttpUrl from blockkit.components import Component @@ -52,6 +52,8 @@ "RichTextSection", "RichTextList", "FileInput", + "EmailTextInput", + "URLTextInput", ] @@ -738,3 +740,58 @@ def __init__( max_files=max_files, ) + +class EmailTextInput(FocusableElement): + type: str = "email_text_input" + placeholder: Union[PlainText, str, None] = None + initial_value: Optional[EmailStr] = None + dispatch_action_config: Optional[DispatchActionConfig] = None + + _validate_placeholder = validator( + "placeholder", validate_text_length, max_length=150 + ) + + def __init__( + self, + *, + action_id: Optional[str] = None, + placeholder: Union[PlainText, str, None] = None, + initial_value: Optional[EmailStr] = None, + dispatch_action_config: Optional[DispatchActionConfig] = None, + focus_on_load: Optional[bool] = None, + ): + super().__init__( + action_id=action_id, + placeholder=placeholder, + initial_value=initial_value, + dispatch_action_config=dispatch_action_config, + focus_on_load=focus_on_load, + ) + + +class URLTextInput(FocusableElement): + type: str = "url_text_input" + placeholder: Union[PlainText, str, None] = None + initial_value: Optional[AnyUrl] = None + dispatch_action_config: Optional[DispatchActionConfig] = None + + _validate_placeholder = validator( + "placeholder", validate_text_length, max_length=150 + ) + + def __init__( + self, + *, + action_id: Optional[str] = None, + placeholder: Union[PlainText, str, None] = None, + initial_value: Optional[AnyUrl] = None, + dispatch_action_config: Optional[DispatchActionConfig] = None, + focus_on_load: Optional[bool] = None, + ): + super().__init__( + action_id=action_id, + placeholder=placeholder, + initial_value=initial_value, + dispatch_action_config=dispatch_action_config, + focus_on_load=focus_on_load, + ) diff --git a/blockkit/validators.py b/blockkit/validators.py index 6b6e254..3c879c4 100644 --- a/blockkit/validators.py +++ b/blockkit/validators.py @@ -52,4 +52,5 @@ def validate_datetime(v: Union[int, datetime]) -> Optional[int]: else: _ = datetime.fromtimestamp(v) return v - return v \ No newline at end of file + return v + diff --git a/requirements.txt b/requirements.txt index 9d3360e..1ea2ac1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pytest>=6.0,<7.0 -pydantic>=2,<3 +pydantic[email]>=2,<3 black>=23.0 python-dateutil>=2.8,<3.0 diff --git a/setup.py b/setup.py index 3a5b23e..b1e13b2 100644 --- a/setup.py +++ b/setup.py @@ -13,9 +13,9 @@ EMAIL = "imryche13@gmail.com" AUTHOR = "Dmitry Chernyshov" REQUIRES_PYTHON = ">=3.7.0" -VERSION = "1.8.4" +VERSION = "1.9.0" -REQUIRED = ["pydantic>=2,<3"] +REQUIRED = ["pydantic[email]>=2,<3"] EXTRAS = {"gen": ["black"]} here = os.path.abspath(os.path.dirname(__file__)) diff --git a/tests/test_elements.py b/tests/test_elements.py index 1b23117..ed873f8 100644 --- a/tests/test_elements.py +++ b/tests/test_elements.py @@ -11,6 +11,7 @@ ConversationsSelect, DatePicker, DatetimePicker, + EmailTextInput, ExternalSelect, FileInput, Image, @@ -28,6 +29,7 @@ RichTextSection, StaticSelect, TimePicker, + URLTextInput, UsersSelect, ) from blockkit.objects import ( @@ -1580,3 +1582,60 @@ def test_fileinput_excessive_max_files_raises_exception(): with pytest.raises(ValidationError): FileInput(max_files=11) + +def test_builds_email_text_input(): + assert EmailTextInput( + action_id="action_id", + initial_value="dima@botsignals.co", + dispatch_action_config=DispatchActionConfig( + trigger_actions_on=["on_character_entered"] + ), + focus_on_load=True, + placeholder=PlainText(text="placeholder"), + ).build() == { + "type": "email_text_input", + "action_id": "action_id", + "initial_value": "dima@botsignals.co", + "dispatch_action_config": {"trigger_actions_on": ["on_character_entered"]}, + "focus_on_load": True, + "placeholder": {"type": "plain_text", "text": "placeholder"}, + } + + +def test_email_text_input_excessive_placeholder_raises_exception(): + with pytest.raises(ValidationError): + EmailTextInput(placeholder=PlainText(text="p" * 151)) + + +def test_email_text_input_invalid_initial_value_raises_exception(): + with pytest.raises(ValidationError): + EmailTextInput(initial_value="dimabotsignals.co") + + +def test_builds_url_text_input(): + assert URLTextInput( + action_id="action_id", + initial_value="https://example.com/", + dispatch_action_config=DispatchActionConfig( + trigger_actions_on=["on_character_entered"] + ), + focus_on_load=True, + placeholder=PlainText(text="placeholder"), + ).build() == { + "type": "url_text_input", + "action_id": "action_id", + "initial_value": "https://example.com/", + "dispatch_action_config": {"trigger_actions_on": ["on_character_entered"]}, + "focus_on_load": True, + "placeholder": {"type": "plain_text", "text": "placeholder"}, + } + + +def test_url_text_input_excessive_placeholder_raises_exception(): + with pytest.raises(ValidationError): + URLTextInput(placeholder=PlainText(text="p" * 151)) + + +def test_url_text_input_invalid_initial_value_raises_exception(): + with pytest.raises(ValidationError): + URLTextInput(initial_value="foo bar")