getstream 3.3.4__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.
Files changed (124) hide show
  1. getstream-3.5.0/.github/workflows/release.yml +215 -0
  2. {getstream-3.3.4 → getstream-3.5.0}/.github/workflows/run_tests.yml +3 -3
  3. getstream-3.5.0/CHANGELOG.md +147 -0
  4. {getstream-3.3.4 → getstream-3.5.0}/Makefile +4 -2
  5. {getstream-3.3.4 → getstream-3.5.0}/PKG-INFO +24 -5
  6. {getstream-3.3.4 → getstream-3.5.0}/README.md +18 -1
  7. {getstream-3.3.4 → getstream-3.5.0}/generate.sh +4 -1
  8. getstream-3.5.0/getstream/__init__.py +9 -0
  9. {getstream-3.3.4 → getstream-3.5.0}/getstream/base.py +132 -73
  10. {getstream-3.3.4 → getstream-3.5.0}/getstream/chat/async_rest_client.py +169 -0
  11. {getstream-3.3.4 → getstream-3.5.0}/getstream/chat/rest_client.py +165 -0
  12. {getstream-3.3.4 → getstream-3.5.0}/getstream/common/async_rest_client.py +53 -0
  13. {getstream-3.3.4 → getstream-3.5.0}/getstream/common/rest_client.py +53 -0
  14. {getstream-3.3.4 → getstream-3.5.0}/getstream/config.py +7 -0
  15. getstream-3.5.0/getstream/exceptions.py +326 -0
  16. {getstream-3.3.4 → getstream-3.5.0}/getstream/feeds/feeds.py +25 -2
  17. {getstream-3.3.4 → getstream-3.5.0}/getstream/feeds/rest_client.py +292 -16
  18. {getstream-3.3.4 → getstream-3.5.0}/getstream/models/__init__.py +2885 -209
  19. {getstream-3.3.4 → getstream-3.5.0}/getstream/moderation/async_rest_client.py +291 -8
  20. {getstream-3.3.4 → getstream-3.5.0}/getstream/moderation/rest_client.py +291 -8
  21. getstream-3.5.0/getstream/stream.py +702 -0
  22. getstream-3.5.0/getstream/tasks.py +104 -0
  23. {getstream-3.3.4 → getstream-3.5.0}/getstream/tests/test_webhook.py +168 -0
  24. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/async_rest_client.py +29 -0
  25. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rest_client.py +29 -0
  26. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/connection_manager.py +2 -0
  27. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/connection_utils.py +26 -31
  28. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/coordinator/ws.py +3 -9
  29. {getstream-3.3.4 → getstream-3.5.0}/getstream/webhook.py +242 -3
  30. {getstream-3.3.4 → getstream-3.5.0}/pyproject.toml +8 -9
  31. {getstream-3.3.4 → getstream-3.5.0}/pytest.ini +2 -0
  32. {getstream-3.3.4 → getstream-3.5.0}/uv.lock +216 -10
  33. getstream-3.3.4/.github/workflows/release.yml +0 -60
  34. getstream-3.3.4/CHANGELOG.md +0 -34
  35. getstream-3.3.4/getstream/__init__.py +0 -2
  36. getstream-3.3.4/getstream/stream.py +0 -411
  37. getstream-3.3.4/getstream/video/rtc/coordinator_api.py +0 -81
  38. {getstream-3.3.4 → getstream-3.5.0}/.cursor/worktrees.json +0 -0
  39. {getstream-3.3.4 → getstream-3.5.0}/.env.example +0 -0
  40. {getstream-3.3.4 → getstream-3.5.0}/.github/actions/python-uv-setup/action.yml +0 -0
  41. {getstream-3.3.4 → getstream-3.5.0}/.github/workflows/ci.yml +0 -0
  42. {getstream-3.3.4 → getstream-3.5.0}/.github/workflows/stream-py.code-workspace +0 -0
  43. {getstream-3.3.4 → getstream-3.5.0}/.gitignore +0 -0
  44. {getstream-3.3.4 → getstream-3.5.0}/.gitmodules +0 -0
  45. {getstream-3.3.4 → getstream-3.5.0}/.pre-commit-config.yaml +0 -0
  46. {getstream-3.3.4 → getstream-3.5.0}/AGENTS.md +0 -0
  47. {getstream-3.3.4 → getstream-3.5.0}/DEVELOPMENT.md +0 -0
  48. {getstream-3.3.4 → getstream-3.5.0}/LICENSE.md +0 -0
  49. {getstream-3.3.4 → getstream-3.5.0}/MIGRATION_v2_to_v3.md +0 -0
  50. {getstream-3.3.4 → getstream-3.5.0}/dev.py +0 -0
  51. {getstream-3.3.4 → getstream-3.5.0}/docs/migration-from-stream-chat-python/01-setup-and-auth.md +0 -0
  52. {getstream-3.3.4 → getstream-3.5.0}/docs/migration-from-stream-chat-python/02-users.md +0 -0
  53. {getstream-3.3.4 → getstream-3.5.0}/docs/migration-from-stream-chat-python/03-channels.md +0 -0
  54. {getstream-3.3.4 → getstream-3.5.0}/docs/migration-from-stream-chat-python/04-messages-and-reactions.md +0 -0
  55. {getstream-3.3.4 → getstream-3.5.0}/docs/migration-from-stream-chat-python/05-moderation.md +0 -0
  56. {getstream-3.3.4 → getstream-3.5.0}/docs/migration-from-stream-chat-python/06-devices.md +0 -0
  57. {getstream-3.3.4 → getstream-3.5.0}/docs/migration-from-stream-chat-python/README.md +0 -0
  58. {getstream-3.3.4 → getstream-3.5.0}/generate_webrtc.sh +0 -0
  59. {getstream-3.3.4 → getstream-3.5.0}/getstream/chat/__init__.py +0 -0
  60. {getstream-3.3.4 → getstream-3.5.0}/getstream/chat/async_channel.py +0 -0
  61. {getstream-3.3.4 → getstream-3.5.0}/getstream/chat/async_client.py +0 -0
  62. {getstream-3.3.4 → getstream-3.5.0}/getstream/chat/channel.py +0 -0
  63. {getstream-3.3.4 → getstream-3.5.0}/getstream/chat/client.py +0 -0
  64. {getstream-3.3.4 → getstream-3.5.0}/getstream/common/__init__.py +0 -0
  65. {getstream-3.3.4 → getstream-3.5.0}/getstream/common/async_client.py +0 -0
  66. {getstream-3.3.4 → getstream-3.5.0}/getstream/common/client.py +0 -0
  67. {getstream-3.3.4 → getstream-3.5.0}/getstream/common/telemetry.py +0 -0
  68. {getstream-3.3.4 → getstream-3.5.0}/getstream/feeds/__init__.py +0 -0
  69. {getstream-3.3.4 → getstream-3.5.0}/getstream/feeds/client.py +0 -0
  70. {getstream-3.3.4 → getstream-3.5.0}/getstream/generic.py +0 -0
  71. {getstream-3.3.4 → getstream-3.5.0}/getstream/meta.py +0 -0
  72. {getstream-3.3.4 → getstream-3.5.0}/getstream/moderation/__init__.py +0 -0
  73. {getstream-3.3.4 → getstream-3.5.0}/getstream/moderation/async_client.py +0 -0
  74. {getstream-3.3.4 → getstream-3.5.0}/getstream/moderation/client.py +0 -0
  75. {getstream-3.3.4 → getstream-3.5.0}/getstream/rate_limit.py +0 -0
  76. {getstream-3.3.4 → getstream-3.5.0}/getstream/stream_response.py +0 -0
  77. {getstream-3.3.4 → getstream-3.5.0}/getstream/utils/__init__.py +0 -0
  78. {getstream-3.3.4 → getstream-3.5.0}/getstream/utils/event_emitter.py +0 -0
  79. {getstream-3.3.4 → getstream-3.5.0}/getstream/utils/retry.py +0 -0
  80. {getstream-3.3.4 → getstream-3.5.0}/getstream/version.py +0 -0
  81. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/__init__.py +0 -0
  82. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/async_call.py +0 -0
  83. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/async_client.py +0 -0
  84. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/call.py +0 -0
  85. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/client.py +0 -0
  86. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/openai.py +0 -0
  87. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/README.md +0 -0
  88. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/__init__.py +0 -0
  89. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/audio_track.py +0 -0
  90. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/coordinator/__init__.py +0 -0
  91. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/coordinator/backoff.py +0 -0
  92. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/coordinator/errors.py +0 -0
  93. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/encoders_patches.py +0 -0
  94. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/g711.py +0 -0
  95. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/location_discovery.py +0 -0
  96. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/models.py +0 -0
  97. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/network_monitor.py +0 -0
  98. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/participants.py +0 -0
  99. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/__init__.py +0 -0
  100. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/__init__.py +0 -0
  101. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/__init__.py +0 -0
  102. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/__init__.py +0 -0
  103. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/event/__init__.py +0 -0
  104. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.py +0 -0
  105. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.pyi +0 -0
  106. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/models/__init__.py +0 -0
  107. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.py +0 -0
  108. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.pyi +0 -0
  109. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/__init__.py +0 -0
  110. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.py +0 -0
  111. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.pyi +0 -0
  112. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_twirp.py +0 -0
  113. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/pc.py +0 -0
  114. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/peer_connection.py +0 -0
  115. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/reconnection.py +0 -0
  116. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/recording.py +0 -0
  117. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/signaling.py +0 -0
  118. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/stats_reporter.py +0 -0
  119. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/stats_tracer.py +0 -0
  120. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/tracer.py +0 -0
  121. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/track_util.py +0 -0
  122. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/tracks.py +0 -0
  123. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/twirp_client_wrapper.py +0 -0
  124. {getstream-3.3.4 → getstream-3.5.0}/getstream/video/rtc/utils.py +0 -0
