Skip to content

Commit b401e58

Browse files
feat: support markdown_text parameter (#1718)
* feat: support markdown_text parameter * fix format issues * rename test file and improve tests coverage * clean things up based on feedback * fix imports
1 parent 8922dc8 commit b401e58

File tree

7 files changed

+167
-22
lines changed

7 files changed

+167
-22
lines changed

slack_sdk/web/async_client.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
_to_v2_file_upload_item,
3131
_update_call_participants,
3232
_validate_for_legacy_client,
33-
_warn_if_text_or_attachment_fallback_is_missing,
33+
_warn_if_message_text_content_is_missing,
3434
)
3535

3636

@@ -2695,6 +2695,7 @@ async def chat_postEphemeral(
26952695
link_names: Optional[bool] = None,
26962696
username: Optional[str] = None,
26972697
parse: Optional[str] = None,
2698+
markdown_text: Optional[str] = None,
26982699
**kwargs,
26992700
) -> AsyncSlackResponse:
27002701
"""Sends an ephemeral message to a user in a channel.
@@ -2714,11 +2715,12 @@ async def chat_postEphemeral(
27142715
"link_names": link_names,
27152716
"username": username,
27162717
"parse": parse,
2718+
"markdown_text": markdown_text,
27172719
}
27182720
)
27192721
_parse_web_class_objects(kwargs)
27202722
kwargs = _remove_none_values(kwargs)
2721-
_warn_if_text_or_attachment_fallback_is_missing("chat.postEphemeral", kwargs)
2723+
_warn_if_message_text_content_is_missing("chat.postEphemeral", kwargs)
27222724
# NOTE: intentionally using json over params for the API methods using blocks/attachments
27232725
return await self.api_call("chat.postEphemeral", json=kwargs)
27242726

@@ -2742,6 +2744,7 @@ async def chat_postMessage(
27422744
username: Optional[str] = None,
27432745
parse: Optional[str] = None, # none, full
27442746
metadata: Optional[Union[Dict, Metadata]] = None,
2747+
markdown_text: Optional[str] = None,
27452748
**kwargs,
27462749
) -> AsyncSlackResponse:
27472750
"""Sends a message to a channel.
@@ -2766,11 +2769,12 @@ async def chat_postMessage(
27662769
"username": username,
27672770
"parse": parse,
27682771
"metadata": metadata,
2772+
"markdown_text": markdown_text,
27692773
}
27702774
)
27712775
_parse_web_class_objects(kwargs)
27722776
kwargs = _remove_none_values(kwargs)
2773-
_warn_if_text_or_attachment_fallback_is_missing("chat.postMessage", kwargs)
2777+
_warn_if_message_text_content_is_missing("chat.postMessage", kwargs)
27742778
# NOTE: intentionally using json over params for the API methods using blocks/attachments
27752779
return await self.api_call("chat.postMessage", json=kwargs)
27762780

