-
Notifications
You must be signed in to change notification settings - Fork 14
refactor: code generated from refactored openapi specs #205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis PR updates public API signatures across multiple SDK modules: Chat module updates Channel.update to accept ChannelInputRequest, extends mark_unread with message_timestamp parameter, and adds mark_delivered method; Feeds module refines get_or_create parameters and significantly expands rest_client.py with new endpoints and telemetry instrumentation; Moderation and Video modules update type parameters and add new endpoint methods. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Areas requiring attention:
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR contains code generated from refactored OpenAPI specifications, updating multiple REST client interfaces and model definitions across the GetStream SDK. The changes primarily involve type renames, new API endpoints, parameter additions, and model restructuring to align with updated API specifications.
Key changes:
- Added new API methods and endpoints (e.g.,
get_call_stats_map, collections CRUD operations,mark_delivered) - Renamed types for clarity (e.g.,
NotificationSettings→NotificationSettingsRequest/Response, action request types now usePayloadsuffix) - Added telemetry decorators to feeds client methods
- Expanded model definitions with new fields and response types
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
getstream/video/rest_client.py |
Added get_call_stats_map method, added pagination params to query_call_session_participant_stats, updated type names for notification settings and SIP challenge |
getstream/video/async_rest_client.py |
Mirror changes to sync client for async version |
getstream/moderation/rest_client.py |
Updated type names for moderation payloads and action requests (added Payload suffix) |
getstream/moderation/async_rest_client.py |
Mirror changes to sync client for async version |
getstream/models/__init__.py |
Extensive model changes: renamed/restructured many dataclasses, added new models for collections, events, notifications; removed deprecated models |
getstream/feeds/rest_client.py |
Added telemetry decorators, new collection endpoints, renamed add_reaction → add_activity_reaction, added new parameters to existing methods |
getstream/feeds/feeds.py |
Updated method signatures to match client changes |
getstream/chat/rest_client.py |
Added mark_delivered method, updated type names, added message_timestamp parameter |
getstream/chat/async_rest_client.py |
Mirror changes to sync client for async version |
getstream/chat/channel.py |
Updated method signatures to match client changes |
getstream/chat/async_channel.py |
Mirror changes to sync client for async version |
The changes appear to be auto-generated code with consistent patterns applied across sync and async versions of the clients. No issues were identified in the generated code structure.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
getstream/chat/async_channel.py(3 hunks)getstream/chat/async_rest_client.py(4 hunks)getstream/chat/channel.py(3 hunks)getstream/chat/rest_client.py(4 hunks)getstream/feeds/feeds.py(2 hunks)getstream/feeds/rest_client.py(51 hunks)getstream/moderation/async_rest_client.py(4 hunks)getstream/moderation/rest_client.py(4 hunks)getstream/video/async_rest_client.py(5 hunks)getstream/video/rest_client.py(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Plugins that work with audio, video, or WebRTC functionality should depend on
getstream[webrtc]instead of justgetstreamto access WebRTC-related dependencies likeaiortc,numpy,torch,torchaudio,soundfile,scipy,deepgram-sdk, andelevenlabs
Files:
getstream/chat/async_channel.pygetstream/chat/async_rest_client.pygetstream/moderation/rest_client.pygetstream/video/async_rest_client.pygetstream/chat/channel.pygetstream/moderation/async_rest_client.pygetstream/video/rest_client.pygetstream/chat/rest_client.pygetstream/feeds/rest_client.pygetstream/feeds/feeds.py
🧬 Code graph analysis (8)
getstream/chat/async_channel.py (1)
getstream/models/__init__.py (1)
ChannelInputRequest(4823-4851)
getstream/chat/async_rest_client.py (5)
getstream/common/telemetry.py (1)
operation_name(429-441)getstream/chat/rest_client.py (1)
mark_delivered(145-157)getstream/models/__init__.py (3)
DeliveredMessagePayload(7418-7420)MarkDeliveredResponse(10927-10928)ChannelInputRequest(4823-4851)getstream/utils/__init__.py (2)
build_query_param(94-126)build_body_dict(151-175)getstream/base.py (2)
post(240-256)post(429-445)
getstream/video/async_rest_client.py (3)
getstream/common/telemetry.py (1)
operation_name(429-441)getstream/models/__init__.py (4)
QueryCallStatsMapResponse(14474-14538)QueryCallSessionParticipantStatsResponse(14424-14457)NotificationSettingsRequest(12890-12908)SIPChallengeRequest(16585-16627)getstream/utils/__init__.py (1)
build_query_param(94-126)
getstream/chat/channel.py (2)
getstream/stream_response.py (1)
data(22-24)getstream/models/__init__.py (1)
ChannelInputRequest(4823-4851)
getstream/moderation/async_rest_client.py (4)
getstream/models/__init__.py (11)
ModerationPayloadRequest(12502-12514)BanActionRequestPayload(1901-1919)BlockActionRequestPayload(2040-2043)DeleteActivityRequestPayload(7131-7137)DeleteCommentRequestPayload(7226-7232)DeleteMessageRequestPayload(7291-7297)DeleteReactionRequestPayload(7322-7328)DeleteUserRequestPayload(7369-7384)MarkReviewedRequestPayload(10956-10963)ShadowBlockActionRequestPayload(17303-17306)UnbanActionRequestPayload(18368-18371)getstream/moderation/rest_client.py (2)
ban(35-58)unban(489-508)getstream/chat/async_rest_client.py (1)
delete_message(969-987)getstream/chat/rest_client.py (1)
delete_message(959-977)
getstream/video/rest_client.py (4)
getstream/common/telemetry.py (1)
operation_name(429-441)getstream/video/async_rest_client.py (1)
get_call_stats_map(875-903)getstream/models/__init__.py (4)
QueryCallStatsMapResponse(14474-14538)QueryCallSessionParticipantStatsResponse(14424-14457)NotificationSettingsRequest(12890-12908)SIPChallengeRequest(16585-16627)getstream/utils/__init__.py (1)
build_query_param(94-126)
getstream/feeds/rest_client.py (5)
getstream/common/telemetry.py (1)
operation_name(429-441)getstream/base.py (6)
post(240-256)post(429-445)delete(276-292)delete(465-481)get(222-238)get(411-427)getstream/utils/__init__.py (2)
build_body_dict(151-175)build_query_param(94-126)getstream/feeds/feeds.py (1)
delete(17-24)getstream/stream.py (2)
feeds(211-212)feeds(316-328)
getstream/feeds/feeds.py (1)
getstream/models/__init__.py (2)
FeedInput(8341-8357)EnrichmentOptions(7693-7744)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Upload results
- GitHub Check: Tests (3.11)
- GitHub Check: Tests (3.12)
- GitHub Check: Tests (3.13)
- GitHub Check: Tests (3.10)
🔇 Additional comments (35)
getstream/video/async_rest_client.py (3)
874-903: LGTM: Newget_call_stats_mapendpoint added.The new method follows the established patterns in the codebase with proper telemetry decoration, path parameter handling, and query parameter construction for optional filters.
1028-1028: Breaking change:notification_settingstype updated.The parameter type changed from
NotificationSettingstoNotificationSettingsRequest. This is a breaking change for callers passing the old type. Ensure migration documentation is provided.
1096-1096: Breaking change:challengeparameter type updated.The parameter type changed from
SIPChallengetoSIPChallengeRequest. Callers using the old type will need to update their code.getstream/moderation/async_rest_client.py (4)
213-213: Breaking change:moderation_payloadtype updated toModerationPayloadRequest.Callers using the previous
ModerationPayloadtype will need to migrate.
249-249: Breaking change:configparameter type updated.Type changed from
FeedsModerationTemplateConfigtoFeedsModerationTemplateConfigPayload.
288-288: Type alignment:sortusesSortParamRequest.This aligns with other methods in the codebase that already use
SortParamRequestfor sort parameters.
460-470: Breaking changes: All action payload types updated to*Payloadvariants.Multiple parameter types changed:
BanActionRequest→BanActionRequestPayloadBlockActionRequest→BlockActionRequestPayloadCustomActionRequest→CustomActionRequestPayloadDeleteActivityRequest→DeleteActivityRequestPayloadDeleteCommentRequest→DeleteCommentRequestPayloadDeleteMessageRequest→DeleteMessageRequestPayloadDeleteReactionRequest→DeleteReactionRequestPayloadDeleteUserRequest→DeleteUserRequestPayloadMarkReviewedRequest→MarkReviewedRequestPayloadShadowBlockActionRequest→ShadowBlockActionRequestPayloadUnbanActionRequest→UnbanActionRequestPayloadCallers will need to update their code to use the new payload types.
getstream/chat/channel.py (2)
71-71: Breaking change:dataparameter type updated toChannelInputRequest.The parameter type changed from
ChannelInputtoChannelInputRequest. Existing callers passingChannelInputwill need to migrate.
329-348: New optionalmessage_timestampparameter added tomark_unread.This is an additive, non-breaking change that extends the API to support marking unread by timestamp in addition to message ID.
getstream/chat/async_channel.py (2)
71-71: Breaking change consistent with sync version.The
dataparameter type changed toChannelInputRequest, matching the syncChannelclass.
329-348: Async version mirrors sync changes formark_unread.The
message_timestampparameter addition is consistent with the syncChannel.mark_unreadmethod.getstream/feeds/feeds.py (1)
26-66: New optional parameters added toget_or_create.Two new optional parameters added:
id_around: Optional[str]- for around-based paginationenrichment_options: Optional[EnrichmentOptions]- for controlling enrichment behaviorThese are additive, non-breaking changes that extend the API surface.
getstream/chat/rest_client.py (3)
144-157: Newmark_deliveredendpoint added.This new method allows marking messages as delivered for a user. The implementation follows the established patterns with proper telemetry decoration and parameter handling.
260-260: Breaking change:dataparameter type updated inupdate_channel.Type changed from
ChannelInputtoChannelInputRequest, consistent with the Channel wrapper classes.
627-654: Extendedmark_unreadwithmessage_timestampparameter.The new optional
message_timestampparameter is properly included in the request body viabuild_body_dict. This is a non-breaking additive change.getstream/video/rest_client.py (4)
870-899: Newget_call_stats_mapendpoint looks correct.The implementation correctly mirrors the async counterpart, using query parameters for optional filters and path parameters for required identifiers. The return type
QueryCallStatsMapResponsealigns with the model definition.
1024-1024: Type update toNotificationSettingsRequestis consistent.The change from
NotificationSettingstoNotificationSettingsRequestaligns with the new payload variant types for request bodies, matching the async client changes.
1062-1062: Type update inupdate_call_typematchescreate_call_type.Consistent use of
NotificationSettingsRequestacross both create and update operations.
1090-1090:SIPChallengeRequesttype update is appropriate.The
challengeparameter now uses the dedicated request payload type, which is consistent with the API schema refactoring pattern applied throughout this PR.getstream/chat/async_rest_client.py (4)
146-159: Newmark_deliveredmethod implementation is correct.The async implementation properly mirrors the sync counterpart, using
user_idas a query parameter andlatest_delivered_messagesin the request body. Telemetry decorator is correctly applied.
264-264: Type update toChannelInputRequestinupdate_channelis correct.This aligns with the PR's schema updates for request payload types.
631-658:mark_unreadextended withmessage_timestampparameter.The new optional
datetimeparameter is correctly added to the method signature and included in the request body viabuild_body_dict. This enhancement allows marking unread by timestamp in addition to message ID.
175-204: Async and sync clients are consistent; type difference between methods appears intentional.Both the async and sync clients use
ChannelInputforget_or_create_distinct_channelandChannelInputRequestforupdate_channel. The type difference is not an inconsistency between sync/async implementations but rather reflects intentional schema differences:ChannelInputincludescreated_by_id,truncated_by_id, andfilter_tagsfields thatChannelInputRequestomits, and theirconfig_overridesfields reference different types (ChannelConfigvsConfigOverridesRequest), suggesting the endpoints accept different request structures.getstream/moderation/rest_client.py (5)
203-225:custom_checkcorrectly updated to useModerationPayloadRequest.The type update for
moderation_payloadparameter aligns with the new payload variant types.
243-252:v2_upsert_templateupdated withFeedsModerationTemplateConfigPayload.The
configparameter type change is consistent with the schema refactoring.
278-292:query_moderation_flagsupdated to useSortParamRequest.Consistent with other methods using the new request type for sort parameters.
448-486:submit_actioncorrectly updated with new payload variant types.All action parameters (ban, block, custom, delete_*, mark_reviewed, shadow_block, unban) now use their respective
...RequestPayloadtypes, aligning with the schema updates.
254-276: Consider clarifying the intent of type inconsistency in moderation methods.The
flagmethod (line 263) usesModerationPayloadwhilecustom_check(line 211) usesModerationPayloadRequest. This pattern is consistent across the async client as well, wherecheckandflaguseModerationPayload, while onlycustom_checkusesModerationPayloadRequest. Since both types have identical structure, clarify whether this distinction is intentional (e.g., to explicitly markcustom_checkas request-only) or if the methods should be unified to use the same type for consistency.getstream/feeds/rest_client.py (7)
3-3: Telemetry import added for instrumentation.The addition of telemetry enables observability across all Feeds API methods.
34-80:add_activityextended with new parameters and telemetry.New optional parameters
restrict_replies,skip_enrich_url, andcollection_refsexpand the API capabilities. Telemetry decorator correctly applied.
505-560: New collection CRUD endpoints added.The
delete_collections,read_collections,update_collections,create_collections, andupsert_collectionsmethods provide comprehensive collection management. Each uses appropriate HTTP methods and parameter handling.
799-808:list_feed_groupsextended withinclude_soft_deletedfilter.Correctly passed as a query parameter for the GET request.
1299-1329: New feed visibility endpoints added.
list_feed_visibilities,get_feed_visibility, andupdate_feed_visibilityprovide visibility management capabilities with consistent patterns.
1375-1395: Newget_feeds_rate_limitsendpoint.Provides rate limit introspection with platform-specific filters (android, ios, web, server_side).
1604-1617:delete_feed_user_datachanged from DELETE to POST.The method now uses POST with a request body containing
hard_delete. This is a semantic change from the typical DELETE pattern but is appropriate when the operation requires request body parameters.
| limit: Optional[int] = None, | ||
| prev: Optional[str] = None, | ||
| next: Optional[str] = None, | ||
| sort: Optional[List[SortParamRequest]] = None, | ||
| filter_conditions: Optional[Dict[str, object]] = None, | ||
| ) -> StreamResponse[QueryCallSessionParticipantStatsResponse]: | ||
| query_params = build_query_param(sort=sort, filter_conditions=filter_conditions) | ||
| query_params = build_query_param( | ||
| limit=limit, | ||
| prev=prev, | ||
| next=next, | ||
| sort=sort, | ||
| filter_conditions=filter_conditions, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for build_query_param function definition
rg -n -B 3 -A 20 "def build_query_param" --type pyRepository: GetStream/stream-py
Length of output: 3411
🏁 Script executed:
#!/bin/bash
# Get the complete build_query_param function
sed -n '94,130p' getstream/utils/__init__.pyRepository: GetStream/stream-py
Length of output: 1485
🏁 Script executed:
#!/bin/bash
# Search for SortParamRequest class definition
rg -n -A 15 "class SortParamRequest" --type pyRepository: GetStream/stream-py
Length of output: 1217
🏁 Script executed:
#!/bin/bash
# Search for DataClassJsonMixin to understand the to_json() method
rg -n "from dataclasses_json\|class DataClassJsonMixin\|def to_json" --type py | head -20Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check imports in models file
head -50 getstream/models/__init__.py | grep -E "import|from"Repository: GetStream/stream-py
Length of output: 419
🏁 Script executed:
#!/bin/bash
# Search for tests or usage of query_call_session_participant_stats
rg -n "query_call_session_participant_stats\|QueryCallSessionParticipantStats" --type pyRepository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Search for test files and build_query_param usage
rg -n "build_query_param\|sort.*filter" tests/ --type py | head -30Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Find test files and search for sort/filter usage
find . -path ./venv -prune -o -name "*test*.py" -type f -print | head -20Repository: GetStream/stream-py
Length of output: 729
🏁 Script executed:
#!/bin/bash
# Search for sort and filter_conditions usage in tests
rg -n "sort\|filter_conditions" tests/ --type py | head -30Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check the actual method signature in async_rest_client.py around lines 944-956
sed -n '930,970p' getstream/video/async_rest_client.pyRepository: GetStream/stream-py
Length of output: 1545
Fix sort parameter serialization in query parameters.
The sort parameter uses str(v) on SortParamRequest objects instead of calling their to_json() method, resulting in malformed query parameters. Update build_query_param() to check for to_json() before converting list items to strings, or ensure SortParamRequest objects are properly serialized as JSON for the API endpoint.
🤖 Prompt for AI Agents
In getstream/video/async_rest_client.py around lines 944 to 956, the sort
parameter is being converted using str(v) which yields malformed query values
for SortParamRequest objects; update the query param construction to detect
items with a to_json() method (or isinstance check for SortParamRequest) and
call item.to_json() (or json-serialize the dict) when present, otherwise
stringify primitives, ensuring the final sort list is properly JSON-serialized
or encoded for the API query string.
| limit: Optional[int] = None, | ||
| prev: Optional[str] = None, | ||
| next: Optional[str] = None, | ||
| sort: Optional[List[SortParamRequest]] = None, | ||
| filter_conditions: Optional[Dict[str, object]] = None, | ||
| ) -> StreamResponse[QueryCallSessionParticipantStatsResponse]: | ||
| query_params = build_query_param(sort=sort, filter_conditions=filter_conditions) | ||
| query_params = build_query_param( | ||
| limit=limit, | ||
| prev=prev, | ||
| next=next, | ||
| sort=sort, | ||
| filter_conditions=filter_conditions, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if the file exists and examine the specified lines
if [ -f "getstream/video/rest_client.py" ]; then
echo "=== Lines 935-955 of getstream/video/rest_client.py ==="
sed -n '935,955p' getstream/video/rest_client.py
else
echo "File not found"
fiRepository: GetStream/stream-py
Length of output: 827
🏁 Script executed:
#!/bin/bash
# Search for the build_query_param function
rg -n "def build_query_param" --type pyRepository: GetStream/stream-py
Length of output: 203
🏁 Script executed:
#!/bin/bash
# Check for query_call_session_participant_stats in async client
rg -n -A 20 "def query_call_session_participant_stats" getstream/video/async_rest_client.pyRepository: GetStream/stream-py
Length of output: 861
🏁 Script executed:
#!/bin/bash
# Examine the build_query_param implementation
sed -n '94,130p' getstream/utils/__init__.pyRepository: GetStream/stream-py
Length of output: 1485
🏁 Script executed:
#!/bin/bash
# Search for SortParamRequest definition
rg -n "class SortParamRequest" --type pyRepository: GetStream/stream-py
Length of output: 141
🏁 Script executed:
#!/bin/bash
# Check if SortParamRequest has to_json method
rg -n -A 10 "class SortParamRequest" --type pyRepository: GetStream/stream-py
Length of output: 808
🏁 Script executed:
#!/bin/bash
# Check DataClassJsonMixin to understand how SortParamRequest serializes
rg -n "class DataClassJsonMixin" --type pyRepository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Look for how the query parameters are actually used in the request
sed -n '950,970p' getstream/video/rest_client.pyRepository: GetStream/stream-py
Length of output: 731
🏁 Script executed:
#!/bin/bash
# Check the exact import and confirmation that SortParamRequest has to_json
rg -n "to_json" getstream/models/__init__.py | head -20Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check if DataClassJsonMixin is imported and used
rg -n "DataClassJsonMixin" getstream/models/__init__.py | head -10Repository: GetStream/stream-py
Length of output: 499
🏁 Script executed:
#!/bin/bash
# Check the imports at the top of utils/__init__.py to see what quote is used
head -30 getstream/utils/__init__.pyRepository: GetStream/stream-py
Length of output: 741
🏁 Script executed:
#!/bin/bash
# Let's also verify the actual HTTP request handling to see if there's any limit consideration
rg -n "def get\(" getstream/video/rest_client.py | head -5Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Find the get method in rest_client to see how query_params are constructed
rg -n "def get" getstream/video/rest_client.py | grep -E "def get\(" | head -3Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Look at the actual HTTP request call in the get method
rg -n -A 15 "def get\(self" getstream/video/rest_client.py | head -30Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check the base class to understand HTTP request handling
rg -n "class.*RestClient" getstream/video/rest_client.pyRepository: GetStream/stream-py
Length of output: 99
🏁 Script executed:
#!/bin/bash
# Look at how query_params are passed in the self.get call
rg -n "query_params=" getstream/video/rest_client.py | head -10Repository: GetStream/stream-py
Length of output: 405
🏁 Script executed:
#!/bin/bash
# Find BaseClient implementation
rg -n "class BaseClient" --type pyRepository: GetStream/stream-py
Length of output: 164
🏁 Script executed:
#!/bin/bash
# Look for the get method in BaseClient
rg -n -A 20 "def get\(self" getstream/base_client.py | head -40Repository: GetStream/stream-py
Length of output: 127
🏁 Script executed:
#!/bin/bash
# Find the get method in BaseClient located at getstream/base.py
rg -n -A 20 "def get\(self" getstream/base.py | head -50Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check what happens with query_params in the HTTP request
rg -n "query_params" getstream/base.py | head -20Repository: GetStream/stream-py
Length of output: 1109
🏁 Script executed:
#!/bin/bash
# Check the _prepare_request method implementation
sed -n '98,115p' getstream/base.pyRepository: GetStream/stream-py
Length of output: 819
🏁 Script executed:
#!/bin/bash
# Check what HTTP library is used (requests import)
head -50 getstream/base.py | grep -E "import|from"Repository: GetStream/stream-py
Length of output: 629
🏁 Script executed:
#!/bin/bash
# Check if SortParamRequest or DataClassJsonMixin provides to_json method
rg -n "to_json" getstream/ --type py | grep -i "sortparam\|dataclass" | head -20Repository: GetStream/stream-py
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check what DataClassJsonMixin provides
python3 -c "from dataclasses_json import DataClassJsonMixin; print(dir(DataClassJsonMixin))" 2>/dev/null || echo "Module check failed, let's verify with rg"
rg -n "\.to_json\(" getstream/ --type py | head -10Repository: GetStream/stream-py
Length of output: 149
🏁 Script executed:
#!/bin/bash
# Let's check if there's a test file that shows how sort parameter is used
rg -n "query_call_session_participant_stats" getstream/ --type py -A 3 | head -40Repository: GetStream/stream-py
Length of output: 885
🏁 Script executed:
#!/bin/bash
# Check if there are any tests for build_query_param
rg -n "build_query_param" getstream/ --type py -B 2 -A 5 | head -60Repository: GetStream/stream-py
Length of output: 3512
🏁 Script executed:
#!/bin/bash
# Let's verify the exact serialization behavior with a simple test
cat > /tmp/test_serialize.py << 'EOF'
import sys
sys.path.insert(0, '/tmp')
# Simulate what build_query_param does with a list
from urllib.parse import quote
class MockSortParam:
def __init__(self, field, direction):
self.field = field
self.direction = direction
def __repr__(self):
return f"SortParamRequest(field={self.field}, direction={self.direction})"
def to_json(self):
return f'{{"field":"{self.field}","direction":{self.direction}}}'
# Test what happens with list serialization
sort_list = [MockSortParam("created_at", 1), MockSortParam("updated_at", -1)]
# This is what build_query_param does for lists:
result = ",".join(quote(str(v)) for v in sort_list)
print("List serialization (current approach):")
print(result)
print()
# This is what it should do if checking to_json:
result_better = ",".join(quote(v.to_json()) if hasattr(v, 'to_json') else quote(str(v)) for v in sort_list)
print("List serialization (if checking to_json):")
print(result_better)
EOF
python3 /tmp/test_serialize.pyRepository: GetStream/stream-py
Length of output: 384
🏁 Script executed:
#!/bin/bash
# Let's check if dataclasses_json actually provides to_json method
cat > /tmp/test_dataclass.py << 'EOF'
from dataclasses import dataclass
from dataclasses_json import DataClassJsonMixin
@dataclass
class TestSort(DataClassJsonMixin):
field: str
direction: int
obj = TestSort(field="created_at", direction=1)
print("Has to_json:", hasattr(obj, 'to_json'))
print("Callable to_json:", hasattr(obj, 'to_json') and callable(obj.to_json))
if hasattr(obj, 'to_json') and callable(obj.to_json):
print("to_json() result:", obj.to_json())
print("str() result:", str(obj))
EOF
python3 /tmp/test_dataclass.pyRepository: GetStream/stream-py
Length of output: 258
🏁 Script executed:
#!/bin/bash
# Now let's verify how the query parameters are actually passed to httpx
rg -n "params=query_params" getstream/base.py -B 3 -A 3Repository: GetStream/stream-py
Length of output: 3367
🏁 Script executed:
#!/bin/bash
# Let's check how httpx handles query parameters
cat > /tmp/test_httpx.py << 'EOF'
import httpx
# Simulate what happens when we pass query_params to httpx
params = {
"sort": "SortParamRequest%28field%3Dcreated_at%2C%20direction%3D1%29,SortParamRequest%28field%3Dupdated_at%2C%20direction%3D-1%29",
"filter_conditions": '{"created_at": {"$gte": "2024-01-01"}, "status": "active"}'
}
# Create a sample request
req = httpx.Request("GET", "http://example.com/api/endpoint", params=params)
print("Generated URL:")
print(req.url)
print()
print("URL length:", len(str(req.url)))
EOF
python3 /tmp/test_httpx.pyRepository: GetStream/stream-py
Length of output: 393
🏁 Script executed:
#!/bin/bash
# Check if there are any other similar patterns in the codebase
rg -n "isinstance.*list" getstream/utils/__init__.py -B 2 -A 5Repository: GetStream/stream-py
Length of output: 1048
Sort parameter serialization bypasses to_json() method for list elements.
The build_query_param function (line 120-122) processes list values using str(v) instead of checking for to_json() methods on elements. When sort is passed as List[SortParamRequest], this produces verbose string representations like SortParamRequest(field=created_at, direction=1) instead of JSON, resulting in double-encoded query parameters (e.g., SortParamRequest%2528field%253Dcreated_at...). While filter_conditions (Dict) correctly uses json.dumps(), the sort parameter should similarly leverage the to_json() method available on DataClassJsonMixin-based objects to produce clean, properly encoded query strings and avoid unnecessarily long URLs.
🤖 Prompt for AI Agents
In getstream/video/rest_client.py around lines 940 to 952, the sort list is
being passed through build_query_param which currently stringifies list elements
with str(v) causing verbose, non-JSON and double-encoded query values; update
the serialization so that when a list element has a to_json() method (or is an
instance of DataClassJsonMixin) you call that to obtain a JSON-serializable
dict/string (or call element.to_json() and then json.loads if it returns a JSON
string), build a list of those serializable representations and json.dumps the
whole list before adding to the query params; alternatively, special-case the
sort parameter before calling build_query_param to map each SortParamRequest to
its JSON form and pass the JSON-dumped list so query strings are compact and
correctly encoded.
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.