@@ -0,0 +1,215 @@
1
+ name: Release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ version_bump:
7
+ description: 'Version bump type for manual release'
8
+ required: true
9
+ default: 'patch'
10
+ type: choice
11
+ options:
12
+ - patch
13
+ - minor
14
+ - major
15
+ use_current_version:
16
+ description: 'Skip version bump and publish the version already set in pyproject.toml'
17
+ required: false
18
+ default: false
19
+ type: boolean
20
+ pull_request:
21
+ types: [closed]
22
+ branches:
23
+ - main
24
+
25
+ concurrency:
26
+ group: release-${{ github.event.pull_request.base.ref || github.ref_name }}
27
+ cancel-in-progress: false
28
+
29
+ permissions:
30
+ contents: read
31
+
32
+ jobs:
33
+ prepare:
34
+ name: Prepare release
35
+ if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true
36
+ runs-on: ubuntu-latest
37
+ outputs:
38
+ should_release: ${{ steps.release_meta_final.outputs.should_release }}
39
+ bump: ${{ steps.release_meta_final.outputs.bump }}
40
+ previous_version: ${{ steps.release_meta_final.outputs.previous_version }}
41
+ version: ${{ steps.release_meta_final.outputs.version }}
42
+ tag: ${{ steps.release_meta_final.outputs.tag }}
43
+ steps:
44
+ - uses: actions/checkout@v5
45
+ with:
46
+ fetch-depth: 0
47
+ ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref || github.ref_name }}
48
+
49
+ - name: Skip when PR is already released
50
+ id: already_released
51
+ run: |
52
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
53
+ echo "value=false" >> "$GITHUB_OUTPUT"
54
+ else
55
+ if git log --oneline --grep="(pr #${{ github.event.pull_request.number }})" -n 1 | grep -q "chore(release):"; then
56
+ echo "value=true" >> "$GITHUB_OUTPUT"
57
+ else
58
+ echo "value=false" >> "$GITHUB_OUTPUT"
59
+ fi
60
+ fi
61
+
62
+ - name: Determine version bump (from PR metadata)
63
+ id: release_meta
64
+ if: github.event_name == 'pull_request' && steps.already_released.outputs.value != 'true'
65
+ env:
66
+ PR_TITLE: ${{ github.event.pull_request.title }}
67
+ run: |
68
+ python3 scripts/release/bump_version.py \
69
+ --title "$PR_TITLE" \
70
+ --output "$GITHUB_OUTPUT"
71
+
72
+ - name: Determine version bump (manual)
73
+ id: release_meta_manual
74
+ if: github.event_name == 'workflow_dispatch'
75
+ run: |
76
+ python3 scripts/release/bump_version.py \
77
+ --manual-bump "${{ github.event.inputs.version_bump }}" \
78
+ --use-current-version "${{ github.event.inputs.use_current_version }}" \
79
+ --output "$GITHUB_OUTPUT"
80
+
81
+ - name: Consolidate release metadata
82
+ id: release_meta_final
83
+ run: |
84
+ if [ "${{ steps.already_released.outputs.value }}" = "true" ]; then
85
+ echo "should_release=false" >> "$GITHUB_OUTPUT"
86
+ echo "bump=none" >> "$GITHUB_OUTPUT"
87
+ exit 0
88
+ fi
89
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
90
+ echo "should_release=${{ steps.release_meta_manual.outputs.should_release }}" >> "$GITHUB_OUTPUT"
91
+ echo "bump=${{ steps.release_meta_manual.outputs.bump }}" >> "$GITHUB_OUTPUT"
92
+ echo "previous_version=${{ steps.release_meta_manual.outputs.previous_version }}" >> "$GITHUB_OUTPUT"
93
+ echo "version=${{ steps.release_meta_manual.outputs.version }}" >> "$GITHUB_OUTPUT"
94
+ echo "tag=${{ steps.release_meta_manual.outputs.tag }}" >> "$GITHUB_OUTPUT"
95
+ else
96
+ echo "should_release=${{ steps.release_meta.outputs.should_release }}" >> "$GITHUB_OUTPUT"
97
+ echo "bump=${{ steps.release_meta.outputs.bump }}" >> "$GITHUB_OUTPUT"
98
+ echo "previous_version=${{ steps.release_meta.outputs.previous_version }}" >> "$GITHUB_OUTPUT"
99
+ echo "version=${{ steps.release_meta.outputs.version }}" >> "$GITHUB_OUTPUT"
100
+ echo "tag=${{ steps.release_meta.outputs.tag }}" >> "$GITHUB_OUTPUT"
101
+ fi
102
+
103
+ test-unit:
104
+ name: Test (unit)
105
+ needs: prepare
106
+ if: needs.prepare.outputs.should_release == 'true'
107
+ uses: ./.github/workflows/run_tests.yml
108
+ with:
109
+ marker: 'not integration'
110
+ secrets: inherit
111
+
112
+ test-integration:
113
+ name: Test (integration)
114
+ needs: prepare
115
+ if: needs.prepare.outputs.should_release == 'true'
116
+ uses: ./.github/workflows/run_tests.yml
117
+ with:
118
+ marker: 'integration'
119
+ secrets: inherit
120
+
121
+ release:
122
+ name: 🚀 Release
123
+ needs: [prepare, test-unit, test-integration]
124
+ if: needs.prepare.outputs.should_release == 'true'
125
+ runs-on: ubuntu-latest
126
+ environment: pypi
127
+ permissions:
128
+ contents: write
129
+ id-token: write
130
+ steps:
131
+ - uses: actions/checkout@v5
132
+ with:
133
+ fetch-depth: 0
134
+ ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref || github.ref_name }}
135
+
136
+ - uses: ./.github/actions/python-uv-setup
137
+
138
+ - name: Apply version bump
139
+ env:
140
+ VERSION: ${{ needs.prepare.outputs.version }}
141
+ run: |
142
+ python3 - <<'PY'
143
+ import os, re
144
+ from pathlib import Path
145
+ version = os.environ['VERSION']
146
+ path = Path('pyproject.toml')
147
+ text = path.read_text(encoding='utf-8')
148
+ pattern = re.compile(r'^version\s*=\s*"\d+\.\d+\.\d+"\s*$', re.MULTILINE)
149
+ new_text, count = pattern.subn(f'version = "{version}"', text, count=1)
150
+ if count == 0:
151
+ raise SystemExit('Could not update version line in pyproject.toml')
152
+ path.write_text(new_text, encoding='utf-8')
153
+ PY
154
+
155
+ - name: Commit version bump
156
+ env:
157
+ VERSION: ${{ needs.prepare.outputs.version }}
158
+ run: |
159
+ git config user.name "github-actions[bot]"
160
+ git config user.email "github-actions[bot]@users.noreply.github.com"
161
+ git add pyproject.toml
162
+ if git diff --cached --quiet; then
163
+ echo "No version changes to commit."
164
+ exit 0
165
+ fi
166
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
167
+ git commit -m "chore(release): v${VERSION} (manual)"
168
+ git push origin "HEAD:${{ github.ref_name }}"
169
+ else
170
+ git commit -m "chore(release): v${VERSION} (pr #${{ github.event.pull_request.number }})"
171
+ git push origin "HEAD:${{ github.event.pull_request.base.ref }}"
172
+ fi
173
+
174
+ - name: Create release tag
175
+ env:
176
+ TAG: ${{ needs.prepare.outputs.tag }}
177
+ run: |
178
+ if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
179
+ echo "Tag ${TAG} already exists; skipping tag creation."
180
+ exit 0
181
+ fi
182
+ git tag "${TAG}"
183
+ git push origin "${TAG}"
184
+
185
+ - name: Clean dist directory
186
+ run: rm -rf dist
187
+
188
+ - name: Build distributions
189
+ run: uv build
190
+
191
+ - name: Publish to PyPI (Trusted Publishing)
192
+ run: uv publish
193
+
194
+ - name: Create release on GitHub
195
+ uses: ncipollo/release-action@v1
196
+ with:
197
+ tag: ${{ needs.prepare.outputs.tag }}
198
+ token: ${{ secrets.GITHUB_TOKEN }}
199
+ skipIfReleaseExists: true
200
+ body: |
201
+ Release v${{ needs.prepare.outputs.version }}
202
+
203
+ - Bump type: `${{ needs.prepare.outputs.bump }}`
204
+ - Previous: `${{ needs.prepare.outputs.previous_version }}`
205
+ - Next: `${{ needs.prepare.outputs.version }}`
206
+ - Trigger: `${{ github.event_name }}`
207
+
208
+ Install with: `pip install getstream==${{ needs.prepare.outputs.version }}`
209
+
210
+ - name: Verify pip install
211
+ env:
212
+ UV_NO_SOURCES: "1"
213
+ run: |
214
+ uv pip install "getstream==${{ needs.prepare.outputs.version }}" || \
215
+ echo "WARNING: pip install verification failed (PyPI index may need a moment to propagate)"
@@ -8,7 +8,7 @@ on:
8
8
  type: string