@@ -2779,7 +2783,7 @@ async def chat_scheduleMessage(
27792783
*,
27802784
channel: str,
27812785
post_at: Union[str, int],
2782-
text: str,
2786+
text: Optional[str] = None,
27832787
as_user: Optional[bool] = None,
27842788
attachments: Optional[Union[str, Sequence[Union[Dict, Attachment]]]] = None,
27852789
blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None,
@@ -2790,6 +2794,7 @@ async def chat_scheduleMessage(
27902794
unfurl_media: Optional[bool] = None,
27912795
link_names: Optional[bool] = None,
27922796
metadata: Optional[Union[Dict, Metadata]] = None,
2797+
markdown_text: Optional[str] = None,
27932798
**kwargs,
27942799
) -> AsyncSlackResponse:
27952800
"""Schedules a message.
@@ -2810,11 +2815,12 @@ async def chat_scheduleMessage(
28102815
"unfurl_media": unfurl_media,
28112816
"link_names": link_names,
28122817
"metadata": metadata,
2818+
"markdown_text": markdown_text,
28132819
}
28142820
)
28152821
_parse_web_class_objects(kwargs)
28162822
kwargs = _remove_none_values(kwargs)
2817-
_warn_if_text_or_attachment_fallback_is_missing("chat.scheduleMessage", kwargs)
2823+
_warn_if_message_text_content_is_missing("chat.scheduleMessage", kwargs)
28182824
# NOTE: intentionally using json over params for the API methods using blocks/attachments
28192825
return await self.api_call("chat.scheduleMessage", json=kwargs)
28202826

@@ -2867,6 +2873,7 @@ async def chat_update(
28672873
parse: Optional[str] = None, # none, full
28682874
reply_broadcast: Optional[bool] = None,
28692875
metadata: Optional[Union[Dict, Metadata]] = None,
2876+
markdown_text: Optional[str] = None,
28702877
**kwargs,
28712878
) -> AsyncSlackResponse:
28722879
"""Updates a message in a channel.
@@ -2884,6 +2891,7 @@ async def chat_update(
28842891
"parse": parse,
28852892
"reply_broadcast": reply_broadcast,
28862893
"metadata": metadata,
2894+
"markdown_text": markdown_text,
28872895
}
28882896
)
28892897
if isinstance(file_ids, (list, tuple)):
@@ -2892,7 +2900,7 @@ async def chat_update(
28922900
kwargs.update({"file_ids": file_ids})
28932901
_parse_web_class_objects(kwargs)
28942902
kwargs = _remove_none_values(kwargs)
2895-
_warn_if_text_or_attachment_fallback_is_missing("chat.update", kwargs)
2903+
_warn_if_message_text_content_is_missing("chat.update", kwargs)
28962904
# NOTE: intentionally using json over params for API methods using blocks/attachments
28972905
return await self.api_call("chat.update", json=kwargs)
28982906

slack_sdk/web/client.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
_to_v2_file_upload_item,
2121
_update_call_participants,
2222
_validate_for_legacy_client,
23-
_warn_if_text_or_attachment_fallback_is_missing,
23+
_warn_if_message_text_content_is_missing,
2424
)
2525

2626

@@ -2685,6 +2685,7 @@ def chat_postEphemeral(
26852685
link_names: Optional[bool] = None,
26862686
username: Optional[str] = None,
26872687
parse: Optional[str] = None,
2688+
markdown_text: Optional[str] = None,
26882689
**kwargs,
26892690
) -> SlackResponse:
26902691
"""Sends an ephemeral message to a user in a channel.
@@ -2704,11 +2705,12 @@ def chat_postEphemeral(
27042705
"link_names": link_names,
27052706
"username": username,
27062707
"parse": parse,
2708+
"markdown_text": markdown_text,
27072709
}
27082710
)
27092711
_parse_web_class_objects(kwargs)
27102712
kwargs = _remove_none_values(kwargs)
2711-
_warn_if_text_or_attachment_fallback_is_missing("chat.postEphemeral", kwargs)
2713+
_warn_if_message_text_content_is_missing("chat.postEphemeral", kwargs)
27122714
# NOTE: intentionally using json over params for the API methods using blocks/attachments
27132715
return self.api_call("chat.postEphemeral", json=kwargs)
27142716

@@ -2732,6 +2734,7 @@ def chat_postMessage(
27322734
username: Optional[str] = None,
27332735
parse: Optional[str] = None, # none, full
27342736
metadata: Optional[Union[Dict, Metadata]] = None,
2737+
markdown_text: Optional[str] = None,
27352738
**kwargs,
27362739
) -> SlackResponse:
27372740
"""Sends a message to a channel.
@@ -2756,11 +2759,12 @@ def chat_postMessage(
27562759
"username": username,
27572760
"parse": parse,
27582761
"metadata": metadata,
2762+
"markdown_text": markdown_text,
27592763
}
27602764
)
27612765
_parse_web_class_objects(kwargs)
27622766
kwargs = _remove_none_values(kwargs)
2763-
_warn_if_text_or_attachment_fallback_is_missing("chat.postMessage", kwargs)
2767+
_warn_if_message_text_content_is_missing("chat.postMessage", kwargs)
27642768
# NOTE: intentionally using json over params for the API methods using blocks/attachments
27652769
return self.api_call("chat.postMessage", json=kwargs)
27662770

