Skip to content

Commit

Permalink
Fix slackapi#1450 slack_file in image block/element
Browse files Browse the repository at this point in the history
  • Loading branch information
seratch committed Jan 26, 2024
1 parent dc96f5f commit beee68b
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 22 deletions.
22 changes: 22 additions & 0 deletions slack_sdk/models/blocks/basic_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,3 +559,25 @@ def to_dict(self) -> Dict[str, Any]: # skipcq: PYL-W0221
else:
json["trigger"] = self._trigger
return json


class SlackFile(JsonObject):
attributes = {"id", "url"}

def __init__(
self,
*,
id: Optional[str] = None,
url: Optional[str] = None,
):
self._id = id
self._url = url

def to_dict(self) -> Dict[str, Any]: # skipcq: PYL-W0221
self.validate_json()
json = {}
if self._id is not None:
json["id"] = self._id
if self._url is not None:
json["url"] = self._url
return json
13 changes: 8 additions & 5 deletions slack_sdk/models/blocks/block_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
JsonValidator,
EnumValidator,
)
from .basic_components import ButtonStyles, Workflow
from .basic_components import ButtonStyles, Workflow, SlackFile
from .basic_components import ConfirmObject
from .basic_components import DispatchActionConfig
from .basic_components import MarkdownTextObject
Expand Down Expand Up @@ -551,13 +551,14 @@ class ImageElement(BlockElement):

@property
def attributes(self) -> Set[str]:
return super().attributes.union({"alt_text", "image_url"})
return super().attributes.union({"alt_text", "image_url", "slack_file"})

def __init__(
self,
*,
image_url: Optional[str] = None,
alt_text: Optional[str] = None,
image_url: Optional[str] = None,
slack_file: Optional[Union[Dict[str, Any], SlackFile]] = None,
**others: dict,
):
"""An element to insert an image - this element can be used in section and
Expand All @@ -566,18 +567,20 @@ def __init__(
https://api.slack.com/reference/block-kit/block-elements#image
Args:
image_url (required): The URL of the image to be displayed.
alt_text (required): A plain-text summary of the image. This should not contain any markup.
image_url: The URL of the image to be displayed.
slack_file: A Slack image file object that defines the source of the image.
"""
super().__init__(type=self.type)
show_unknown_key_warning(self, others)

self.image_url = image_url
self.alt_text = alt_text
self.slack_file = slack_file if slack_file is None or isinstance(slack_file, SlackFile) else SlackFile(**slack_file)

@JsonValidator(f"image_url attribute cannot exceed {image_url_max_length} characters")
def _validate_image_url_length(self) -> bool:
return len(self.image_url) <= self.image_url_max_length
return self.image_url is None or len(self.image_url) <= self.image_url_max_length

@JsonValidator(f"alt_text attribute cannot exceed {alt_text_max_length} characters")
def _validate_alt_text_length(self) -> bool:
Expand Down
18 changes: 12 additions & 6 deletions slack_sdk/models/blocks/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
JsonObject,
JsonValidator,
)
from .basic_components import MarkdownTextObject
from .basic_components import MarkdownTextObject, SlackFile
from .basic_components import PlainTextObject
from .basic_components import TextObject
from .block_elements import BlockElement, RichTextElement
Expand Down Expand Up @@ -208,7 +208,7 @@ class ImageBlock(Block):

@property
def attributes(self) -> Set[str]:
return super().attributes.union({"alt_text", "image_url", "title"})
return super().attributes.union({"alt_text", "image_url", "title", "slack_file"})

