Skip to content

Conversation

@vegeris
Copy link

@vegeris vegeris commented Nov 6, 2025

Summary

This PR adds the following support for work objects:

  • Defines the schema for work object metadata
  • Updates the inputs for chat.unfurl or chat.postMessage to accept entity metadata
  • Adds the entity.presentDetails API method

Testing

Category

  • slack_sdk.web.WebClient (sync/async) (Web API client)
  • slack_sdk.webhook.WebhookClient (sync/async) (Incoming Webhook, response_url sender)
  • slack_sdk.socket_mode (Socket Mode client)
  • slack_sdk.signature (Request Signature Verifier)
  • slack_sdk.oauth (OAuth Flow Utilities)
  • slack_sdk.models (UI component builders)
  • slack_sdk.scim (SCIM API client)
  • slack_sdk.audit_logs (Audit Logs API client)
  • slack_sdk.rtm_v2 (RTM client)
  • /docs (Documents)
  • /tutorial (PythOnBoardingBot tutorial)
  • tests/integration_tests (Automated tests for this library)

Requirements

  • I've read and understood the Contributing Guidelines and have done my best effort to follow them.
  • I've read and agree to the Code of Conduct.
  • I've run python3 -m venv .venv && source .venv/bin/activate && ./scripts/run_validation.sh after making the changes.

@codecov
Copy link

codecov bot commented Nov 6, 2025

Codecov Report

❌ Patch coverage is 61.60164% with 187 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.29%. Comparing base (47843de) to head (194963a).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
slack_sdk/models/metadata/__init__.py 64.85% 155 Missing ⚠️
slack_sdk/web/async_client.py 16.66% 10 Missing ⚠️
slack_sdk/web/client.py 16.66% 10 Missing ⚠️
slack_sdk/web/legacy_client.py 16.66% 10 Missing ⚠️
slack_sdk/web/internal_utils.py 71.42% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1783      +/-   ##
==========================================
- Coverage   85.15%   84.29%   -0.86%     
==========================================
  Files         115      115              
  Lines       13069    13547     +478     
==========================================
+ Hits        11129    11420     +291     
- Misses       1940     2127     +187     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@vegeris vegeris force-pushed the feat-work-objects branch 2 times, most recently from 0aab530 to 2f3febb Compare November 7, 2025 15:28
Copy link
Contributor

@WilliamBergamin WilliamBergamin left a comment

Choose a reason for hiding this comment

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

Nice thanks for working on this, it look promising 💯

Left a few comments 📝

For EntityPayload it might be a good idea to add unit tests similar to what is found in tests/slack_sdk/models/test_objects.py, let me know what you think about creating a dedicated unit test file in tests/slack_sdk/models similar to what the other "models" have 🤔

Comment on lines +1094 to +1096
# Store entity attributes data with a different internal name to avoid
# shadowing the class-level 'attributes' set used for JSON serialization
self._entity_attributes = attributes
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice 💯 yup this makes sense!

Comment on lines +197 to +200
if isinstance(obj, EventAndEntityMetadata):
return obj.to_dict()
if isinstance(obj, EntityMetadata):
return obj.to_dict()
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice 💯

Comment on lines +1115 to +1119
def get_object_attribute(self, key: str):
if key == "attributes":
return self._entity_attributes
else:
return getattr(self, key, None)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice 💯 🚀

@vegeris vegeris force-pushed the feat-work-objects branch 4 times, most recently from c091881 to 5fc9652 Compare November 10, 2025 15:19
@vegeris vegeris marked this pull request as ready for review November 10, 2025 15:43
@vegeris vegeris marked this pull request as draft November 10, 2025 15:43
@vegeris vegeris marked this pull request as ready for review November 10, 2025 19:30
edit=EntityEditSupport(enabled=True, text=EntityEditTextConfig(min_length=5, max_length=100)),
),
due_date=EntityTypedField(value="2026-06-06", type="slack#/types/date"),
created_by=EntityTypedField(
Copy link
Author

Choose a reason for hiding this comment

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

Debating leaving this as EntityTypedField or adding a 'user' type field for the entity-specific pre-defined fields

Copy link
Contributor

Choose a reason for hiding this comment

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

For now I would suggest keeping it simple and leaving it as EntityTypedField in the future if we see that a dedicated 'user' type field would be useful we can always add it, until then it provides us with more flexibility 🤔

Copy link
Contributor

@WilliamBergamin WilliamBergamin left a comment

Choose a reason for hiding this comment

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

These changes look great 🚀

I left one comment on the test, let me know what you think

Note: you may need to update from main to get the checks to pass

Comment on lines +43 to +45
def get_object_attribute(self, key: str):
return getattr(self, key, None)

Copy link
Contributor

Choose a reason for hiding this comment

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

Nice 💯

edit=EntityEditSupport(enabled=True, text=EntityEditTextConfig(min_length=5, max_length=100)),
),
due_date=EntityTypedField(value="2026-06-06", type="slack#/types/date"),
created_by=EntityTypedField(
Copy link
Contributor

Choose a reason for hiding this comment

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

For now I would suggest keeping it simple and leaving it as EntityTypedField in the future if we see that a dedicated 'user' type field would be useful we can always add it, until then it provides us with more flexibility 🤔

class EntityMetadataTests(unittest.TestCase):
maxDiff = None

def test_creation(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

What do you think about potentially creating more tests that cover more specific cases?

When the tests fail it will make it easier for maintainers to determine what area is the issue originates from

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants