Skip to content

Commit 7e71b73

Browse files
authored
Fix #1450 slack_file in image block/element (#1452)
1 parent 00bb7cd commit 7e71b73

5 files changed

Lines changed: 130 additions & 22 deletions

File tree

slack_sdk/models/blocks/basic_components.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,32 @@ def to_dict(self) -> Dict[str, Any]: # skipcq: PYL-W0221
559559
else:
560560
json["trigger"] = self._trigger
561561
return json
562+
563+
564+
class SlackFile(JsonObject):
565+
attributes = {"id", "url"}
566+
567+
def __init__(
568+
self,
569+
*,
570+
id: Optional[str] = None,
571+
url: Optional[str] = None,
572+
):
573+
"""An object containing Slack file information to be used in an image block or image element.
574+
https://api.slack.com/reference/block-kit/composition-objects#slack_file
575+
576+
Args:
577+
id: Slack ID of the file.
578+
url: This URL can be the url_private or the permalink of the Slack file.
579+
"""
580+
self._id = id
581+
self._url = url
582+
583+
def to_dict(self) -> Dict[str, Any]: # skipcq: PYL-W0221
584+
self.validate_json()
585+
json = {}
586+
if self._id is not None:
587+
json["id"] = self._id
588+
if self._url is not None:
589+
json["url"] = self._url
590+
return json

slack_sdk/models/blocks/block_elements.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
JsonValidator,
1212
EnumValidator,
1313
)
14-
from .basic_components import ButtonStyles, Workflow
14+
from .basic_components import ButtonStyles, Workflow, SlackFile
1515
from .basic_components import ConfirmObject
1616
from .basic_components import DispatchActionConfig
1717
from .basic_components import MarkdownTextObject
@@ -551,13 +551,14 @@ class ImageElement(BlockElement):
551551

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

556556
def __init__(
557557
self,
558558
*,
559-
image_url: Optional[str] = None,
560559
alt_text: Optional[str] = None,
560+
image_url: Optional[str] = None,
561+
slack_file: Optional[Union[Dict[str, Any], SlackFile]] = None,
561562
**others: dict,
562563
):
563564
"""An element to insert an image - this element can be used in section and
@@ -566,18 +567,20 @@ def __init__(
566567
https://api.slack.com/reference/block-kit/block-elements#image
567568
568569
Args:
569-
image_url (required): The URL of the image to be displayed.
570570
alt_text (required): A plain-text summary of the image. This should not contain any markup.
571+
image_url: The URL of the image to be displayed.
572+
slack_file: A Slack image file object that defines the source of the image.
571573
"""
572574
super().__init__(type=self.type)
573575
show_unknown_key_warning(self, others)
574576

575577
self.image_url = image_url
576578
self.alt_text = alt_text
579+
self.slack_file = slack_file if slack_file is None or isinstance(slack_file, SlackFile) else SlackFile(**slack_file)
577580

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

582585
@JsonValidator(f"alt_text attribute cannot exceed {alt_text_max_length} characters")
583586
def _validate_alt_text_length(self) -> bool:

slack_sdk/models/blocks/blocks.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
JsonObject,
99
JsonValidator,
1010
)
11-
from .basic_components import MarkdownTextObject
11+
from .basic_components import MarkdownTextObject, SlackFile
1212
from .basic_components import PlainTextObject
1313
from .basic_components import TextObject
1414
from .block_elements import BlockElement, RichTextElement
@@ -208,7 +208,7 @@ class ImageBlock(Block):
208208

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

