Files
567-labs--instructor/tests/processing/test_list_response_wrapper.py
T
wehub-resource-sync 97e91a83f3
Ruff / Ruff (push) Waiting to run
Test / Core Tests (push) Waiting to run
Test / Offline Coverage Tests (Python 3.10) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.11) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.12) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.13) (push) Waiting to run
Test / Offline Coverage Tests (Python 3.9) (push) Waiting to run
Test / Full Coverage (Python 3.11) (push) Waiting to run
Test / Core Provider Tests (OpenAI) (push) Blocked by required conditions
Test / Core Provider Tests (Anthropic) (push) Blocked by required conditions
Test / Core Provider Tests (Google) (push) Blocked by required conditions
Test / Core Provider Tests (Other) (push) Blocked by required conditions
Test / Anthropic Tests (push) Blocked by required conditions
Test / Gemini Tests (push) Blocked by required conditions
Test / Google GenAI Tests (push) Blocked by required conditions
Test / Vertex AI Tests (push) Blocked by required conditions
Test / OpenAI Tests (push) Blocked by required conditions
Test / Writer Tests (push) Blocked by required conditions
Test / Auto Client Tests (push) Blocked by required conditions
ty / type-check (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:38 +08:00

104 lines
2.9 KiB
Python

from __future__ import annotations
from collections.abc import AsyncGenerator, Generator
import pytest
from pydantic import BaseModel
from instructor.dsl.iterable import IterableBase
from instructor.dsl.response_list import ListResponse
from instructor.mode import Mode
from instructor.processing.response import process_response, process_response_async
from instructor.utils.core import prepare_response_model
class DummyIterableModel(BaseModel, IterableBase):
tasks: list[int]
@classmethod
def from_response(cls, completion, **kwargs): # noqa: ANN001,ARG003
return cls(tasks=[1, 2])
@classmethod
def from_streaming_response( # ty: ignore[invalid-method-override] # noqa: ANN001
cls, _completion, mode: Mode, **_kwargs
) -> Generator[int, None, None]:
del mode
yield 1
yield 2
@classmethod
def from_streaming_response_async( # ty: ignore[invalid-method-override] # noqa: ANN001
cls, _completion: AsyncGenerator[object, None], mode: Mode, **_kwargs
) -> AsyncGenerator[int, None]:
del mode
async def gen() -> AsyncGenerator[int, None]:
yield 1
yield 2
return gen()
class DummyCompletion(BaseModel):
"""Minimal stand-in for a provider completion object."""
def test_process_response_returns_list_response_for_iterable_model():
raw = DummyCompletion()
result = process_response(
raw,
response_model=DummyIterableModel,
stream=False,
mode=Mode.TOOLS,
)
assert isinstance(result, ListResponse)
assert list(result) == [1, 2]
assert result._raw_response == raw
def test_process_response_streaming_returns_list_response_for_iterable_model():
raw = DummyCompletion()
result = process_response(
raw,
response_model=DummyIterableModel,
stream=True,
mode=Mode.TOOLS,
)
# Streaming IterableBase should preserve generator behavior (used by create_iterable()).
assert list(result) == [1, 2]
@pytest.mark.asyncio
async def test_process_response_async_streaming_returns_list_response_for_iterable_model():
async def completion_stream() -> AsyncGenerator[object, None]:
yield object()
raw = completion_stream()
result = await process_response_async(
raw, # ty: ignore[invalid-argument-type]
response_model=DummyIterableModel,
stream=True,
mode=Mode.TOOLS,
)
# Streaming IterableBase should preserve async generator behavior (used by create_iterable()).
collected: list[int] = []
async for item in result:
collected.append(item)
assert collected == [1, 2]
def test_prepare_response_model_treats_list_as_iterable_model():
class User(BaseModel):
name: str
prepared = prepare_response_model(list[User])
assert prepared is not None
assert issubclass(prepared, IterableBase)