9
9
  secrets: { }
10
10
  concurrency:
11
- group: ${{ github.workflow }}-${{ github.ref }}
11
+ group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.marker }}
12
12
  cancel-in-progress: true
13
13
 
14
14
  env:
@@ -49,7 +49,7 @@ jobs:
49
49
  strategy:
50
50
  fail-fast: false
51
51
  matrix:
52
- python-version: ["3.10", "3.11", "3.12", "3.13"]
52
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
53
53
  timeout-minutes: 30
54
54
  steps:
55
55
  - name: Checkout
@@ -75,7 +75,7 @@ jobs:
75
75
  strategy:
76
76
  fail-fast: false
77
77
  matrix:
78
- python-version: ["3.10", "3.11", "3.12", "3.13"]
78
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
79
79
  timeout-minutes: 30
80
80
  steps:
81
81
  - name: Checkout
@@ -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
@@ -56,11 +56,13 @@ TY_EXCLUDES := \
56
56
 
57
57
  ## Run non-video tests (chat, feeds, moderation, etc.)
58
58
  test:
59
- uv run pytest -m "$(MARKER)" tests/ getstream/ $(VIDEO_IGNORE) $(MANUAL_IGNORE)
59
+ @uv run pytest -m "$(MARKER)" tests/ getstream/ $(VIDEO_IGNORE) $(MANUAL_IGNORE); \
60
+ ec=$$?; if [ $$ec -eq 5 ]; then echo "No tests matched marker '$(MARKER)' — treating as success."; exit 0; else exit $$ec; fi
60
61
 