213213
image_url_max_length = 3000
214214
alt_text_max_length = 2000
@@ -217,8 +217,9 @@ def attributes(self) -> Set[str]:
217217
def __init__(
218218
self,
219219
*,
220-
image_url: str,
221220
alt_text: str,
221+
image_url: Optional[str] = None,
222+
slack_file: Optional[Union[Dict[str, Any], SlackFile]] = None,
222223
title: Optional[Union[str, dict, PlainTextObject]] = None,
223224
block_id: Optional[str] = None,
224225
**others: dict,
@@ -227,10 +228,11 @@ def __init__(
227228
https://api.slack.com/reference/block-kit/blocks#image
228229
229230
Args:
230-
image_url (required): The URL of the image to be displayed.
231-
Maximum length for this field is 3000 characters.
232231
alt_text (required): A plain-text summary of the image. This should not contain any markup.
233232
Maximum length for this field is 2000 characters.
233+
image_url: The URL of the image to be displayed.
234+
Maximum length for this field is 3000 characters.
235+
slack_file: A Slack image file object that defines the source of the image.
234236
title: An optional title for the image in the form of a text object that can only be of type: plain_text.
235237
Maximum length for the text in this field is 2000 characters.
236238
block_id: A string acting as a unique identifier for a block. If not specified, one will be generated.
@@ -255,11 +257,15 @@ def __init__(
255257
parsed_title = title
256258
else:
257259
raise SlackObjectFormationError(f"Unsupported type for title in an image block: {type(title)}")
260+
if slack_file is not None:
261+
self.slack_file = (
262+
slack_file if slack_file is None or isinstance(slack_file, SlackFile) else SlackFile(**slack_file)
263+
)
258264
self.title = parsed_title
259265

260266
@JsonValidator(f"image_url attribute cannot exceed {image_url_max_length} characters")
261267
def _validate_image_url_length(self):
262-
return len(self.image_url) <= self.image_url_max_length
268+
return self.image_url is None or len(self.image_url) <= self.image_url_max_length
263269

264270
@JsonValidator(f"alt_text attribute cannot exceed {alt_text_max_length} characters")
265271
def _validate_alt_text_length(self):

tests/slack_sdk/models/test_blocks.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
RichTextPreformattedElement,
3030
RichTextElementParts,
3131
)
32+
from slack_sdk.models.blocks.basic_components import SlackFile
3233
from . import STRING_3001_CHARS
3334

3435

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

154-
button = LinkButtonElement(text="Click me!", url="http://google.com")
155+
button = LinkButtonElement(text="Click me!", url="https://example.com")
155156
self.assertDictEqual(
156157
{
157158
"type": "section",
@@ -314,11 +315,11 @@ def test_issue_1369_title_type(self):
314315
def test_json(self):
315316
self.assertDictEqual(
316317
{
317-
"image_url": "http://google.com",
318+
"image_url": "https://example.com",
318319
"alt_text": "not really an image",
319320
"type": "image",
320321
},
321-
ImageBlock(image_url="http://google.com", alt_text="not really an image").to_dict(),
322+
ImageBlock(image_url="https://example.com", alt_text="not really an image").to_dict(),
322323
)
323324

324325
def test_image_url_length(self):
@@ -327,11 +328,45 @@ def test_image_url_length(self):
327328

328329
def test_alt_text_length(self):
329330
with self.assertRaises(SlackObjectFormationError):
330-
ImageBlock(image_url="http://google.com", alt_text=STRING_3001_CHARS).to_dict()
331+
ImageBlock(image_url="https://example.com", alt_text=STRING_3001_CHARS).to_dict()
331332

332333
def test_title_length(self):
333334
with self.assertRaises(SlackObjectFormationError):
334-
ImageBlock(image_url="http://google.com", alt_text="text", title=STRING_3001_CHARS).to_dict()
335+
ImageBlock(image_url="https://example.com", alt_text="text", title=STRING_3001_CHARS).to_dict()
336+
337+
def test_slack_file(self):
338+
self.assertDictEqual(
339+
{
340+
"slack_file": {"url": "https://example.com"},
341+
"alt_text": "not really an image",
342+
"type": "image",
343+
},
344+
ImageBlock(slack_file=SlackFile(url="https://example.com"), alt_text="not really an image").to_dict(),
345+
)
346+
self.assertDictEqual(
347+
{
348+
"slack_file": {"id": "F11111"},
349+
"alt_text": "not really an image",
350+
"type": "image",
351+
},
352+
ImageBlock(slack_file=SlackFile(id="F11111"), alt_text="not really an image").to_dict(),
353+
)
354+
self.assertDictEqual(
355+
{
356+
"slack_file": {"url": "https://example.com"},
357+
"alt_text": "not really an image",
358+
"type": "image",
359+
},
360+
ImageBlock(slack_file={"url": "https://example.com"}, alt_text="not really an image").to_dict(),
361+
)
362+
self.assertDictEqual(
363+
{
364+
"slack_file": {"id": "F11111"},
365+
"alt_text": "not really an image",
366+
"type": "image",
367+
},
368+
ImageBlock(slack_file={"id": "F11111"}, alt_text="not really an image").to_dict(),
369+
)
335370

336371

337372
# ----------------------------------------------
@@ -446,7 +481,7 @@ def test_document_2(self):
446481
def test_json(self):
447482
self.elements = [
448483
ButtonElement(text="Click me", action_id="reg_button", value="1"),
449-
LinkButtonElement(text="URL Button", url="http://google.com"),
484+
LinkButtonElement(text="URL Button", url="https://example.com"),
450485
]
451486
self.dict_elements = []
452487
for e in self.elements:

tests/slack_sdk/models/test_elements.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
InteractiveElement,
2929
PlainTextObject,
3030
)
31+
from slack_sdk.models.blocks.basic_components import SlackFile
3132
from slack_sdk.models.blocks.block_elements import (
3233
DateTimePickerElement,
3334
EmailInputElement,
@@ -186,11 +187,11 @@ def test_action_id(self):
186187

187188
class LinkButtonElementTests(unittest.TestCase):
188189
def test_json(self):
189-
button = LinkButtonElement(action_id="test", text="button text", url="http://google.com")
190+
button = LinkButtonElement(action_id="test", text="button text", url="https://example.com")
190191
self.assertDictEqual(
191192
{
192193
"text": {"emoji": True, "text": "button text", "type": "plain_text"},
193-
"url": "http://google.com",
194+
"url": "https://example.com",
194195
"type": "button",
195196
"action_id": button.action_id,
196197
},
@@ -456,11 +457,11 @@ def test_document(self):
456457
def test_json(self):
457458
self.assertDictEqual(
458459
{
459-
"image_url": "http://google.com",
460+
"image_url": "https://example.com",
460461
"alt_text": "not really an image",
461462
"type": "image",
462463
},
463-
ImageElement(image_url="http://google.com", alt_text="not really an image").to_dict(),
464+
ImageElement(image_url="https://example.com", alt_text="not really an image").to_dict(),
464465
)
465466

466467
def test_image_url_length(self):
@@ -469,7 +470,41 @@ def test_image_url_length(self):
469470

470471
def test_alt_text_length(self):
471472
with self.assertRaises(SlackObjectFormationError):
472-
ImageElement(image_url="http://google.com", alt_text=STRING_3001_CHARS).to_dict()
473+
ImageElement(image_url="https://example.com", alt_text=STRING_3001_CHARS).to_dict()
474+
475+
def test_slack_file(self):
476+
self.assertDictEqual(
477+
{
478+
"slack_file": {"id": "F11111"},
479+
"alt_text": "not really an image",
480+
"type": "image",
481+
},
482+
ImageElement(slack_file=SlackFile(id="F11111"), alt_text="not really an image").to_dict(),
483+
)
484+
self.assertDictEqual(
485+
{
486+
"slack_file": {"url": "https://example.com"},
487+
"alt_text": "not really an image",
488+
"type": "image",
489+
},
490+
ImageElement(slack_file=SlackFile(url="https://example.com"), alt_text="not really an image").to_dict(),
491+
)
492+
self.assertDictEqual(
493+
{
494+
"slack_file": {"id": "F11111"},
495+
"alt_text": "not really an image",
496+
"type": "image",
497+
},
498+
ImageElement(slack_file={"id": "F11111"}, alt_text="not really an image").to_dict(),
499+
)
500+
self.assertDictEqual(
501+
{
502+
"slack_file": {"url": "https://example.com"},
503+
"alt_text": "not really an image",
504+
"type": "image",
505+
},
506+
ImageElement(slack_file={"url": "https://example.com"}, alt_text="not really an image").to_dict(),
507+
)
473508

474509

475510
# -------------------------------------------------

0 commit comments

Comments
 (0)