getstream 3.4.0__tar.gz → 3.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {getstream-3.4.0 → getstream-3.5.0}/.github/workflows/release.yml +0 -4
- getstream-3.5.0/CHANGELOG.md +147 -0
- {getstream-3.4.0 → getstream-3.5.0}/PKG-INFO +1 -1
- getstream-3.5.0/getstream/__init__.py +9 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/base.py +132 -73
- {getstream-3.4.0 → getstream-3.5.0}/getstream/chat/async_rest_client.py +62 -1
- {getstream-3.4.0 → getstream-3.5.0}/getstream/chat/rest_client.py +60 -1
- {getstream-3.4.0 → getstream-3.5.0}/getstream/common/async_rest_client.py +29 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/common/rest_client.py +29 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/config.py +6 -0
- getstream-3.5.0/getstream/exceptions.py +326 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/feeds/feeds.py +2 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/feeds/rest_client.py +69 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/models/__init__.py +1159 -47
- {getstream-3.4.0 → getstream-3.5.0}/getstream/moderation/async_rest_client.py +88 -4
- {getstream-3.4.0 → getstream-3.5.0}/getstream/moderation/rest_client.py +86 -4
- {getstream-3.4.0 → getstream-3.5.0}/getstream/stream.py +157 -40
- getstream-3.5.0/getstream/tasks.py +104 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/tests/test_webhook.py +13 -1
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/async_rest_client.py +9 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rest_client.py +9 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/webhook.py +9 -3
- {getstream-3.4.0 → getstream-3.5.0}/pyproject.toml +2 -1
- {getstream-3.4.0 → getstream-3.5.0}/uv.lock +30 -4
- getstream-3.4.0/CHANGELOG.md +0 -69
- getstream-3.4.0/getstream/__init__.py +0 -2
- {getstream-3.4.0 → getstream-3.5.0}/.cursor/worktrees.json +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.env.example +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.github/actions/python-uv-setup/action.yml +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.github/workflows/ci.yml +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.github/workflows/run_tests.yml +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.github/workflows/stream-py.code-workspace +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.gitignore +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.gitmodules +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/.pre-commit-config.yaml +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/AGENTS.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/DEVELOPMENT.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/LICENSE.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/MIGRATION_v2_to_v3.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/Makefile +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/README.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/dev.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/docs/migration-from-stream-chat-python/01-setup-and-auth.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/docs/migration-from-stream-chat-python/02-users.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/docs/migration-from-stream-chat-python/03-channels.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/docs/migration-from-stream-chat-python/04-messages-and-reactions.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/docs/migration-from-stream-chat-python/05-moderation.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/docs/migration-from-stream-chat-python/06-devices.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/docs/migration-from-stream-chat-python/README.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/generate.sh +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/generate_webrtc.sh +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/chat/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/chat/async_channel.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/chat/async_client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/chat/channel.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/chat/client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/common/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/common/async_client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/common/client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/common/telemetry.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/feeds/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/feeds/client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/generic.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/meta.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/moderation/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/moderation/async_client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/moderation/client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/rate_limit.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/stream_response.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/utils/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/utils/event_emitter.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/utils/retry.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/version.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/async_call.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/async_client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/call.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/client.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/openai.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/README.md +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/audio_track.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/connection_manager.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/connection_utils.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/coordinator/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/coordinator/backoff.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/coordinator/errors.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/coordinator/ws.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/encoders_patches.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/g711.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/location_discovery.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/models.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/network_monitor.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/participants.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/event/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.pyi +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/models/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.pyi +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/__init__.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.pyi +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_twirp.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/pc.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/peer_connection.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/reconnection.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/recording.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/signaling.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/stats_reporter.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/stats_tracer.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/tracer.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/track_util.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/tracks.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/twirp_client_wrapper.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/getstream/video/rtc/utils.py +0 -0
- {getstream-3.4.0 → getstream-3.5.0}/pytest.ini +0 -0
|
@@ -64,13 +64,9 @@ jobs:
|
|
|
64
64
|
if: github.event_name == 'pull_request' && steps.already_released.outputs.value != 'true'
|
|
65
65
|
env:
|
|
66
66
|
PR_TITLE: ${{ github.event.pull_request.title }}
|
|
67
|
-
PR_BODY: ${{ github.event.pull_request.body }}
|
|
68
67
|
run: |
|
|
69
|
-
PR_BODY_FILE=$(mktemp)
|
|
70
|
-
printf '%s' "$PR_BODY" > "$PR_BODY_FILE"
|
|
71
68
|
python3 scripts/release/bump_version.py \
|
|
72
69
|
--title "$PR_TITLE" \
|
|
73
|
-
--body-file "$PR_BODY_FILE" \
|
|
74
70
|
--output "$GITHUB_OUTPUT"
|
|
75
71
|
|
|
76
72
|
- name: Determine version bump (manual)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Standardized error hierarchy ([CHA-2958](https://linear.app/stream/issue/CHA-2958)).
|
|
13
|
+
New exception classes importable from `getstream` (also re-exported from
|
|
14
|
+
`getstream.exceptions`):
|
|
15
|
+
- `StreamException`: abstract base for every SDK error.
|
|
16
|
+
- `StreamApiException`: any HTTP 4xx/5xx response. Carries `status_code`,
|
|
17
|
+
`code`, `message`, `exception_fields`, `unrecoverable`,
|
|
18
|
+
`raw_response_body`, `more_info`, `details`. The `unrecoverable` flag
|
|
19
|
+
from `APIError` is now surfaced (was previously dropped on most paths).
|
|
20
|
+
- `StreamRateLimitException`: subclass of `StreamApiException` raised on
|
|
21
|
+
HTTP 429. Adds `retry_after: datetime.timedelta | None`, parsed from
|
|
22
|
+
`Retry-After` per RFC 7231 (integer seconds or HTTP-date). Missing or
|
|
23
|
+
unparseable headers map to `None`; past HTTP-dates clamp to `0`.
|
|
24
|
+
- `StreamTransportException`: raised when a network-layer failure (no
|
|
25
|
+
HTTP response received) propagates out of `httpx` — connection reset,
|
|
26
|
+
timeout, TLS handshake failure, DNS failure. Carries `error_type`
|
|
27
|
+
enum (`connection_reset` / `timeout` / `dns_failure` /
|
|
28
|
+
`tls_handshake_failed` / `unknown`). The original `httpx` exception
|
|
29
|
+
is preserved as `__cause__`.
|
|
30
|
+
- `StreamTaskException`: raised by `wait_for_task` when the polled task
|
|
31
|
+
ends in `status='failed'`. Carries `task_id`, `error_type`,
|
|
32
|
+
`description`, `stack_trace`, `version`.
|
|
33
|
+
- `Stream.wait_for_task(task_id, *, poll_interval=1.0, timeout=60.0)` and
|
|
34
|
+
the matching async coroutine on `AsyncStream`. Polls `get_task` until the
|
|
35
|
+
task reaches a terminal state. On `completed` returns the
|
|
36
|
+
`StreamResponse[GetTaskResponse]`; on `failed` raises
|
|
37
|
+
`StreamTaskException` populated from `ErrorResult`; on timeout raises
|
|
38
|
+
`StreamTransportException(error_type='timeout')`.
|
|
39
|
+
|
|
40
|
+
- Explicit HTTP connection pool configuration ([CHA-2956](https://linear.app/stream/issue/CHA-2956/connection-pooling)).
|
|
41
|
+
Four new kwargs on `Stream(...)` and `AsyncStream(...)`:
|
|
42
|
+
- `max_conns_per_host: int`: default `5`
|
|
43
|
+
- `idle_timeout: float` (seconds): default `55.0`
|
|
44
|
+
- `connect_timeout: float` (seconds): default `10.0`
|
|
45
|
+
- `request_timeout: float` (seconds): default `30.0` (was `6.0`; see Behavior changes)
|
|
46
|
+
|
|
47
|
+
These tune the underlying `httpx.Limits` and `httpx.Timeout`. The existing `http_client=` and `transport=` kwargs continue to act as escape hatches; when `http_client` is set, none of the four new kwargs apply. Env-var fallbacks for the new kwargs: `STREAM_MAX_CONNS_PER_HOST`, `STREAM_IDLE_TIMEOUT`, `STREAM_CONNECT_TIMEOUT`, `STREAM_REQUEST_TIMEOUT`.
|
|
48
|
+
- INFO log on client construction (logger `getstream`) lists the effective pool config and whether a user-supplied `http_client` is in use.
|
|
49
|
+
|
|
50
|
+
- Webhook handling spec helpers (CHA-2961): `UnknownEvent` dataclass for
|
|
51
|
+
forward-compat; `gunzip_payload`, `decode_sqs_payload`, `decode_sns_payload`
|
|
52
|
+
primitives; `parse_event` (returns typed event or `UnknownEvent` for
|
|
53
|
+
unrecognized discriminators); `verify_signature` canonical alias of
|
|
54
|
+
`verify_webhook_signature`; `verify_and_parse_webhook` HTTP composite
|
|
55
|
+
(gunzip + verify + parse); `parse_sqs` and `parse_sns` queue composites
|
|
56
|
+
(no signature parameter: queue transports are authenticated by AWS IAM,
|
|
57
|
+
so the backend emits no HMAC for queue messages today). Transparent gzip
|
|
58
|
+
via magic-byte detection.
|
|
59
|
+
- New instance methods on `Stream` and `AsyncStream`:
|
|
60
|
+
`verify_signature(body, signature)` and
|
|
61
|
+
`verify_and_parse_webhook(body, signature)` that drop the api_secret parameter
|
|
62
|
+
in favor of the client's stored secret. Dual API: the module-level functions
|
|
63
|
+
in `getstream.webhook` remain available for callers who want explicit
|
|
64
|
+
secret control.
|
|
65
|
+
- New instance methods on `Stream` / `AsyncStream`: `parse_sqs(message_body)`,
|
|
66
|
+
`parse_sns(notification_body)` (no signature; AWS IAM).
|
|
67
|
+
- `InvalidWebhookError` exception type covering both signature mismatches and
|
|
68
|
+
malformed payloads. Distinguish failure modes via the exception message or
|
|
69
|
+
`__cause__` chain.
|
|
70
|
+
- Conformance fixture suite under `tests/fixtures/webhooks/` (13 happy-path
|
|
71
|
+
event directories + 8 negative cases) for SDK conformance testing across
|
|
72
|
+
language ports.
|
|
73
|
+
- Regenerated from the latest chat OpenAPI spec. New endpoints: `moderation.analyze`,
|
|
74
|
+
`moderation.bulk_action_appeals`, `moderation.get_setup_session`,
|
|
75
|
+
`moderation.upsert_setup_session`; `feeds.get_or_create_follow`,
|
|
76
|
+
`feeds.get_or_create_unfollow`, `feeds.get_user_interests`; `chat.create_segment`,
|
|
77
|
+
`chat.update_segment`, `chat.add_segment_targets`; `common.cancel_import_v2_task`;
|
|
78
|
+
`video.report_client_call_event`, together with the request/response models backing them.
|
|
79
|
+
- New webhook event types `moderation.image_analysis.complete` and
|
|
80
|
+
`moderation.text_analysis.complete`, with `ModerationImageAnalysisCompleteEvent`
|
|
81
|
+
and `ModerationTextAnalysisCompleteEvent` models.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- HTTP request errors raised by `httpx` (the `httpx.RequestError` family —
|
|
86
|
+
`ConnectError`, `ReadTimeout`, etc.) are now wrapped at the SDK boundary
|
|
87
|
+
in `StreamTransportException` so callers handle one Stream error category
|
|
88
|
+
instead of catching `httpx.RequestError` separately. The original `httpx`
|
|
89
|
+
exception is preserved via `__cause__` (CHA-2958).
|
|
90
|
+
- **Default `request_timeout` is now `30.0` seconds (was `6.0`).** Aligns stream-py with the cross-SDK contract in CHA-2956. Existing callers using `timeout=` are unaffected; `timeout` is kept as an alias for `request_timeout`. Callers relying on the 6s ceiling for fail-fast behavior should pass `request_timeout=6.0` (or `timeout=6.0`) explicitly.
|
|
91
|
+
- Default HTTP transport now caps connections per host at `5` and closes idle sockets after `55.0s`. Previous default was httpx's `100` max-connections with `5.0s` keep-alive expiry.
|
|
92
|
+
- No breaking changes. All existing webhook helpers (`verify_webhook_signature`,
|
|
93
|
+
`parse_webhook_event`, `get_event_type`, event type constants) are preserved.
|
|
94
|
+
- `FlagResponse` now represents the full flag record (`created_at`, `updated_at`,
|
|
95
|
+
`target_message`, `target_user`, `user`, `reason`, `details`, `custom`, and related
|
|
96
|
+
fields). The moderation flag-action acknowledgement, which carries `item_id` and
|
|
97
|
+
`duration`, moved to the new `FlagItemResponse`; `moderation.flag()` now returns
|
|
98
|
+
`FlagItemResponse`. The `/api/v2/moderation/flag` wire response is unchanged, so code
|
|
99
|
+
reading `item_id`/`duration` off the parsed response is unaffected. Code referencing
|
|
100
|
+
the `FlagResponse` type for those two fields should switch to `FlagItemResponse`.
|
|
101
|
+
- `ChannelInput.config_overrides` and `ChannelDataUpdate.config_overrides` are now typed
|
|
102
|
+
as `ChannelConfigOverrides` (the override-specific field set) instead of `ChannelConfig`.
|
|
103
|
+
- `enabled` on `DeliveryReceiptsResponse`, `ReadReceiptsResponse`, and
|
|
104
|
+
`TypingIndicatorsResponse` is now a required `bool` (was `Optional[bool]`).
|
|
105
|
+
- `LLMRule.description`, `TargetResolution.bitrate`, and `TranslationSettings.languages` /
|
|
106
|
+
`TranslationSettings.enabled` are now optional.
|
|
107
|
+
|
|
108
|
+
### Deprecated
|
|
109
|
+
|
|
110
|
+
- `getstream.base.StreamAPIException` (capital `API`) is now an alias for
|
|
111
|
+
`getstream.exceptions.StreamApiException` (lowercase `Api`). Importing the
|
|
112
|
+
old name emits `DeprecationWarning`; existing `isinstance` / `except` /
|
|
113
|
+
`pytest.raises` checks continue to work because the alias resolves to the
|
|
114
|
+
same class. The legacy spelling will be removed one minor cycle after this
|
|
115
|
+
release (CHA-2958 §10).
|
|
116
|
+
|
|
117
|
+
### Notes
|
|
118
|
+
|
|
119
|
+
- Per-call `timeout=httpx.Timeout(...)` continues to work through `.get(...)`, `.post(...)`, etc., and pre-empts the client-level `request_timeout`.
|
|
120
|
+
|
|
121
|
+
## [3.0.0b1] - 2026-02-27
|
|
122
|
+
|
|
123
|
+
### Breaking Changes
|
|
124
|
+
|
|
125
|
+
- Type names across all products now follow the OpenAPI spec naming convention: response types are suffixed with `Response`, input types with `Request`. See [MIGRATION_v2_to_v3.md](./MIGRATION_v2_to_v3.md) for the complete rename mapping.
|
|
126
|
+
- `Event` (WebSocket envelope type) renamed to `WSEvent`. Base event type renamed from `BaseEvent` to `Event` (with field `type` instead of `T`).
|
|
127
|
+
- Event composition changed from monolithic `*Preset` embeds to modular `Has*` types.
|
|
128
|
+
- `Pager` renamed to `PagerResponse` and migrated from offset-based to cursor-based pagination (`next`/`prev` tokens).
|
|
129
|
+
- Types that were previously `dict` or `TypedDict` (e.g., `User`, `Channel`, `Message`) are now full dataclasses with typed fields.
|
|
130
|
+
|
|
131
|
+
### Added
|
|
132
|
+
|
|
133
|
+
- Full product coverage: Chat, Video, Moderation, and Feeds APIs are all supported in a single SDK.
|
|
134
|
+
- **Feeds**: activities, feeds, feed groups, follows, comments, reactions, collections, bookmarks, membership levels, feed views, and more.
|
|
135
|
+
- **Video**: calls, recordings, transcription, closed captions, SFU, call statistics, user feedback analytics, and more.
|
|
136
|
+
- **Moderation**: flags, review queue, moderation rules, config, appeals, moderation logs, and more.
|
|
137
|
+
- Push notification types, preferences, and templates.
|
|
138
|
+
- Webhook support: `WHEvent` envelope class for receiving webhook payloads, utility functions for decoding and verifying webhook signatures, and a full set of individual typed event dataclasses for every event across all products (Chat, Video, Moderation, Feeds) usable as discriminated event types.
|
|
139
|
+
- Cursor-based pagination across all list endpoints.
|
|
140
|
+
|
|
141
|
+
## [2.7.1] - 2026-02-18
|
|
142
|
+
|
|
143
|
+
## [2.7.0] - 2026-02-03
|
|
144
|
+
|
|
145
|
+
## [2.6.0] - 2025-12-11
|
|
146
|
+
|
|
147
|
+
## [2.5.22] - 2025-10-15
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: getstream
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: GetStream Python SDK - Build scalable activity feeds, chat, and video calling applications
|
|
5
5
|
Author-email: sachaarbonel <sacha.arbonel@hotmail.fr>, tbarbugli <tbarbugli@gmail.com>
|
|
6
6
|
License-File: LICENSE.md
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from getstream.exceptions import ( # noqa: F401
|
|
2
|
+
StreamApiException,
|
|
3
|
+
StreamException,
|
|
4
|
+
StreamRateLimitException,
|
|
5
|
+
StreamTaskException,
|
|
6
|
+
StreamTransportException,
|
|
7
|
+
)
|
|
8
|
+
from getstream.stream import Stream # noqa: F401
|
|
9
|
+
from getstream.stream import AsyncStream # noqa: F401
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import logging
|
|
2
3
|
import mimetypes
|
|
3
4
|
import os
|
|
4
5
|
import time
|
|
5
6
|
import uuid
|
|
7
|
+
import warnings
|
|
6
8
|
import asyncio
|
|
7
9
|
from typing import Any, Dict, List, Optional, Tuple, Type, cast, get_origin
|
|
8
10
|
|
|
9
|
-
from getstream.
|
|
10
|
-
|
|
11
|
+
from getstream.exceptions import (
|
|
12
|
+
StreamApiException,
|
|
13
|
+
build_api_exception,
|
|
14
|
+
wrap_transport_error,
|
|
15
|
+
)
|
|
11
16
|
from getstream.stream_response import StreamResponse
|
|
12
17
|
from getstream.generic import T
|
|
13
18
|
import httpx
|
|
@@ -27,6 +32,51 @@ from getstream.common.telemetry import (
|
|
|
27
32
|
import ijson
|
|
28
33
|
|
|
29
34
|
|
|
35
|
+
# ── Connection pool defaults (CHA-2956) ──────────────────────────────
|
|
36
|
+
# Kept in sync with getstream.stream constants; duplicated here so BaseClient/AsyncBaseClient can be instantiated standalone (e.g. by sub-clients constructed directly without going through Stream/AsyncStream).
|
|
37
|
+
DEFAULT_MAX_CONNS_PER_HOST = 5
|
|
38
|
+
DEFAULT_IDLE_TIMEOUT = 55.0
|
|
39
|
+
DEFAULT_CONNECT_TIMEOUT = 10.0
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
logger = logging.getLogger("getstream")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _resolve_pool_knobs(obj):
|
|
46
|
+
"""Pull the 3 pool knobs off ``obj`` if BaseStream has set them, else fall back to spec defaults. Top-level ``Stream``/``AsyncStream`` sets them on ``self`` before calling ``super().__init__()``, so a directly instantiated sub-client (or test fixture) still gets sane values.
|
|
47
|
+
|
|
48
|
+
`is None` (not truthiness) so an explicit `0` / `0.0` from the caller is preserved rather than silently swapped for a default.
|
|
49
|
+
"""
|
|
50
|
+
max_conns_per_host = getattr(obj, "max_conns_per_host", None)
|
|
51
|
+
idle_timeout = getattr(obj, "idle_timeout", None)
|
|
52
|
+
connect_timeout = getattr(obj, "connect_timeout", None)
|
|
53
|
+
return (
|
|
54
|
+
DEFAULT_MAX_CONNS_PER_HOST
|
|
55
|
+
if max_conns_per_host is None
|
|
56
|
+
else max_conns_per_host,
|
|
57
|
+
DEFAULT_IDLE_TIMEOUT if idle_timeout is None else idle_timeout,
|
|
58
|
+
DEFAULT_CONNECT_TIMEOUT if connect_timeout is None else connect_timeout,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _log_pool_config(cfg, *, user_http_client: bool) -> None:
|
|
63
|
+
if user_http_client:
|
|
64
|
+
logger.info(
|
|
65
|
+
"getstream connection pool: user_http_client=True (5 knobs not applied)"
|
|
66
|
+
)
|
|
67
|
+
else:
|
|
68
|
+
logger.info(
|
|
69
|
+
"getstream connection pool: "
|
|
70
|
+
"max_conns_per_host=%s idle_timeout=%ss "
|
|
71
|
+
"connect_timeout=%ss request_timeout=%ss "
|
|
72
|
+
"user_http_client=False",
|
|
73
|
+
cfg.max_conns_per_host,
|
|
74
|
+
cfg.idle_timeout,
|
|
75
|
+
cfg.connect_timeout,
|
|
76
|
+
cfg.timeout,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
30
80
|
def _read_file_bytes(file_path: str) -> bytes:
|
|
31
81
|
with open(file_path, "rb") as f:
|
|
32
82
|
return f.read()
|
|
@@ -56,9 +106,7 @@ class ResponseParserMixin:
|
|
|
56
106
|
self, response: httpx.Response, data_type: Type[T]
|
|
57
107
|
) -> StreamResponse[T]:
|
|
58
108
|
if response.status_code >= 399:
|
|
59
|
-
raise
|
|
60
|
-
response=response,
|
|
61
|
-
)
|
|
109
|
+
raise build_api_exception(response)
|
|
62
110
|
|
|
63
111
|
try:
|
|
64
112
|
parsed_result = json.loads(response.text) if response.text else {}
|
|
@@ -72,10 +120,8 @@ class ResponseParserMixin:
|
|
|
72
120
|
else:
|
|
73
121
|
data = cast(T, parsed_result)
|
|
74
122
|
|
|
75
|
-
except (ValueError, AttributeError):
|
|
76
|
-
raise
|
|
77
|
-
response=response,
|
|
78
|
-
)
|
|
123
|
+
except (ValueError, AttributeError) as err:
|
|
124
|
+
raise StreamApiException(response=response) from err
|
|
79
125
|
|
|
80
126
|
return StreamResponse(response, data)
|
|
81
127
|
|
|
@@ -151,12 +197,17 @@ class BaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, ABC):
|
|
|
151
197
|
timeout=None,
|
|
152
198
|
user_agent=None,
|
|
153
199
|
):
|
|
200
|
+
# The 3 pool knobs (max_conns_per_host, idle_timeout, connect_timeout) are set on ``self`` by BaseStream prior to this call when used via the top-level ``Stream``/``AsyncStream`` constructors. Sub-clients constructed directly use the spec defaults via _resolve_pool_knobs.
|
|
201
|
+
max_conns_per_host, idle_timeout, connect_timeout = _resolve_pool_knobs(self)
|
|
154
202
|
super().__init__(
|
|
155
203
|
api_key=api_key,
|
|
156
204
|
base_url=base_url,
|
|
157
205
|
token=token,
|
|
158
206
|
timeout=timeout,
|
|
159
207
|
user_agent=user_agent,
|
|
208
|
+
max_conns_per_host=max_conns_per_host,
|
|
209
|
+
idle_timeout=idle_timeout,
|
|
210
|
+
connect_timeout=connect_timeout,
|
|
160
211
|
)
|
|
161
212
|
http_client = getattr(self, "_http_client", None)
|
|
162
213
|
if http_client is not None:
|
|
@@ -173,23 +224,39 @@ class BaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, ABC):
|
|
|
173
224
|
self.client = http_client
|
|
174
225
|
self._owns_http_client = False
|
|
175
226
|
else:
|
|
227
|
+
limits = httpx.Limits(
|
|
228
|
+
max_connections=self.max_conns_per_host,
|
|
229
|
+
max_keepalive_connections=self.max_conns_per_host,
|
|
230
|
+
keepalive_expiry=self.idle_timeout,
|
|
231
|
+
)
|
|
232
|
+
timeout_obj = httpx.Timeout(
|
|
233
|
+
connect=self.connect_timeout,
|
|
234
|
+
read=self.timeout,
|
|
235
|
+
write=self.timeout,
|
|
236
|
+
pool=self.timeout,
|
|
237
|
+
)
|
|
176
238
|
transport = getattr(self, "_transport", None)
|
|
177
239
|
if transport is not None:
|
|
178
240
|
self.client = httpx.Client(
|
|
179
241
|
base_url=self.base_url or "",
|
|
180
|
-
headers=self.headers,
|
|
242
|
+
headers={**self.headers, "Accept-Encoding": "gzip"},
|
|
181
243
|
params=self.params,
|
|
182
|
-
timeout=
|
|
244
|
+
timeout=timeout_obj,
|
|
245
|
+
limits=limits,
|
|
183
246
|
transport=transport,
|
|
184
247
|
)
|
|
185
248
|
else:
|
|
186
249
|
self.client = httpx.Client(
|
|
187
250
|
base_url=self.base_url or "",
|
|
188
|
-
headers=self.headers,
|
|
251
|
+
headers={**self.headers, "Accept-Encoding": "gzip"},
|
|
189
252
|
params=self.params,
|
|
190
|
-
timeout=
|
|
253
|
+
timeout=timeout_obj,
|
|
254
|
+
limits=limits,
|
|
191
255
|
)
|
|
192
256
|
self._owns_http_client = True
|
|
257
|
+
# The pool-config INFO line is emitted once by BaseStream after the
|
|
258
|
+
# top-level client is built, not here, to avoid one line per
|
|
259
|
+
# sub-client construction.
|
|
193
260
|
|
|
194
261
|
def __enter__(self):
|
|
195
262
|
return self
|
|
@@ -224,9 +291,12 @@ class BaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, ABC):
|
|
|
224
291
|
) as span:
|
|
225
292
|
call_kwargs = dict(kwargs)
|
|
226
293
|
call_kwargs.pop("path_params", None)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
294
|
+
try:
|
|
295
|
+
response = getattr(self.client, method.lower())(
|
|
296
|
+
url_path, params=query_params, *args, **call_kwargs
|
|
297
|
+
)
|
|
298
|
+
except httpx.RequestError as err:
|
|
299
|
+
raise wrap_transport_error(err) from err
|
|
230
300
|
duration = parse_duration_from_body(response.content)
|
|
231
301
|
if duration:
|
|
232
302
|
span.set_attribute("http.server.duration", duration)
|
|
@@ -376,7 +446,7 @@ class BaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, ABC):
|
|
|
376
446
|
Close HTTPX client.
|
|
377
447
|
|
|
378
448
|
If the client was provided externally via ``http_client``, this is a
|
|
379
|
-
no-op
|
|
449
|
+
no-op; the caller that created the client is responsible for closing
|
|
380
450
|
it.
|
|
381
451
|
"""
|
|
382
452
|
if getattr(self, "_owns_http_client", True):
|
|
@@ -392,12 +462,17 @@ class AsyncBaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, A
|
|
|
392
462
|
timeout=None,
|
|
393
463
|
user_agent=None,
|
|
394
464
|
):
|
|
465
|
+
# The 3 pool knobs (max_conns_per_host, idle_timeout, connect_timeout) are set on ``self`` by BaseStream prior to this call when used via the top-level ``Stream``/``AsyncStream`` constructors. Sub-clients constructed directly use the spec defaults via _resolve_pool_knobs.
|
|
466
|
+
max_conns_per_host, idle_timeout, connect_timeout = _resolve_pool_knobs(self)
|
|
395
467
|
super().__init__(
|
|
396
468
|
api_key=api_key,
|
|
397
469
|
base_url=base_url,
|
|
398
470
|
token=token,
|
|
399
471
|
timeout=timeout,
|
|
400
472
|
user_agent=user_agent,
|
|
473
|
+
max_conns_per_host=max_conns_per_host,
|
|
474
|
+
idle_timeout=idle_timeout,
|
|
475
|
+
connect_timeout=connect_timeout,
|
|
401
476
|
)
|
|
402
477
|
http_client = getattr(self, "_http_client", None)
|
|
403
478
|
if http_client is not None:
|
|
@@ -414,23 +489,39 @@ class AsyncBaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, A
|
|
|
414
489
|
self.client = http_client
|
|
415
490
|
self._owns_http_client = False
|
|
416
491
|
else:
|
|
492
|
+
limits = httpx.Limits(
|
|
493
|
+
max_connections=self.max_conns_per_host,
|
|
494
|
+
max_keepalive_connections=self.max_conns_per_host,
|
|
495
|
+
keepalive_expiry=self.idle_timeout,
|
|
496
|
+
)
|
|
497
|
+
timeout_obj = httpx.Timeout(
|
|
498
|
+
connect=self.connect_timeout,
|
|
499
|
+
read=self.timeout,
|
|
500
|
+
write=self.timeout,
|
|
501
|
+
pool=self.timeout,
|
|
502
|
+
)
|
|
417
503
|
transport = getattr(self, "_transport", None)
|
|
418
504
|
if transport is not None:
|
|
419
505
|
self.client = httpx.AsyncClient(
|
|
420
506
|
base_url=self.base_url or "",
|
|
421
|
-
headers=self.headers,
|
|
507
|
+
headers={**self.headers, "Accept-Encoding": "gzip"},
|
|
422
508
|
params=self.params,
|
|
423
|
-
timeout=
|
|
509
|
+
timeout=timeout_obj,
|
|
510
|
+
limits=limits,
|
|
424
511
|
transport=transport,
|
|
425
512
|
)
|
|
426
513
|
else:
|
|
427
514
|
self.client = httpx.AsyncClient(
|
|
428
515
|
base_url=self.base_url or "",
|
|
429
|
-
headers=self.headers,
|
|
516
|
+
headers={**self.headers, "Accept-Encoding": "gzip"},
|
|
430
517
|
params=self.params,
|
|
431
|
-
timeout=
|
|
518
|
+
timeout=timeout_obj,
|
|
519
|
+
limits=limits,
|
|
432
520
|
)
|
|
433
521
|
self._owns_http_client = True
|
|
522
|
+
# The pool-config INFO line is emitted once by BaseStream after the
|
|
523
|
+
# top-level client is built, not here, to avoid one line per
|
|
524
|
+
# sub-client construction.
|
|
434
525
|
|
|
435
526
|
async def __aenter__(self):
|
|
436
527
|
return self
|
|
@@ -442,7 +533,7 @@ class AsyncBaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, A
|
|
|
442
533
|
"""Close HTTPX async client (closes pools/keep-alives).
|
|
443
534
|
|
|
444
535
|
If the client was provided externally via ``http_client``, this is a
|
|
445
|
-
no-op
|
|
536
|
+
no-op; the caller that created the client is responsible for closing
|
|
446
537
|
it.
|
|
447
538
|
"""
|
|
448
539
|
if getattr(self, "_owns_http_client", True):
|
|
@@ -516,9 +607,12 @@ class AsyncBaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, A
|
|
|
516
607
|
call_kwargs["headers"] = call_kwargs.get("headers", {})
|
|
517
608
|
call_kwargs["headers"]["Content-Type"] = "application/json"
|
|
518
609
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
610
|
+
try:
|
|
611
|
+
response = await getattr(self.client, method.lower())(
|
|
612
|
+
url_path, params=query_params, *args, **call_kwargs
|
|
613
|
+
)
|
|
614
|
+
except httpx.RequestError as err:
|
|
615
|
+
raise wrap_transport_error(err) from err
|
|
522
616
|
duration = parse_duration_from_body(response.content)
|
|
523
617
|
if duration:
|
|
524
618
|
span.set_attribute("http.server.duration", duration)
|
|
@@ -633,54 +727,19 @@ class AsyncBaseClient(TelemetryEndpointMixin, BaseConfig, ResponseParserMixin, A
|
|
|
633
727
|
)
|
|
634
728
|
|
|
635
729
|
|
|
636
|
-
|
|
637
|
-
"""
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
controls extracted from the response headers.
|
|
650
|
-
http_response (httpx.Response): The full HTTP response object from httpx.
|
|
651
|
-
status_code (int): The HTTP status code from the response.
|
|
652
|
-
|
|
653
|
-
Args:
|
|
654
|
-
response (httpx.Response): The HTTP response received from the Stream API.
|
|
655
|
-
|
|
656
|
-
Raises:
|
|
657
|
-
ValueError: If the response content cannot be parsed into JSON, indicating
|
|
658
|
-
that the server's response was not in the expected format.
|
|
659
|
-
"""
|
|
660
|
-
|
|
661
|
-
def __init__(self, response: httpx.Response) -> None:
|
|
662
|
-
self.api_error: Optional[APIError] = None
|
|
663
|
-
self.rate_limit_info = extract_rate_limit(response)
|
|
664
|
-
self.http_response = response
|
|
665
|
-
self.status_code = response.status_code
|
|
666
|
-
|
|
667
|
-
try:
|
|
668
|
-
parsed_response: Dict = json.loads(response.content)
|
|
669
|
-
self.api_error = APIError.from_dict(parsed_response)
|
|
670
|
-
except ValueError:
|
|
671
|
-
pass
|
|
672
|
-
|
|
673
|
-
def __str__(self) -> str:
|
|
674
|
-
if self.api_error:
|
|
675
|
-
return f'Stream error code {self.api_error.code}: {self.api_error.message}"'
|
|
676
|
-
body_preview = ""
|
|
677
|
-
try:
|
|
678
|
-
text = self.http_response.text[:200] if self.http_response.text else ""
|
|
679
|
-
if text:
|
|
680
|
-
body_preview = f" body: {text}"
|
|
681
|
-
except Exception:
|
|
682
|
-
pass
|
|
683
|
-
return f"Stream error HTTP code: {self.status_code}{body_preview}"
|
|
730
|
+
def __getattr__(name: str):
|
|
731
|
+
"""StreamApiException is exported under its new name; resolve here lazily and warn once."""
|
|
732
|
+
if name == "StreamAPIException":
|
|
733
|
+
warnings.warn(
|
|
734
|
+
"getstream.base.StreamAPIException is deprecated; import "
|
|
735
|
+
"StreamApiException from getstream (or getstream.exceptions) "
|
|
736
|
+
"instead. The legacy alias will be removed one minor cycle after "
|
|
737
|
+
"this release.",
|
|
738
|
+
DeprecationWarning,
|
|
739
|
+
stacklevel=2,
|
|
740
|
+
)
|
|
741
|
+
return StreamApiException
|
|
742
|
+
raise AttributeError(f"module 'getstream.base' has no attribute {name!r}")
|
|
684
743
|
|
|
685
744
|
|
|
686
745
|
def parse_duration_from_body(body: bytes) -> Optional[str]:
|
|
@@ -282,10 +282,11 @@ class ChatRestClient(AsyncBaseClient):
|
|
|
282
282
|
self,
|
|
283
283
|
limit: Optional[int] = None,
|
|
284
284
|
user_id: Optional[str] = None,
|
|
285
|
+
groups: Optional[Dict[str, GroupedChannelsGroupRequest]] = None,
|
|
285
286
|
user: Optional[UserRequest] = None,
|
|
286
287
|
) -> StreamResponse[GroupedQueryChannelsResponse]:
|
|
287
288
|
json = GroupedQueryChannelsRequest(
|
|
288
|
-
limit=limit, user_id=user_id, user=user
|
|
289
|
+
limit=limit, user_id=user_id, groups=groups, user=user
|
|
289
290
|
).to_dict()
|
|
290
291
|
return await self.post(
|
|
291
292
|
"/api/v2/chat/channels/grouped", GroupedQueryChannelsResponse, json=json
|
|
@@ -1657,6 +1658,30 @@ class ChatRestClient(AsyncBaseClient):
|
|
|
1657
1658
|
"/api/v2/chat/search", SearchResponse, query_params=query_params
|
|
1658
1659
|
)
|
|
1659
1660
|
|
|
1661
|
+
@telemetry.operation_name("getstream.api.chat.create_segment")
|
|
1662
|
+
async def create_segment(
|
|
1663
|
+
self,
|
|
1664
|
+
type: str,
|
|
1665
|
+
all_sender_channels: Optional[bool] = None,
|
|
1666
|
+
all_users: Optional[bool] = None,
|
|
1667
|
+
description: Optional[str] = None,
|
|
1668
|
+
id: Optional[str] = None,
|
|
1669
|
+
name: Optional[str] = None,
|
|
1670
|
+
filter: Optional[Dict[str, object]] = None,
|
|
1671
|
+
) -> StreamResponse[CreateSegmentResponse]:
|
|
1672
|
+
json = CreateSegmentRequest(
|
|
1673
|
+
type=type,
|
|
1674
|
+
all_sender_channels=all_sender_channels,
|
|
1675
|
+
all_users=all_users,
|
|
1676
|
+
description=description,
|
|
1677
|
+
id=id,
|
|
1678
|
+
name=name,
|
|
1679
|
+
filter=filter,
|
|
1680
|
+
).to_dict()
|
|
1681
|
+
return await self.post(
|
|
1682
|
+
"/api/v2/chat/segments", CreateSegmentResponse, json=json
|
|
1683
|
+
)
|
|
1684
|
+
|
|
1660
1685
|
@telemetry.operation_name("getstream.api.chat.query_segments")
|
|
1661
1686
|
async def query_segments(
|
|
1662
1687
|
self,
|
|
@@ -1691,6 +1716,42 @@ class ChatRestClient(AsyncBaseClient):
|
|
|
1691
1716
|
"/api/v2/chat/segments/{id}", GetSegmentResponse, path_params=path_params
|
|
1692
1717
|
)
|
|
1693
1718
|
|
|
1719
|
+
@telemetry.operation_name("getstream.api.chat.update_segment")
|
|
1720
|
+
async def update_segment(
|
|
1721
|
+
self,
|
|
1722
|
+
id: str,
|
|
1723
|
+
description: Optional[str] = None,
|
|
1724
|
+
name: Optional[str] = None,
|
|
1725
|
+
filter: Optional[Dict[str, object]] = None,
|
|
1726
|
+
) -> StreamResponse[UpdateSegmentResponse]:
|
|
1727
|
+
path_params = {
|
|
1728
|
+
"id": id,
|
|
1729
|
+
}
|
|
1730
|
+
json = UpdateSegmentRequest(
|
|
1731
|
+
description=description, name=name, filter=filter
|
|
1732
|
+
).to_dict()
|
|
1733
|
+
return await self.put(
|
|
1734
|
+
"/api/v2/chat/segments/{id}",
|
|
1735
|
+
UpdateSegmentResponse,
|
|
1736
|
+
path_params=path_params,
|
|
1737
|
+
json=json,
|
|
1738
|
+
)
|
|
1739
|
+
|
|
1740
|
+
@telemetry.operation_name("getstream.api.chat.add_segment_targets")
|
|
1741
|
+
async def add_segment_targets(
|
|
1742
|
+
self, id: str, target_ids: List[str]
|
|
1743
|
+
) -> StreamResponse[Response]:
|
|
1744
|
+
path_params = {
|
|
1745
|
+
"id": id,
|
|
1746
|
+
}
|
|
1747
|
+
json = AddSegmentTargetsRequest(target_ids=target_ids).to_dict()
|
|
1748
|
+
return await self.post(
|
|
1749
|
+
"/api/v2/chat/segments/{id}/addtargets",
|
|
1750
|
+
Response,
|
|
1751
|
+
path_params=path_params,
|
|
1752
|
+
json=json,
|
|
1753
|
+
)
|
|
1754
|
+
|
|
1694
1755
|
@telemetry.operation_name("getstream.api.chat.delete_segment_targets")
|
|
1695
1756
|
async def delete_segment_targets(
|
|
1696
1757
|
self, id: str, target_ids: List[str]
|