61
62
  ## Run video/WebRTC tests only
62
63
  test-video:
63
- uv run pytest -m "$(MARKER)" $(VIDEO_PATHS)
64
+ @uv run pytest -m "$(MARKER)" $(VIDEO_PATHS); \
65
+ ec=$$?; if [ $$ec -eq 5 ]; then echo "No tests matched marker '$(MARKER)' — treating as success."; exit 0; else exit $$ec; fi
64
66
 
65
67
  ## Run all tests (non-video + video), excluding manual tests
66
68
  test-all:
@@ -1,15 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: getstream
3
- Version: 3.3.4
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
7
7
  Classifier: Programming Language :: Python :: 3
8
- Classifier: Programming Language :: Python :: 3.9
9
8
  Classifier: Programming Language :: Python :: 3.10
10
9
  Classifier: Programming Language :: Python :: 3.11
11
10
  Classifier: Programming Language :: Python :: 3.12
12
11
  Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
13
  Requires-Python: <4.0.0,>=3.10
14
14
  Requires-Dist: dataclasses-json<0.7,>=0.6.0
15
15
  Requires-Dist: httpx>=0.28.1
@@ -31,13 +31,15 @@ Provides-Extra: webrtc
31
31
  Requires-Dist: aiohttp<4,>=3.13.2; extra == 'webrtc'