image_url_max_length = 3000
alt_text_max_length = 2000
Expand All @@ -217,8 +217,9 @@ def attributes(self) -> Set[str]:
def __init__(
self,
*,
image_url: str,
alt_text: str,
image_url: Optional[str] = None,
slack_file: Optional[Union[Dict[str, Any], SlackFile]] = None,
title: Optional[Union[str, dict, PlainTextObject]] = None,
block_id: Optional[str] = None,
**others: dict,
Expand All @@ -227,10 +228,11 @@ def __init__(
https://api.slack.com/reference/block-kit/blocks#image
Args:
image_url (required): The URL of the image to be displayed.
Maximum length for this field is 3000 characters.
alt_text (required): A plain-text summary of the image. This should not contain any markup.
Maximum length for this field is 2000 characters.
image_url: The URL of the image to be displayed.
Maximum length for this field is 3000 characters.
slack_file: A Slack image file object that defines the source of the image.
title: An optional title for the image in the form of a text object that can only be of type: plain_text.
Maximum length for the text in this field is 2000 characters.
block_id: A string acting as a unique identifier for a block. If not specified, one will be generated.
Expand All @@ -255,11 +257,15 @@ def __init__(
parsed_title = title
else:
raise SlackObjectFormationError(f"Unsupported type for title in an image block: {type(title)}")
if slack_file is not None:
self.slack_file = (
slack_file if slack_file is None or isinstance(slack_file, SlackFile) else SlackFile(**slack_file)
)
self.title = parsed_title

@JsonValidator(f"image_url attribute cannot exceed {image_url_max_length} characters")
def _validate_image_url_length(self):
return len(self.image_url) <= self.image_url_max_length
return self.image_url is None or len(self.image_url) <= self.image_url_max_length

@JsonValidator(f"alt_text attribute cannot exceed {alt_text_max_length} characters")
def _validate_alt_text_length(self):
Expand Down
47 changes: 41 additions & 6 deletions tests/slack_sdk/models/test_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
RichTextPreformattedElement,
RichTextElementParts,
)
from slack_sdk.models.blocks.basic_components import SlackFile
from . import STRING_3001_CHARS


Expand Down Expand Up @@ -151,7 +152,7 @@ def test_json(self):
SectionBlock(text="some text", fields=[f"field{i}" for i in range(5)]).to_dict(),
)

button = LinkButtonElement(text="Click me!", url="http://google.com")
button = LinkButtonElement(text="Click me!", url="https://example.com")
self.assertDictEqual(
{
"type": "section",
Expand Down Expand Up @@ -314,11 +315,11 @@ def test_issue_1369_title_type(self):
def test_json(self):
self.assertDictEqual(
{
"image_url": "http://google.com",
"image_url": "https://example.com",
"alt_text": "not really an image",
"type": "image",
},
ImageBlock(image_url="http://google.com", alt_text="not really an image").to_dict(),
ImageBlock(image_url="https://example.com", alt_text="not really an image").to_dict(),
)

def test_image_url_length(self):
Expand All @@ -327,13 +328,47 @@ def test_image_url_length(self):

def test_alt_text_length(self):
with self.assertRaises(SlackObjectFormationError):
ImageBlock(image_url="http://google.com", alt_text=STRING_3001_CHARS).to_dict()
ImageBlock(image_url="https://example.com", alt_text=STRING_3001_CHARS).to_dict()

def test_title_length(self):
with self.assertRaises(SlackObjectFormationError):
ImageBlock(image_url="http://google.com", alt_text="text", title=STRING_3001_CHARS).to_dict()
ImageBlock(image_url="https://example.com", alt_text="text", title=STRING_3001_CHARS).to_dict()


def test_slack_file(self):
self.assertDictEqual(
{
"slack_file": {"url": "https://example.com" },
"alt_text": "not really an image",
"type": "image",
},
ImageBlock(slack_file=SlackFile(url="https://example.com"), alt_text="not really an image").to_dict(),
)
self.assertDictEqual(
{
"slack_file": {"id": "F11111" },
"alt_text": "not really an image",
"type": "image",
},
ImageBlock(slack_file=SlackFile(id="F11111"), alt_text="not really an image").to_dict(),
)
self.assertDictEqual(
{
"slack_file": {"url": "https://example.com" },
"alt_text": "not really an image",
"type": "image",
},
ImageBlock(slack_file= {"url": "https://example.com" }, alt_text="not really an image").to_dict(),
)
self.assertDictEqual(
{
"slack_file": {"id": "F11111" },
"alt_text": "not really an image",
"type": "image",
},
ImageBlock(slack_file={"id": "F11111" }, alt_text="not really an image").to_dict(),
)

# ----------------------------------------------
# Actions
# ----------------------------------------------
Expand Down Expand Up @@ -446,7 +481,7 @@ def test_document_2(self):
def test_json(self):
self.elements = [
ButtonElement(text="Click me", action_id="reg_button", value="1"),
LinkButtonElement(text="URL Button", url="http://google.com"),
LinkButtonElement(text="URL Button", url="https://example.com"),
]
self.dict_elements = []
for e in self.elements:
Expand Down
45 changes: 40 additions & 5 deletions tests/slack_sdk/models/test_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
InteractiveElement,
PlainTextObject,
)
from slack_sdk.models.blocks.basic_components import SlackFile
from slack_sdk.models.blocks.block_elements import (
DateTimePickerElement,
EmailInputElement,
Expand Down Expand Up @@ -186,11 +187,11 @@ def test_action_id(self):

class LinkButtonElementTests(unittest.TestCase):
def test_json(self):
button = LinkButtonElement(action_id="test", text="button text", url="http://google.com")
button = LinkButtonElement(action_id="test", text="button text", url="https://example.com")
self.assertDictEqual(
{
"text": {"emoji": True, "text": "button text", "type": "plain_text"},
"url": "http://google.com",
"url": "https://example.com",
"type": "button",
"action_id": button.action_id,
},
Expand Down Expand Up @@ -456,11 +457,11 @@ def test_document(self):
def test_json(self):
self.assertDictEqual(
{
"image_url": "http://google.com",
"image_url": "https://example.com",
"alt_text": "not really an image",
"type": "image",
},
ImageElement(image_url="http://google.com", alt_text="not really an image").to_dict(),
ImageElement(image_url="https://example.com", alt_text="not really an image").to_dict(),
)

def test_image_url_length(self):
Expand All @@ -469,7 +470,41 @@ def test_image_url_length(self):

def test_alt_text_length(self):
with self.assertRaises(SlackObjectFormationError):
ImageElement(image_url="http://google.com", alt_text=STRING_3001_CHARS).to_dict()
ImageElement(image_url="https://example.com", alt_text=STRING_3001_CHARS).to_dict()

def test_slack_file(self):
self.assertDictEqual(
{
"slack_file": {"id": "F11111"},
"alt_text": "not really an image",
"type": "image",
},
ImageElement(slack_file=SlackFile(id="F11111"), alt_text="not really an image").to_dict(),
)
self.assertDictEqual(
{
"slack_file": {"url": "https://example.com"},
"alt_text": "not really an image",
"type": "image",
},
ImageElement(slack_file=SlackFile(url="https://example.com"), alt_text="not really an image").to_dict(),
)
self.assertDictEqual(
{
"slack_file": {"id": "F11111"},
"alt_text": "not really an image",
"type": "image",
},
ImageElement(slack_file={"id": "F11111"}, alt_text="not really an image").to_dict(),
)
self.assertDictEqual(
{
"slack_file": {"url": "https://example.com"},
"alt_text": "not really an image",
"type": "image",
},
ImageElement(slack_file= {"url": "https://example.com"}, alt_text="not really an image").to_dict(),
)


# -------------------------------------------------
Expand Down

0 comments on commit beee68b

Please sign in to comment.