@@ -2769,7 +2773,7 @@ def chat_scheduleMessage(
27692773
*,
27702774
channel: str,
27712775
post_at: Union[str, int],
2772-
text: str,
2776+
text: Optional[str] = None,
27732777
as_user: Optional[bool] = None,
27742778
attachments: Optional[Union[str, Sequence[Union[Dict, Attachment]]]] = None,
27752779
blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None,
@@ -2780,6 +2784,7 @@ def chat_scheduleMessage(
27802784
unfurl_media: Optional[bool] = None,
27812785
link_names: Optional[bool] = None,
27822786
metadata: Optional[Union[Dict, Metadata]] = None,
2787+
markdown_text: Optional[str] = None,
27832788
**kwargs,
27842789
) -> SlackResponse:
27852790
"""Schedules a message.
@@ -2800,11 +2805,12 @@ def chat_scheduleMessage(
28002805
"unfurl_media": unfurl_media,
28012806
"link_names": link_names,
28022807
"metadata": metadata,
2808+
"markdown_text": markdown_text,
28032809
}
28042810
)
28052811
_parse_web_class_objects(kwargs)
28062812
kwargs = _remove_none_values(kwargs)
2807-
_warn_if_text_or_attachment_fallback_is_missing("chat.scheduleMessage", kwargs)
2813+
_warn_if_message_text_content_is_missing("chat.scheduleMessage", kwargs)
28082814
# NOTE: intentionally using json over params for the API methods using blocks/attachments
28092815
return self.api_call("chat.scheduleMessage", json=kwargs)
28102816

@@ -2857,6 +2863,7 @@ def chat_update(
28572863
parse: Optional[str] = None, # none, full
28582864
reply_broadcast: Optional[bool] = None,
28592865
metadata: Optional[Union[Dict, Metadata]] = None,
2866+
markdown_text: Optional[str] = None,
28602867
**kwargs,
28612868
) -> SlackResponse:
28622869
"""Updates a message in a channel.
@@ -2874,6 +2881,7 @@ def chat_update(
28742881
"parse": parse,
28752882
"reply_broadcast": reply_broadcast,
28762883
"metadata": metadata,
2884+
"markdown_text": markdown_text,
28772885
}
28782886
)
28792887
if isinstance(file_ids, (list, tuple)):
@@ -2882,7 +2890,7 @@ def chat_update(
28822890
kwargs.update({"file_ids": file_ids})
28832891
_parse_web_class_objects(kwargs)
28842892
kwargs = _remove_none_values(kwargs)
2885-
_warn_if_text_or_attachment_fallback_is_missing("chat.update", kwargs)
2893+
_warn_if_message_text_content_is_missing("chat.update", kwargs)
28862894
# NOTE: intentionally using json over params for API methods using blocks/attachments
28872895
return self.api_call("chat.update", json=kwargs)
28882896

slack_sdk/web/internal_utils.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,17 @@ def _to_0_or_1_if_bool(v: Any) -> Union[Any, str]:
247247
return v
248248

249249

250-
def _warn_if_text_or_attachment_fallback_is_missing(endpoint: str, kwargs: Dict[str, Any]) -> None:
250+
def _warn_if_message_text_content_is_missing(endpoint: str, kwargs: Dict[str, Any]) -> None:
251251
text = kwargs.get("text")
252252
if text and len(text.strip()) > 0:
253253
# If a top-level text arg is provided, we are good. This is the recommended accessibility field to always provide.
254254
return
255255

256+
markdown_text = kwargs.get("markdown_text")
257+
if markdown_text and len(markdown_text.strip()) > 0:
258+
# If a top-level markdown_text arg is provided, we are good. It should not be used in conjunction with text.
259+
return
260+
256261
# for unit tests etc.
257262
skip_deprecation = os.environ.get("SKIP_SLACK_SDK_WARNING")
258263
if skip_deprecation:

slack_sdk/web/legacy_client.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
_to_v2_file_upload_item,
3333
_update_call_participants,
3434
_validate_for_legacy_client,
35-
_warn_if_text_or_attachment_fallback_is_missing,
35+
_warn_if_message_text_content_is_missing,
3636
)
3737