32
32
  Requires-Dist: aiortc<1.15.0,>=1.14.0; extra == 'webrtc'
33
33
  Requires-Dist: av<17,>=14.2.0; extra == 'webrtc'
34
- Requires-Dist: numpy<2.3,>=2.2.6; extra == 'webrtc'
34
+ Requires-Dist: numpy<2.3,>=2.2.6; (python_version < '3.14') and extra == 'webrtc'
35
+ Requires-Dist: numpy<2.4,>=2.3.2; (python_version >= '3.14') and extra == 'webrtc'
35
36
  Requires-Dist: numpy>=2.2.6; extra == 'webrtc'
36
37
  Requires-Dist: ping3>=4.0.8; extra == 'webrtc'
37
38
  Requires-Dist: protobuf>=4.25.1; extra == 'webrtc'
38
39
  Requires-Dist: protobuf>=6.31.1; extra == 'webrtc'
39
40
  Requires-Dist: python-dateutil>=2.8.2; extra == 'webrtc'
40
- Requires-Dist: scipy<1.16,>=1.15.3; extra == 'webrtc'
41
+ Requires-Dist: scipy<1.16,>=1.15.3; (python_version < '3.14') and extra == 'webrtc'
42
+ Requires-Dist: scipy<1.17,>=1.16.1; (python_version >= '3.14') and extra == 'webrtc'
41
43
  Requires-Dist: scipy>=1.15.3; extra == 'webrtc'
