Skip to content

Commit a955f24

Browse files
Zawwarsami16claude
andcommitted
fix CI: use inspect.isgenerator + isasyncgen before iscoroutine check
python 3.10 / 3.11 quirk — sync generator objects sometimes pass the asyncio.iscoroutine() check, so `await result` raises TypeError. order the inspect checks: async-gen → sync-gen → coroutine → final value. tests pass 3.10/3.11/3.12/3.13. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b24b4f6 commit a955f24

1 file changed

Lines changed: 10 additions & 7 deletions

File tree

zhub/client.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,28 +182,31 @@ async def runner() -> None:
182182

183183

184184
async def _handle_chat(pub: ZhubPublication, ws, env: Envelope) -> None:
185+
import inspect
186+
185187
messages = env.payload.get("messages", [])
186188
options = {k: v for k, v in env.payload.items() if k != "messages"}
187189
streaming_requested = bool(options.get("stream"))
188190
try:
189191
result = pub.chat_handler(messages, options)
190192

191-
# Coroutines
192-
if asyncio.iscoroutine(result):
193-
result = await result
194-
195-
# Sync iterators / async iterators — streaming
196-
if hasattr(result, "__aiter__"):
193+
# Streaming first — before iscoroutine check, since some Python versions
194+
# treat sync generators ambiguously and `await` on a generator throws.
195+
if inspect.isasyncgen(result):
197196
async for chunk in result:
198197
await ws.send(chat_chunk(str(chunk), env.request_id).to_json())
199198
await ws.send(chat_chunk("", env.request_id, done=True, finish_reason="stop").to_json())
200199
return
201-
if streaming_requested and hasattr(result, "__iter__") and not isinstance(result, (str, dict, bytes)):
200+
if inspect.isgenerator(result):
202201
for chunk in result:
203202
await ws.send(chat_chunk(str(chunk), env.request_id).to_json())
204203
await ws.send(chat_chunk("", env.request_id, done=True, finish_reason="stop").to_json())
205204
return
206205

206+
# Coroutine — await for the final value
207+
if inspect.iscoroutine(result):
208+
result = await result
209+
207210
# Single-shot
208211
if isinstance(result, str):
209212
payload = {"text": result, "finish_reason": "stop"}

0 commit comments

Comments
 (0)