3838

@@ -2697,6 +2697,7 @@ def chat_postEphemeral(
26972697
link_names: Optional[bool] = None,
26982698
username: Optional[str] = None,
26992699
parse: Optional[str] = None,
2700+
markdown_text: Optional[str] = None,
27002701
**kwargs,
27012702
) -> Union[Future, SlackResponse]:
27022703
"""Sends an ephemeral message to a user in a channel.
@@ -2716,11 +2717,12 @@ def chat_postEphemeral(
27162717
"link_names": link_names,
27172718
"username": username,
27182719
"parse": parse,
2720+
"markdown_text": markdown_text,
27192721
}
27202722
)
27212723
_parse_web_class_objects(kwargs)
27222724
kwargs = _remove_none_values(kwargs)
2723-
_warn_if_text_or_attachment_fallback_is_missing("chat.postEphemeral", kwargs)
2725+
_warn_if_message_text_content_is_missing("chat.postEphemeral", kwargs)
27242726
# NOTE: intentionally using json over params for the API methods using blocks/attachments
27252727
return self.api_call("chat.postEphemeral", json=kwargs)
27262728

@@ -2744,6 +2746,7 @@ def chat_postMessage(
27442746
username: Optional[str] = None,
27452747
parse: Optional[str] = None, # none, full
27462748
metadata: Optional[Union[Dict, Metadata]] = None,
2749+
markdown_text: Optional[str] = None,
27472750
**kwargs,
27482751
) -> Union[Future, SlackResponse]:
27492752
"""Sends a message to a channel.
@@ -2768,11 +2771,12 @@ def chat_postMessage(
27682771
"username": username,
27692772
"parse": parse,
27702773
"metadata": metadata,
2774+
"markdown_text": markdown_text,
27712775
}
27722776
)
27732777
_parse_web_class_objects(kwargs)
27742778
kwargs = _remove_none_values(kwargs)
2775-
_warn_if_text_or_attachment_fallback_is_missing("chat.postMessage", kwargs)
2779+
_warn_if_message_text_content_is_missing("chat.postMessage", kwargs)
27762780
# NOTE: intentionally using json over params for the API methods using blocks/attachments
27772781
return self.api_call("chat.postMessage", json=kwargs)
27782782

