Skip to content

Commit aecc0ce

Browse files
committed
refactor: centralize shared HTTP client logic in stream.py
Move _apply_shared_client into BaseStream so sub-client files need zero HTTP-related changes. Remove _resolve_http_client from BaseClient/AsyncBaseClient. Made-with: Cursor
1 parent 87378dd commit aecc0ce

9 files changed

Lines changed: 83 additions & 79 deletions

File tree

getstream/base.py

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def __init__(
158158
timeout=timeout,
159159
user_agent=user_agent,
160160
)
161-
http_client = self._resolve_http_client()
161+
http_client = getattr(self, "_http_client", None)
162162
if http_client is not None:
163163
if not isinstance(http_client, httpx.Client):
164164
raise TypeError(
@@ -185,18 +185,6 @@ def __init__(
185185
self.client = httpx.Client(**client_kwargs)
186186
self._owns_http_client = True
187187

188-
def _resolve_http_client(self):
189-
"""Return a pre-built httpx client if one was provided, checking both
190-
the instance attribute (set by BaseStream) and the parent stream
191-
back-reference (set by sub-clients like VideoClient)."""
192-
client = getattr(self, "_http_client", None)
193-
if client is not None:
194-
return client
195-
stream = getattr(self, "stream", None)
196-
if stream is not None:
197-
return getattr(stream, "_shared_client", None)
198-
return None
199-
200188
def __enter__(self):
201189
return self
202190

@@ -405,7 +393,7 @@ def __init__(
405393
timeout=timeout,
406394
user_agent=user_agent,
407395
)
408-
http_client = self._resolve_http_client()
396+
http_client = getattr(self, "_http_client", None)
409397
if http_client is not None:
410398
if not isinstance(http_client, httpx.AsyncClient):
411399
raise TypeError(
@@ -432,15 +420,6 @@ def __init__(
432420
self.client = httpx.AsyncClient(**client_kwargs)
433421
self._owns_http_client = True
434422

435-
def _resolve_http_client(self):
436-
client = getattr(self, "_http_client", None)
437-
if client is not None:
438-
return client
439-
stream = getattr(self, "stream", None)
440-
if stream is not None:
441-
return getattr(stream, "_shared_client", None)
442-
return None
443-
444423
async def __aenter__(self):
445424
return self
446425

getstream/chat/async_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515

1616
class ChatClient(ChatRestClient):
1717
def __init__(self, api_key: str, base_url, token, timeout, stream, user_agent=None):
18-
self.stream = stream
1918
super().__init__(
2019
api_key=api_key,
2120
base_url=base_url,
2221
token=token,
2322
timeout=timeout,
2423
user_agent=user_agent,
2524
)
25+
self.stream = stream
2626

2727
def channel(self, call_type: str, id: str) -> Channel:
2828
return Channel(self, call_type, id)

getstream/chat/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515

1616
class ChatClient(ChatRestClient):
1717
def __init__(self, api_key: str, base_url, token, timeout, stream, user_agent=None):
18-
self.stream = stream
1918
super().__init__(
2019
api_key=api_key,
2120
base_url=base_url,
2221
token=token,
2322
timeout=timeout,
2423
user_agent=user_agent,
2524
)
25+
self.stream = stream
2626

2727
def channel(self, call_type: str, id: str) -> Channel:
2828
return Channel(self, call_type, id)

getstream/feeds/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55

66
class FeedsClient(FeedsRestClient):
77
def __init__(self, api_key: str, base_url, token, timeout, stream, user_agent=None):
8-
self.stream = stream
98
super().__init__(
109
api_key=api_key,
1110
base_url=base_url,
1211
token=token,
1312
timeout=timeout,
1413
user_agent=user_agent,
1514
)
15+
self.stream = stream
1616

1717
def feed(
1818
self, feed_type: str, feed_id: str, custom_data: Optional[Dict] = None

getstream/moderation/async_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
class ModerationClient(ModerationRestClient):
55
def __init__(self, api_key: str, base_url, token, timeout, stream, user_agent=None):
6-
self.stream = stream
76
super().__init__(
87
api_key=api_key,
98
base_url=base_url,
109
token=token,
1110
timeout=timeout,
1211
user_agent=user_agent,
1312
)
13+
self.stream = stream

getstream/moderation/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
class ModerationClient(ModerationRestClient):
55
def __init__(self, api_key: str, base_url, token, timeout, stream, user_agent=None):
6-
self.stream = stream
76
super().__init__(
87
api_key=api_key,
98
base_url=base_url,
109
token=token,
1110
timeout=timeout,
1211
user_agent=user_agent,
1312
)
13+
self.stream = stream

getstream/stream.py

Lines changed: 74 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from typing import List, Optional
77
from uuid import uuid4
88

9+
import httpx
910
import jwt
1011
from pydantic_settings import BaseSettings, SettingsConfigDict
1112

@@ -87,6 +88,16 @@ def __init__(
8788
else:
8889
self._shared_client = None
8990

91+
def _apply_shared_client(self, sub_client):
92+
"""Replace a sub-client's auto-created httpx client with the shared
93+
one built from user-provided transport/http_client config."""
94+
if self._shared_client is not None:
95+
if isinstance(sub_client.client, httpx.Client):
96+
sub_client.client.close()
97+
sub_client.client = self._shared_client
98+
sub_client._owns_http_client = False
99+
return sub_client
100+
90101
def create_token(
91102
self,
92103
user_id: str,
@@ -183,13 +194,15 @@ def video(self) -> AsyncVideoClient:
183194
Video stream client.
184195
185196
"""
186-
return AsyncVideoClient(
187-
api_key=self.api_key,
188-
base_url=self.base_url,
189-
token=self.token,
190-
timeout=self.timeout,
191-
stream=self,
192-
user_agent=self.user_agent,
197+
return self._apply_shared_client(
198+
AsyncVideoClient(
199+
api_key=self.api_key,
200+
base_url=self.base_url,
201+
token=self.token,
202+
timeout=self.timeout,
203+
stream=self,
204+
user_agent=self.user_agent,
205+
)
193206
)
194207

195208
@cached_property
@@ -198,13 +211,15 @@ def chat(self) -> AsyncChatClient:
198211
Chat stream client.
199212
200213
"""
201-
return AsyncChatClient(
202-
api_key=self.api_key,
203-
base_url=self.base_url,
204-
token=self.token,
205-
timeout=self.timeout,
206-
stream=self,
207-
user_agent=self.user_agent,
214+
return self._apply_shared_client(
215+
AsyncChatClient(
216+
api_key=self.api_key,
217+
base_url=self.base_url,
218+
token=self.token,
219+
timeout=self.timeout,
220+
stream=self,
221+
user_agent=self.user_agent,
222+
)
208223
)
209224

210225
@cached_property
@@ -213,13 +228,15 @@ def moderation(self) -> AsyncModerationClient:
213228
Moderation stream client.
214229
215230
"""
216-
return AsyncModerationClient(
217-
api_key=self.api_key,
218-
base_url=self.base_url,
219-
token=self.token,
220-
timeout=self.timeout,
221-
stream=self,
222-
user_agent=self.user_agent,
231+
return self._apply_shared_client(
232+
AsyncModerationClient(
233+
api_key=self.api_key,
234+
base_url=self.base_url,
235+
token=self.token,
236+
timeout=self.timeout,
237+
stream=self,
238+
user_agent=self.user_agent,
239+
)
223240
)
224241

225242
async def aclose(self):
@@ -305,13 +322,15 @@ def video(self) -> VideoClient:
305322
Video stream client.
306323
307324
"""
308-
return VideoClient(
309-
api_key=self.api_key,
310-
base_url=self.base_url,
311-
token=self.token,
312-
timeout=self.timeout,
313-
stream=self,
314-
user_agent=self.user_agent,
325+
return self._apply_shared_client(
326+
VideoClient(
327+
api_key=self.api_key,
328+
base_url=self.base_url,
329+
token=self.token,
330+
timeout=self.timeout,
331+
stream=self,
332+
user_agent=self.user_agent,
333+
)
315334
)
316335

317336
@cached_property
@@ -320,13 +339,15 @@ def chat(self) -> ChatClient:
320339
Chat stream client.
321340
322341
"""
323-
return ChatClient(
324-
api_key=self.api_key,
325-
base_url=self.base_url,
326-
token=self.token,
327-
timeout=self.timeout,
328-
stream=self,
329-
user_agent=self.user_agent,
342+
return self._apply_shared_client(
343+
ChatClient(
344+
api_key=self.api_key,
345+
base_url=self.base_url,
346+
token=self.token,
347+
timeout=self.timeout,
348+
stream=self,
349+
user_agent=self.user_agent,
350+
)
330351
)
331352

332353
@cached_property
@@ -335,13 +356,15 @@ def moderation(self) -> ModerationClient:
335356
Moderation stream client.
336357
337358
"""
338-
return ModerationClient(
339-
api_key=self.api_key,
340-
base_url=self.base_url,
341-
token=self.token,
342-
timeout=self.timeout,
343-
stream=self,
344-
user_agent=self.user_agent,
359+
return self._apply_shared_client(
360+
ModerationClient(
361+
api_key=self.api_key,
362+
base_url=self.base_url,
363+
token=self.token,
364+
timeout=self.timeout,
365+
stream=self,
366+
user_agent=self.user_agent,
367+
)
345368
)
346369

347370
@cached_property
@@ -350,13 +373,15 @@ def feeds(self) -> FeedsClient:
350373
Feeds stream client.
351374
352375
"""
353-
return FeedsClient(
354-
api_key=self.api_key,
355-
base_url=self.base_url,
356-
token=self.token,
357-
timeout=self.timeout,
358-
stream=self,
359-
user_agent=self.user_agent,
376+
return self._apply_shared_client(
377+
FeedsClient(
378+
api_key=self.api_key,
379+
base_url=self.base_url,
380+
token=self.token,
381+
timeout=self.timeout,
382+
stream=self,
383+
user_agent=self.user_agent,
384+
)
360385
)
361386

362387
@telemetry.operation_name("getstream.api.common.create_user")

getstream/video/async_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ def __init__(self, api_key: str, base_url, token, timeout, stream, user_agent=No
1212
:param timeout: A number representing the time limit for a request
1313
:param user_agent: Optional custom user agent string
1414
"""
15-
self.stream = stream
1615
super().__init__(
1716
api_key=api_key,
1817
base_url=base_url,
1918
token=token,
2019
timeout=timeout,
2120
user_agent=user_agent,
2221
)
22+
self.stream = stream
2323

2424
def call(self, call_type: str, id: str) -> Call:
2525
return Call(self, call_type, id)

getstream/video/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ def __init__(self, api_key: str, base_url, token, timeout, stream, user_agent=No
1212
:param timeout: A number representing the time limit for a request
1313
:param user_agent: Optional custom user agent string
1414
"""
15-
self.stream = stream
1615
super().__init__(
1716
api_key=api_key,
1817
base_url=base_url,
1918
token=token,
2019
timeout=timeout,
2120
user_agent=user_agent,
2221
)
22+
self.stream = stream
2323

2424
def call(self, call_type: str, id: str) -> Call:
2525
return Call(self, call_type, id)

0 commit comments

Comments
 (0)