42
44
  Requires-Dist: soundfile>=0.13.1; extra == 'webrtc'
43
45
  Requires-Dist: structlog<24; extra == 'webrtc'
@@ -175,7 +177,7 @@ We use [uv](https://github.com/astral-sh/uv) to manage dependencies and run test
175
177
  ### 🚀 Quick Start
176
178
 
177
179
  **Prerequisites:**
178
- - Python 3.9+ (recommended: 3.12.2)
180
+ - Python 3.10+ (recommended: 3.12.2)
179
181
  - [uv](https://github.com/astral-sh/uv) package manager
180
182
 
181
183
  **Setup:**
@@ -280,6 +282,23 @@ uv run pytest -v -s
280
282
  uv run pytest tests/test_video.py::test_specific_function -v
281
283
  ```
282
284
 
285
+ ## Releases
286
+
287
+ Releases use two paths:
288
+
289
+ - **Default**: automatic release when a PR is merged to `main`. The PR title (and body) drives the semver bump.
290
+ - **Fallback**: manual release via the `Release` workflow's `workflow_dispatch` (admin use). Select a `version_bump` (`patch`/`minor`/`major`). `use_current_version=true` skips the bump and publishes whatever is already in `pyproject.toml`.
291
+
292
+ Automatic semver bump rules:
293
+
294
+ - `feat:` -> minor
295
+ - `fix:` (or `bug:`) -> patch
296
+ - `feat!:`, `<type>(scope)!:`, or `BREAKING CHANGE` in the PR body/title -> major
297
+
298
+ PRs with any other prefix do not trigger a release.
299
+
300
+ The release pipeline runs lint, type-check, and the full test matrix (unit + integration, across all supported Python versions) on the merged commit before publishing to PyPI via Trusted Publishing (OIDC). Each step in the publish job is idempotent: a failed run can be re-dispatched from the Actions UI.
301
+
283
302
  ## License
284
303
 
285
304
  This project is licensed under the [MIT License](LICENSE).
@@ -125,7 +125,7 @@ We use [uv](https://github.com/astral-sh/uv) to manage dependencies and run test
125
125
  ### 🚀 Quick Start
126
126
 
127
127
  **Prerequisites:**
128
- - Python 3.9+ (recommended: 3.12.2)
128
+ - Python 3.10+ (recommended: 3.12.2)
129
129
  - [uv](https://github.com/astral-sh/uv) package manager
130
130
 
131
131
  **Setup:**
@@ -230,6 +230,23 @@ uv run pytest -v -s
230
230
  uv run pytest tests/test_video.py::test_specific_function -v
231
231
  ```
232
232
 
233
+ ## Releases
234
+
235
+ Releases use two paths:
236
+
237
+ - **Default**: automatic release when a PR is merged to `main`. The PR title (and body) drives the semver bump.
238
+ - **Fallback**: manual release via the `Release` workflow's `workflow_dispatch` (admin use). Select a `version_bump` (`patch`/`minor`/`major`). `use_current_version=true` skips the bump and publishes whatever is already in `pyproject.toml`.
239
+
240
+ Automatic semver bump rules:
241
+
242
+ - `feat:` -> minor
243
+ - `fix:` (or `bug:`) -> patch
244
+ - `feat!:`, `<type>(scope)!:`, or `BREAKING CHANGE` in the PR body/title -> major
245
+
246
+ PRs with any other prefix do not trigger a release.
247
+
248
+ The release pipeline runs lint, type-check, and the full test matrix (unit + integration, across all supported Python versions) on the merged commit before publishing to PyPI via Trusted Publishing (OIDC). Each step in the publish job is idempotent: a failed run can be re-dispatched from the Actions UI.
249
+
233
250
  ## License
234
251
 
235
252
  This project is licensed under the [MIT License](LICENSE).
@@ -17,7 +17,10 @@ fi
17
17
  set -ex
18
18
 
19
19
  # cd in API repo, generate new spec and then generate code from it
20
- ( cd $SOURCE_PATH ; make openapi ; go run ./cmd/chat-manager openapi generate-client --language python --spec ./releases/v2/serverside-api.yaml --output ../stream-py/getstream/ )
20
+ ( cd $SOURCE_PATH ; make openapi ; ./build/chat-manager openapi generate-client --language python --spec ./releases/v2/serverside-api.yaml --output ../stream-py/getstream/ )
21
+
22
+ # Regenerate webhook conformance fixtures (CHA-2961)
23
+ ( cd $SOURCE_PATH ; ./build/chat-manager openapi generate-webhook-fixtures --output ../stream-py/tests/assets/webhooks --time-format=unix-ns )
21
24
 
22
25
  # lint + auto-fix, then format generated code with ruff (align with pre-commit)
23
26
  uv run ruff check --fix getstream/ tests/
@@ -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