@@ -2781,7 +2785,7 @@ def chat_scheduleMessage(
27812785
*,
27822786
channel: str,
27832787
post_at: Union[str, int],
2784-
text: str,
2788+
text: Optional[str] = None,
27852789
as_user: Optional[bool] = None,
27862790
attachments: Optional[Union[str, Sequence[Union[Dict, Attachment]]]] = None,
27872791
blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None,
@@ -2792,6 +2796,7 @@ def chat_scheduleMessage(
27922796
unfurl_media: Optional[bool] = None,
27932797
link_names: Optional[bool] = None,
27942798
metadata: Optional[Union[Dict, Metadata]] = None,
2799+
markdown_text: Optional[str] = None,
27952800
**kwargs,
27962801
) -> Union[Future, SlackResponse]:
27972802
"""Schedules a message.
@@ -2812,11 +2817,12 @@ def chat_scheduleMessage(
28122817
"unfurl_media": unfurl_media,
28132818
"link_names": link_names,
28142819
"metadata": metadata,
2820+
"markdown_text": markdown_text,
28152821
}
28162822
)
28172823
_parse_web_class_objects(kwargs)
28182824
kwargs = _remove_none_values(kwargs)
2819-
_warn_if_text_or_attachment_fallback_is_missing("chat.scheduleMessage", kwargs)
2825+
_warn_if_message_text_content_is_missing("chat.scheduleMessage", kwargs)
28202826
# NOTE: intentionally using json over params for the API methods using blocks/attachments
28212827
return self.api_call("chat.scheduleMessage", json=kwargs)
28222828

@@ -2869,6 +2875,7 @@ def chat_update(
28692875
parse: Optional[str] = None, # none, full
28702876
reply_broadcast: Optional[bool] = None,
28712877
metadata: Optional[Union[Dict, Metadata]] = None,
2878+
markdown_text: Optional[str] = None,
28722879
**kwargs,
28732880
) -> Union[Future, SlackResponse]:
28742881
"""Updates a message in a channel.
@@ -2886,6 +2893,7 @@ def chat_update(
28862893
"parse": parse,
28872894
"reply_broadcast": reply_broadcast,
28882895
"metadata": metadata,
2896+
"markdown_text": markdown_text,
28892897
}
28902898
)
28912899
if isinstance(file_ids, (list, tuple)):
@@ -2894,7 +2902,7 @@ def chat_update(
28942902
kwargs.update({"file_ids": file_ids})
28952903
_parse_web_class_objects(kwargs)
28962904
kwargs = _remove_none_values(kwargs)
2897-
_warn_if_text_or_attachment_fallback_is_missing("chat.update", kwargs)
2905+
_warn_if_message_text_content_is_missing("chat.update", kwargs)
28982906
# NOTE: intentionally using json over params for API methods using blocks/attachments
28992907
return self.api_call("chat.update", json=kwargs)
29002908

tests/slack_sdk/web/test_web_client_issue_891.py renamed to tests/slack_sdk/web/test_web_client_msg_text_content_warnings.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import unittest
2+
import warnings
23

34
from slack_sdk import WebClient
45
from tests.web.mock_web_api_handler import MockHandler
56
from tests.mock_web_api_server import setup_mock_web_api_server, cleanup_mock_web_api_server
67

78

8-
class TestWebClient_Issue_891(unittest.TestCase):
9+
class TestWebClientMessageTextContentWarnings(unittest.TestCase):
910
def setUp(self):
1011
setup_mock_web_api_server(self, MockHandler)
1112

@@ -65,3 +66,39 @@ def test_missing_fallback_warning_chat_update(self):
6566
with self.assertWarnsRegex(UserWarning, "`fallback` argument is missing"):
6667
resp = client.chat_update(channel="C111", ts="111.222", blocks=[], attachments=[{"text": "hi"}])
6768
self.assertIsNone(resp["error"])
69+
70+
def test_no_warning_when_markdown_text_is_provided_chat_postMessage(self):
71+
client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test")
72+
with warnings.catch_warnings(record=True) as warning_list:
73+
warnings.simplefilter("always")
74+
resp = client.chat_postMessage(channel="C111", markdown_text="# hello")
75+
76+
self.assertEqual(warning_list, [])
77+
self.assertIsNone(resp["error"])
78+
79+
def test_no_warning_when_markdown_text_is_provided_chat_postEphemeral(self):
80+
client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test")
81+
with warnings.catch_warnings(record=True) as warning_list:
82+
warnings.simplefilter("always")
83+
resp = client.chat_postEphemeral(channel="C111", user="U111", markdown_text="# hello")
84+
85+
self.assertEqual(warning_list, [])
86+
self.assertIsNone(resp["error"])
87+
88+
def test_no_warning_when_markdown_text_is_provided_chat_scheduleMessage(self):
89+
client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test")
90+
with warnings.catch_warnings(record=True) as warning_list:
91+
warnings.simplefilter("always")
92+
resp = client.chat_scheduleMessage(channel="C111", post_at="299876400", markdown_text="# hello")
93+
94+
self.assertEqual(warning_list, [])
95+
self.assertIsNone(resp["error"])
96+
97+
def test_no_warning_when_markdown_text_is_provided_chat_update(self):
98+
client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test")
99+
with warnings.catch_warnings(record=True) as warning_list:
100+
warnings.simplefilter("always")
101+
resp = client.chat_update(channel="C111", ts="111.222", markdown_text="# hello")
102+
103+
self.assertEqual(warning_list, [])
104+
self.assertIsNone(resp["error"])

0 commit comments

Comments
 (0)