From 793b1cd96b984e0272f5cb042873c7880d6784f4 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Thu, 31 Jul 2025 13:27:29 -0400 Subject: [PATCH 1/5] feat: support markdown_text parameter --- slack_sdk/web/async_client.py | 20 +++++++--- slack_sdk/web/client.py | 20 +++++++--- slack_sdk/web/internal_utils.py | 6 ++- slack_sdk/web/legacy_client.py | 20 +++++++--- tests/web/test_web_client_issue_891.py | 54 ++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 20 deletions(-) diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index 9334abfd2..271f68f22 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -22,7 +22,7 @@ from .internal_utils import ( _parse_web_class_objects, _update_call_participants, - _warn_if_text_or_attachment_fallback_is_missing, + _warn_if_message_text_content_is_missing, _remove_none_values, _to_v2_file_upload_item, _validate_for_legacy_client, @@ -2694,6 +2694,7 @@ async def chat_postEphemeral( link_names: Optional[bool] = None, username: Optional[str] = None, parse: Optional[str] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> AsyncSlackResponse: """Sends an ephemeral message to a user in a channel. @@ -2713,11 +2714,12 @@ async def chat_postEphemeral( "link_names": link_names, "username": username, "parse": parse, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.postEphemeral", kwargs) + _warn_if_message_text_content_is_missing("chat.postEphemeral", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return await self.api_call("chat.postEphemeral", json=kwargs) @@ -2741,6 +2743,7 @@ async def chat_postMessage( username: Optional[str] = None, parse: Optional[str] = None, # none, full metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> AsyncSlackResponse: """Sends a message to a channel. @@ -2765,11 +2768,12 @@ async def chat_postMessage( "username": username, "parse": parse, "metadata": metadata, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.postMessage", kwargs) + _warn_if_message_text_content_is_missing("chat.postMessage", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return await self.api_call("chat.postMessage", json=kwargs) @@ -2778,7 +2782,7 @@ async def chat_scheduleMessage( *, channel: str, post_at: Union[str, int], - text: str, + text: Optional[str] = None, as_user: Optional[bool] = None, attachments: Optional[Union[str, Sequence[Union[Dict, Attachment]]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, @@ -2789,6 +2793,7 @@ async def chat_scheduleMessage( unfurl_media: Optional[bool] = None, link_names: Optional[bool] = None, metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> AsyncSlackResponse: """Schedules a message. @@ -2809,11 +2814,12 @@ async def chat_scheduleMessage( "unfurl_media": unfurl_media, "link_names": link_names, "metadata": metadata, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.scheduleMessage", kwargs) + _warn_if_message_text_content_is_missing("chat.scheduleMessage", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return await self.api_call("chat.scheduleMessage", json=kwargs) @@ -2866,6 +2872,7 @@ async def chat_update( parse: Optional[str] = None, # none, full reply_broadcast: Optional[bool] = None, metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> AsyncSlackResponse: """Updates a message in a channel. @@ -2883,6 +2890,7 @@ async def chat_update( "parse": parse, "reply_broadcast": reply_broadcast, "metadata": metadata, + "markdown_text": markdown_text, } ) if isinstance(file_ids, (list, tuple)): @@ -2891,7 +2899,7 @@ async def chat_update( kwargs.update({"file_ids": file_ids}) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.update", kwargs) + _warn_if_message_text_content_is_missing("chat.update", kwargs) # NOTE: intentionally using json over params for API methods using blocks/attachments return await self.api_call("chat.update", json=kwargs) diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index 80fbec86b..f15307187 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -12,7 +12,7 @@ from .internal_utils import ( _parse_web_class_objects, _update_call_participants, - _warn_if_text_or_attachment_fallback_is_missing, + _warn_if_message_text_content_is_missing, _remove_none_values, _to_v2_file_upload_item, _validate_for_legacy_client, @@ -2684,6 +2684,7 @@ def chat_postEphemeral( link_names: Optional[bool] = None, username: Optional[str] = None, parse: Optional[str] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> SlackResponse: """Sends an ephemeral message to a user in a channel. @@ -2703,11 +2704,12 @@ def chat_postEphemeral( "link_names": link_names, "username": username, "parse": parse, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.postEphemeral", kwargs) + _warn_if_message_text_content_is_missing("chat.postEphemeral", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return self.api_call("chat.postEphemeral", json=kwargs) @@ -2731,6 +2733,7 @@ def chat_postMessage( username: Optional[str] = None, parse: Optional[str] = None, # none, full metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> SlackResponse: """Sends a message to a channel. @@ -2755,11 +2758,12 @@ def chat_postMessage( "username": username, "parse": parse, "metadata": metadata, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.postMessage", kwargs) + _warn_if_message_text_content_is_missing("chat.postMessage", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return self.api_call("chat.postMessage", json=kwargs) @@ -2768,7 +2772,7 @@ def chat_scheduleMessage( *, channel: str, post_at: Union[str, int], - text: str, + text: Optional[str] = None, as_user: Optional[bool] = None, attachments: Optional[Union[str, Sequence[Union[Dict, Attachment]]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, @@ -2779,6 +2783,7 @@ def chat_scheduleMessage( unfurl_media: Optional[bool] = None, link_names: Optional[bool] = None, metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> SlackResponse: """Schedules a message. @@ -2799,11 +2804,12 @@ def chat_scheduleMessage( "unfurl_media": unfurl_media, "link_names": link_names, "metadata": metadata, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.scheduleMessage", kwargs) + _warn_if_message_text_content_is_missing("chat.scheduleMessage", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return self.api_call("chat.scheduleMessage", json=kwargs) @@ -2856,6 +2862,7 @@ def chat_update( parse: Optional[str] = None, # none, full reply_broadcast: Optional[bool] = None, metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> SlackResponse: """Updates a message in a channel. @@ -2873,6 +2880,7 @@ def chat_update( "parse": parse, "reply_broadcast": reply_broadcast, "metadata": metadata, + "markdown_text": markdown_text, } ) if isinstance(file_ids, (list, tuple)): @@ -2881,7 +2889,7 @@ def chat_update( kwargs.update({"file_ids": file_ids}) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.update", kwargs) + _warn_if_message_text_content_is_missing("chat.update", kwargs) # NOTE: intentionally using json over params for API methods using blocks/attachments return self.api_call("chat.update", json=kwargs) diff --git a/slack_sdk/web/internal_utils.py b/slack_sdk/web/internal_utils.py index ca76e3555..6ae2c385f 100644 --- a/slack_sdk/web/internal_utils.py +++ b/slack_sdk/web/internal_utils.py @@ -247,10 +247,12 @@ def _to_0_or_1_if_bool(v: Any) -> Union[Any, str]: return v -def _warn_if_text_or_attachment_fallback_is_missing(endpoint: str, kwargs: Dict[str, Any]) -> None: +def _warn_if_message_text_content_is_missing(endpoint: str, kwargs: Dict[str, Any]) -> None: text = kwargs.get("text") - if text and len(text.strip()) > 0: + markdown_text = kwargs.get("markdown_text") + if (text and len(text.strip()) > 0) or (markdown_text and len(markdown_text.strip()) > 0): # If a top-level text arg is provided, we are good. This is the recommended accessibility field to always provide. + # If a top-level markdown_text arg is provided, we are good. It should not be used in conjunction with blocks or text. return # for unit tests etc. diff --git a/slack_sdk/web/legacy_client.py b/slack_sdk/web/legacy_client.py index 5496226bc..757cdcb66 100644 --- a/slack_sdk/web/legacy_client.py +++ b/slack_sdk/web/legacy_client.py @@ -24,7 +24,7 @@ from .internal_utils import ( _parse_web_class_objects, _update_call_participants, - _warn_if_text_or_attachment_fallback_is_missing, + _warn_if_message_text_content_is_missing, _remove_none_values, _to_v2_file_upload_item, _validate_for_legacy_client, @@ -2696,6 +2696,7 @@ def chat_postEphemeral( link_names: Optional[bool] = None, username: Optional[str] = None, parse: Optional[str] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Sends an ephemeral message to a user in a channel. @@ -2715,11 +2716,12 @@ def chat_postEphemeral( "link_names": link_names, "username": username, "parse": parse, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.postEphemeral", kwargs) + _warn_if_message_text_content_is_missing("chat.postEphemeral", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return self.api_call("chat.postEphemeral", json=kwargs) @@ -2743,6 +2745,7 @@ def chat_postMessage( username: Optional[str] = None, parse: Optional[str] = None, # none, full metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Sends a message to a channel. @@ -2767,11 +2770,12 @@ def chat_postMessage( "username": username, "parse": parse, "metadata": metadata, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.postMessage", kwargs) + _warn_if_message_text_content_is_missing("chat.postMessage", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return self.api_call("chat.postMessage", json=kwargs) @@ -2780,7 +2784,7 @@ def chat_scheduleMessage( *, channel: str, post_at: Union[str, int], - text: str, + text: Optional[str] = None, as_user: Optional[bool] = None, attachments: Optional[Union[str, Sequence[Union[Dict, Attachment]]]] = None, blocks: Optional[Union[str, Sequence[Union[Dict, Block]]]] = None, @@ -2791,6 +2795,7 @@ def chat_scheduleMessage( unfurl_media: Optional[bool] = None, link_names: Optional[bool] = None, metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Schedules a message. @@ -2811,11 +2816,12 @@ def chat_scheduleMessage( "unfurl_media": unfurl_media, "link_names": link_names, "metadata": metadata, + "markdown_text": markdown_text, } ) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.scheduleMessage", kwargs) + _warn_if_message_text_content_is_missing("chat.scheduleMessage", kwargs) # NOTE: intentionally using json over params for the API methods using blocks/attachments return self.api_call("chat.scheduleMessage", json=kwargs) @@ -2868,6 +2874,7 @@ def chat_update( parse: Optional[str] = None, # none, full reply_broadcast: Optional[bool] = None, metadata: Optional[Union[Dict, Metadata]] = None, + markdown_text: Optional[str] = None, **kwargs, ) -> Union[Future, SlackResponse]: """Updates a message in a channel. @@ -2885,6 +2892,7 @@ def chat_update( "parse": parse, "reply_broadcast": reply_broadcast, "metadata": metadata, + "markdown_text": markdown_text, } ) if isinstance(file_ids, (list, tuple)): @@ -2893,7 +2901,7 @@ def chat_update( kwargs.update({"file_ids": file_ids}) _parse_web_class_objects(kwargs) kwargs = _remove_none_values(kwargs) - _warn_if_text_or_attachment_fallback_is_missing("chat.update", kwargs) + _warn_if_message_text_content_is_missing("chat.update", kwargs) # NOTE: intentionally using json over params for API methods using blocks/attachments return self.api_call("chat.update", json=kwargs) diff --git a/tests/web/test_web_client_issue_891.py b/tests/web/test_web_client_issue_891.py index f2d341f49..790e37fd1 100644 --- a/tests/web/test_web_client_issue_891.py +++ b/tests/web/test_web_client_issue_891.py @@ -1,4 +1,5 @@ import unittest +import warnings from slack import WebClient from tests.web.mock_web_api_handler import MockHandler @@ -11,6 +12,7 @@ def setUp(self): def tearDown(self): cleanup_mock_web_api_server(self) + warnings.resetwarnings() def test_missing_text_warning_chat_postMessage(self): client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") @@ -65,3 +67,55 @@ def test_missing_fallback_warning_chat_update(self): with self.assertWarnsRegex(UserWarning, "`fallback` argument is missing"): resp = client.chat_update(channel="C111", ts="111.222", blocks=[], attachments=[{"text": "hi"}]) self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_postMessage(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_postMessage( + channel="C111", + markdown_text="# hello" + ) + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_postEphemeral(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_postEphemeral( + channel="C111", + user="U111", + markdown_text="# hello" + ) + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_scheduleMessage(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_scheduleMessage( + channel="C111", + post_at="299876400", + markdown_text="# hello" + ) + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_update(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_update( + channel="C111", + ts="111.222", + markdown_text="# hello" + ) + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + From 8341b6f44b8c84e8897d8e9260af0f0e05608b94 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Thu, 31 Jul 2025 13:30:09 -0400 Subject: [PATCH 2/5] fix format issues --- slack_sdk/web/internal_utils.py | 2 +- tests/web/test_web_client_issue_891.py | 48 +++++++++----------------- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/slack_sdk/web/internal_utils.py b/slack_sdk/web/internal_utils.py index 6ae2c385f..4e4689b5d 100644 --- a/slack_sdk/web/internal_utils.py +++ b/slack_sdk/web/internal_utils.py @@ -252,7 +252,7 @@ def _warn_if_message_text_content_is_missing(endpoint: str, kwargs: Dict[str, An markdown_text = kwargs.get("markdown_text") if (text and len(text.strip()) > 0) or (markdown_text and len(markdown_text.strip()) > 0): # If a top-level text arg is provided, we are good. This is the recommended accessibility field to always provide. - # If a top-level markdown_text arg is provided, we are good. It should not be used in conjunction with blocks or text. + # If a top-level markdown_text arg is provided, we are good. It should not be used in conjunction with text. return # for unit tests etc. diff --git a/tests/web/test_web_client_issue_891.py b/tests/web/test_web_client_issue_891.py index 790e37fd1..9ea970deb 100644 --- a/tests/web/test_web_client_issue_891.py +++ b/tests/web/test_web_client_issue_891.py @@ -67,55 +67,39 @@ def test_missing_fallback_warning_chat_update(self): with self.assertWarnsRegex(UserWarning, "`fallback` argument is missing"): resp = client.chat_update(channel="C111", ts="111.222", blocks=[], attachments=[{"text": "hi"}]) self.assertIsNone(resp["error"]) - + def test_no_warning_when_markdown_text_is_provided_chat_postMessage(self): client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: - warnings.simplefilter("always") - resp = client.chat_postMessage( - channel="C111", - markdown_text="# hello" - ) - + warnings.simplefilter("always") + resp = client.chat_postMessage(channel="C111", markdown_text="# hello") + self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) - + def test_no_warning_when_markdown_text_is_provided_chat_postEphemeral(self): client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: - warnings.simplefilter("always") - resp = client.chat_postEphemeral( - channel="C111", - user="U111", - markdown_text="# hello" - ) - + warnings.simplefilter("always") + resp = client.chat_postEphemeral(channel="C111", user="U111", markdown_text="# hello") + self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) - + def test_no_warning_when_markdown_text_is_provided_chat_scheduleMessage(self): client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: - warnings.simplefilter("always") - resp = client.chat_scheduleMessage( - channel="C111", - post_at="299876400", - markdown_text="# hello" - ) - + warnings.simplefilter("always") + resp = client.chat_scheduleMessage(channel="C111", post_at="299876400", markdown_text="# hello") + self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) - + def test_no_warning_when_markdown_text_is_provided_chat_update(self): client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: - warnings.simplefilter("always") - resp = client.chat_update( - channel="C111", - ts="111.222", - markdown_text="# hello" - ) - + warnings.simplefilter("always") + resp = client.chat_update(channel="C111", ts="111.222", markdown_text="# hello") + self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) - From 462ef6f87c0c9dd5ec6e1000b9b21d228bb15ea8 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Fri, 1 Aug 2025 16:25:26 -0400 Subject: [PATCH 3/5] rename test file and improve tests coverage --- ...t_web_client_msg_text_content_warnings.py} | 39 ++++++++++++++++- ...t_web_client_msg_text_content_warnings.py} | 43 ++++++++++++++++++- ...t_web_client_msg_text_content_warnings.py} | 2 +- 3 files changed, 81 insertions(+), 3 deletions(-) rename tests/slack_sdk/web/{test_web_client_issue_891.py => test_web_client_msg_text_content_warnings.py} (63%) rename tests/slack_sdk_async/web/{test_web_client_issue_891.py => test_web_client_msg_text_content_warnings.py} (65%) rename tests/web/{test_web_client_issue_891.py => test_web_client_msg_text_content_warnings.py} (98%) diff --git a/tests/slack_sdk/web/test_web_client_issue_891.py b/tests/slack_sdk/web/test_web_client_msg_text_content_warnings.py similarity index 63% rename from tests/slack_sdk/web/test_web_client_issue_891.py rename to tests/slack_sdk/web/test_web_client_msg_text_content_warnings.py index ed47b0e4d..e94adba07 100644 --- a/tests/slack_sdk/web/test_web_client_issue_891.py +++ b/tests/slack_sdk/web/test_web_client_msg_text_content_warnings.py @@ -1,11 +1,12 @@ import unittest +import warnings from slack_sdk import WebClient from tests.web.mock_web_api_handler import MockHandler from tests.mock_web_api_server import setup_mock_web_api_server, cleanup_mock_web_api_server -class TestWebClient_Issue_891(unittest.TestCase): +class TestWebClientMessageTextContentWarnings(unittest.TestCase): def setUp(self): setup_mock_web_api_server(self, MockHandler) @@ -65,3 +66,39 @@ def test_missing_fallback_warning_chat_update(self): with self.assertWarnsRegex(UserWarning, "`fallback` argument is missing"): resp = client.chat_update(channel="C111", ts="111.222", blocks=[], attachments=[{"text": "hi"}]) self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_postMessage(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_postMessage(channel="C111", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_postEphemeral(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_postEphemeral(channel="C111", user="U111", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_scheduleMessage(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_scheduleMessage(channel="C111", post_at="299876400", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + def test_no_warning_when_markdown_text_is_provided_chat_update(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_update(channel="C111", ts="111.222", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) diff --git a/tests/slack_sdk_async/web/test_web_client_issue_891.py b/tests/slack_sdk_async/web/test_web_client_msg_text_content_warnings.py similarity index 65% rename from tests/slack_sdk_async/web/test_web_client_issue_891.py rename to tests/slack_sdk_async/web/test_web_client_msg_text_content_warnings.py index 1e81f775d..d4a3ea646 100644 --- a/tests/slack_sdk_async/web/test_web_client_issue_891.py +++ b/tests/slack_sdk_async/web/test_web_client_msg_text_content_warnings.py @@ -1,4 +1,5 @@ import unittest +import warnings from slack_sdk.web.async_client import AsyncWebClient from tests.helpers import async_test @@ -6,7 +7,7 @@ from tests.mock_web_api_server import setup_mock_web_api_server_async, cleanup_mock_web_api_server_async -class TestWebClient_Issue_829(unittest.TestCase): +class TestWebClientMessageTextContentWarnings(unittest.TestCase): def setUp(self): setup_mock_web_api_server_async(self, MockHandler) @@ -74,3 +75,43 @@ async def test_missing_fallback_warning_chat_update(self): with self.assertWarnsRegex(UserWarning, "`text` argument is missing"): resp = await client.chat_update(channel="C111", ts="111.222", blocks=[], attachments=[{"text": "hi"}]) self.assertIsNone(resp["error"]) + + @async_test + def test_no_warning_when_markdown_text_is_provided_chat_postMessage(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_postMessage(channel="C111", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + @async_test + def test_no_warning_when_markdown_text_is_provided_chat_postEphemeral(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_postEphemeral(channel="C111", user="U111", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + @async_test + def test_no_warning_when_markdown_text_is_provided_chat_scheduleMessage(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_scheduleMessage(channel="C111", post_at="299876400", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) + + @async_test + def test_no_warning_when_markdown_text_is_provided_chat_update(self): + client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter("always") + resp = client.chat_update(channel="C111", ts="111.222", markdown_text="# hello") + + self.assertEqual(warning_list, []) + self.assertIsNone(resp["error"]) diff --git a/tests/web/test_web_client_issue_891.py b/tests/web/test_web_client_msg_text_content_warnings.py similarity index 98% rename from tests/web/test_web_client_issue_891.py rename to tests/web/test_web_client_msg_text_content_warnings.py index 9ea970deb..11ca100ac 100644 --- a/tests/web/test_web_client_issue_891.py +++ b/tests/web/test_web_client_msg_text_content_warnings.py @@ -6,7 +6,7 @@ from tests.mock_web_api_server import setup_mock_web_api_server, cleanup_mock_web_api_server -class TestWebClient_Issue_891(unittest.TestCase): +class TestWebClientMessageTextContentWarnings(unittest.TestCase): def setUp(self): setup_mock_web_api_server(self, MockHandler) From f00fa90da33af55d556c4e7059e757df7b9f86d2 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Fri, 1 Aug 2025 16:34:47 -0400 Subject: [PATCH 4/5] clean things up based on feedback --- slack_sdk/web/internal_utils.py | 7 +++-- ...st_web_client_msg_text_content_warnings.py | 26 +++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/slack_sdk/web/internal_utils.py b/slack_sdk/web/internal_utils.py index 4e4689b5d..41a870c5c 100644 --- a/slack_sdk/web/internal_utils.py +++ b/slack_sdk/web/internal_utils.py @@ -249,9 +249,12 @@ def _to_0_or_1_if_bool(v: Any) -> Union[Any, str]: def _warn_if_message_text_content_is_missing(endpoint: str, kwargs: Dict[str, Any]) -> None: text = kwargs.get("text") - markdown_text = kwargs.get("markdown_text") - if (text and len(text.strip()) > 0) or (markdown_text and len(markdown_text.strip()) > 0): + if text and len(text.strip()) > 0: # If a top-level text arg is provided, we are good. This is the recommended accessibility field to always provide. + return + + markdown_text = kwargs.get("markdown_text") + if markdown_text and len(markdown_text.strip()) > 0: # If a top-level markdown_text arg is provided, we are good. It should not be used in conjunction with text. return diff --git a/tests/slack_sdk_async/web/test_web_client_msg_text_content_warnings.py b/tests/slack_sdk_async/web/test_web_client_msg_text_content_warnings.py index d4a3ea646..085b103d9 100644 --- a/tests/slack_sdk_async/web/test_web_client_msg_text_content_warnings.py +++ b/tests/slack_sdk_async/web/test_web_client_msg_text_content_warnings.py @@ -75,43 +75,43 @@ async def test_missing_fallback_warning_chat_update(self): with self.assertWarnsRegex(UserWarning, "`text` argument is missing"): resp = await client.chat_update(channel="C111", ts="111.222", blocks=[], attachments=[{"text": "hi"}]) self.assertIsNone(resp["error"]) - + @async_test - def test_no_warning_when_markdown_text_is_provided_chat_postMessage(self): - client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + async def test_no_warning_when_markdown_text_is_provided_chat_postMessage(self): + client = AsyncWebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") - resp = client.chat_postMessage(channel="C111", markdown_text="# hello") + resp = await client.chat_postMessage(channel="C111", markdown_text="# hello") self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) @async_test - def test_no_warning_when_markdown_text_is_provided_chat_postEphemeral(self): - client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + async def test_no_warning_when_markdown_text_is_provided_chat_postEphemeral(self): + client = AsyncWebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") - resp = client.chat_postEphemeral(channel="C111", user="U111", markdown_text="# hello") + resp = await client.chat_postEphemeral(channel="C111", user="U111", markdown_text="# hello") self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) @async_test - def test_no_warning_when_markdown_text_is_provided_chat_scheduleMessage(self): - client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + async def test_no_warning_when_markdown_text_is_provided_chat_scheduleMessage(self): + client = AsyncWebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") - resp = client.chat_scheduleMessage(channel="C111", post_at="299876400", markdown_text="# hello") + resp = await client.chat_scheduleMessage(channel="C111", post_at="299876400", markdown_text="# hello") self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) @async_test - def test_no_warning_when_markdown_text_is_provided_chat_update(self): - client = WebClient(base_url="http://localhost:8888", token="xoxb-api_test") + async def test_no_warning_when_markdown_text_is_provided_chat_update(self): + client = AsyncWebClient(base_url="http://localhost:8888", token="xoxb-api_test") with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") - resp = client.chat_update(channel="C111", ts="111.222", markdown_text="# hello") + resp = await client.chat_update(channel="C111", ts="111.222", markdown_text="# hello") self.assertEqual(warning_list, []) self.assertIsNone(resp["error"]) From 4fb424a730a42e8039fe1f5e9245f40badebd238 Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Fri, 1 Aug 2025 17:02:33 -0400 Subject: [PATCH 5/5] fix imports --- slack_sdk/web/async_client.py | 4 +--- slack_sdk/web/client.py | 4 +--- slack_sdk/web/legacy_client.py | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/slack_sdk/web/async_client.py b/slack_sdk/web/async_client.py index ae493e292..44aa87830 100644 --- a/slack_sdk/web/async_client.py +++ b/slack_sdk/web/async_client.py @@ -25,14 +25,12 @@ from .async_base_client import AsyncBaseClient, AsyncSlackResponse from .internal_utils import ( _parse_web_class_objects, - _update_call_participants, - _warn_if_message_text_content_is_missing, _print_files_upload_v2_suggestion, _remove_none_values, _to_v2_file_upload_item, _update_call_participants, _validate_for_legacy_client, - _warn_if_text_or_attachment_fallback_is_missing, + _warn_if_message_text_content_is_missing, ) diff --git a/slack_sdk/web/client.py b/slack_sdk/web/client.py index af2462206..b03621364 100644 --- a/slack_sdk/web/client.py +++ b/slack_sdk/web/client.py @@ -15,14 +15,12 @@ from .base_client import BaseClient, SlackResponse from .internal_utils import ( _parse_web_class_objects, - _update_call_participants, - _warn_if_message_text_content_is_missing, _print_files_upload_v2_suggestion, _remove_none_values, _to_v2_file_upload_item, _update_call_participants, _validate_for_legacy_client, - _warn_if_text_or_attachment_fallback_is_missing, + _warn_if_message_text_content_is_missing, ) diff --git a/slack_sdk/web/legacy_client.py b/slack_sdk/web/legacy_client.py index 02b10f42c..6bb8a8154 100644 --- a/slack_sdk/web/legacy_client.py +++ b/slack_sdk/web/legacy_client.py @@ -27,14 +27,12 @@ from .legacy_base_client import LegacyBaseClient, SlackResponse from .internal_utils import ( _parse_web_class_objects, - _update_call_participants, - _warn_if_message_text_content_is_missing, _print_files_upload_v2_suggestion, _remove_none_values, _to_v2_file_upload_item, _update_call_participants, _validate_for_legacy_client, - _warn_if_text_or_attachment_fallback_is_missing, + _warn_if_message_text_content_is_missing, )