Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions slack_sdk/web/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the markdown_text argument in the methods definitions, but we could omit this since developers are able to pass this value through keyword arguments, should we explicitly define this argument?

praise: Adding this I think is a nice improvement for the typeahead hints found in some editors with virtual environments!

thought: It's nice to know that missing arguments aren't blocking new features though 🤖 ✨

**kwargs,
) -> AsyncSlackResponse:
"""Sends an ephemeral message to a user in a channel.
Expand All @@ -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)

Expand All @@ -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.
Expand All @@ -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)

Expand All @@ -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,
Expand All @@ -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.
Expand All @@ -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)

Expand Down Expand Up @@ -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.
Expand All @@ -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)):
Expand All @@ -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)

Expand Down
20 changes: 14 additions & 6 deletions slack_sdk/web/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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)

Expand All @@ -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.
Expand All @@ -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)

Expand All @@ -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,
Expand All @@ -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.
Expand All @@ -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)

Expand Down Expand Up @@ -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.
Expand All @@ -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)):
Expand All @@ -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)

Expand Down
6 changes: 4 additions & 2 deletions slack_sdk/web/internal_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion(non-blocking): Separating these cases as separate if statements and returns might make later additions more clear 👁️‍🗨️

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yess I agree let me see how this looks 💯

# 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 text.
return

# for unit tests etc.
Expand Down
20 changes: 14 additions & 6 deletions slack_sdk/web/legacy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand All @@ -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)

Expand All @@ -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.
Expand All @@ -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)

Expand All @@ -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,
Expand All @@ -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.
Expand All @@ -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)

Expand Down Expand Up @@ -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.
Expand All @@ -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)):
Expand All @@ -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)

Expand Down
38 changes: 38 additions & 0 deletions tests/web/test_web_client_issue_891.py
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question(non-blocking): Do we want to keep the issue_### pattern or can we change this to something like:

tests/web/test_web_client_warnings.py

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point let me rename this 💯

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import unittest
import warnings

from slack import WebClient
from tests.web.mock_web_api_handler import MockHandler
Expand All @@ -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")
Expand Down Expand Up @@ -65,3 +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")

self.assertEqual(warning_list, [])
self.assertIsNone(resp["error"])
Comment on lines +77 to +78
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🪄 ✨


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"])