diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 98411f0f2b..783bfe09c9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.102.0" + ".": "1.102.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 26ca1c5cb2..92b70cd616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 1.102.1 (2025-08-29) + +Full Changelog: [v1.102.0...v1.102.1](https://github.com/openai/openai-python/compare/v1.102.0...v1.102.1) + +### Bug Fixes + +* **responses:** add missing params to stream() method ([bfc0673](https://github.com/openai/openai-python/commit/bfc06732ffe3764cb95cef9f23b4b5c0d312826a)) + + +### Chores + +* bump `inline-snapshot` version to 0.28.0 ([#2590](https://github.com/openai/openai-python/issues/2590)) ([a6b0872](https://github.com/openai/openai-python/commit/a6b087226587d4cc4f59f1f09a595921b2823ef2)) +* **internal:** add Sequence related utils ([d3d72b9](https://github.com/openai/openai-python/commit/d3d72b9ce3c0885bf2b6934ac57d9e84f8653208)) +* **internal:** fix formatting ([3ab273f](https://github.com/openai/openai-python/commit/3ab273f21e601f088be7502b7bb5d249fc386d6a)) +* **internal:** minor formatting change ([478a348](https://github.com/openai/openai-python/commit/478a34881c968e9cab9d93ac2cf8da2fcb37c46c)) +* **internal:** update pyright exclude list ([66e440f](https://github.com/openai/openai-python/commit/66e440fac3ca388400392c64211450dedc491c11)) + ## 1.102.0 (2025-08-26) Full Changelog: [v1.101.0...v1.102.0](https://github.com/openai/openai-python/compare/v1.101.0...v1.102.0) diff --git a/pyproject.toml b/pyproject.toml index 6736c1ad9e..d045616d2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai" -version = "1.102.0" +version = "1.102.1" description = "The official Python library for the openai API" dynamic = ["readme"] license = "Apache-2.0" @@ -64,7 +64,7 @@ dev-dependencies = [ "dirty-equals>=0.6.0", "importlib-metadata>=6.7.0", "rich>=13.7.1", - "inline-snapshot >=0.7.0", + "inline-snapshot>=0.28.0", "azure-identity >=1.14.1", "types-tqdm > 4", "types-pyaudio > 0", @@ -165,6 +165,7 @@ exclude = [ "_dev", ".venv", ".nox", + ".git", # uses inline `uv` script dependencies # which means it can't be type checked diff --git a/requirements-dev.lock b/requirements-dev.lock index e8bea53014..669378387d 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -90,7 +90,7 @@ idna==3.4 importlib-metadata==7.0.0 iniconfig==2.0.0 # via pytest -inline-snapshot==0.27.0 +inline-snapshot==0.28.0 jiter==0.5.0 # via openai markdown-it-py==3.0.0 diff --git a/src/openai/_types.py b/src/openai/_types.py index 5dae55f4a9..0e8ffa12aa 100644 --- a/src/openai/_types.py +++ b/src/openai/_types.py @@ -13,10 +13,21 @@ Mapping, TypeVar, Callable, + Iterator, Optional, Sequence, ) -from typing_extensions import Set, Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable +from typing_extensions import ( + Set, + Literal, + Protocol, + TypeAlias, + TypedDict, + SupportsIndex, + overload, + override, + runtime_checkable, +) import httpx import pydantic @@ -219,3 +230,26 @@ class _GenericAlias(Protocol): class HttpxSendArgs(TypedDict, total=False): auth: httpx.Auth follow_redirects: bool + + +_T_co = TypeVar("_T_co", covariant=True) + + +if TYPE_CHECKING: + # This works because str.__contains__ does not accept object (either in typeshed or at runtime) + # https://github.com/hauntsaninja/useful_types/blob/5e9710f3875107d068e7679fd7fec9cfab0eff3b/useful_types/__init__.py#L285 + class SequenceNotStr(Protocol[_T_co]): + @overload + def __getitem__(self, index: SupportsIndex, /) -> _T_co: ... + @overload + def __getitem__(self, index: slice, /) -> Sequence[_T_co]: ... + def __contains__(self, value: object, /) -> bool: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[_T_co]: ... + def index(self, value: Any, start: int = 0, stop: int = ..., /) -> int: ... + def count(self, value: Any, /) -> int: ... + def __reversed__(self) -> Iterator[_T_co]: ... +else: + # just point this to a normal `Sequence` at runtime to avoid having to special case + # deserializing our custom sequence type + SequenceNotStr = Sequence diff --git a/src/openai/_utils/__init__.py b/src/openai/_utils/__init__.py index bd01c088dc..6471aa4c0d 100644 --- a/src/openai/_utils/__init__.py +++ b/src/openai/_utils/__init__.py @@ -41,6 +41,7 @@ extract_type_arg as extract_type_arg, is_iterable_type as is_iterable_type, is_required_type as is_required_type, + is_sequence_type as is_sequence_type, is_annotated_type as is_annotated_type, is_type_alias_type as is_type_alias_type, strip_annotated_type as strip_annotated_type, diff --git a/src/openai/_utils/_typing.py b/src/openai/_utils/_typing.py index 1bac9542e2..845cd6b287 100644 --- a/src/openai/_utils/_typing.py +++ b/src/openai/_utils/_typing.py @@ -26,6 +26,11 @@ def is_list_type(typ: type) -> bool: return (get_origin(typ) or typ) == list +def is_sequence_type(typ: type) -> bool: + origin = get_origin(typ) or typ + return origin == typing_extensions.Sequence or origin == typing.Sequence or origin == _c_abc.Sequence + + def is_iterable_type(typ: type) -> bool: """If the given type is `typing.Iterable[T]`""" origin = get_origin(typ) or typ diff --git a/src/openai/_version.py b/src/openai/_version.py index b2d62263ff..db883559a6 100644 --- a/src/openai/_version.py +++ b/src/openai/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "openai" -__version__ = "1.102.0" # x-release-please-version +__version__ = "1.102.1" # x-release-please-version diff --git a/src/openai/resources/beta/threads/messages.py b/src/openai/resources/beta/threads/messages.py index 943d2e7f05..8903ff0316 100644 --- a/src/openai/resources/beta/threads/messages.py +++ b/src/openai/resources/beta/threads/messages.py @@ -600,27 +600,27 @@ def __init__(self, messages: Messages) -> None: self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - messages.create # pyright: ignore[reportDeprecated], + messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - messages.retrieve # pyright: ignore[reportDeprecated], + messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - messages.update # pyright: ignore[reportDeprecated], + messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - messages.list # pyright: ignore[reportDeprecated], + messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - messages.delete # pyright: ignore[reportDeprecated], + messages.delete, # pyright: ignore[reportDeprecated], ) ) @@ -631,27 +631,27 @@ def __init__(self, messages: AsyncMessages) -> None: self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - messages.create # pyright: ignore[reportDeprecated], + messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - messages.retrieve # pyright: ignore[reportDeprecated], + messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - messages.update # pyright: ignore[reportDeprecated], + messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - messages.list # pyright: ignore[reportDeprecated], + messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - messages.delete # pyright: ignore[reportDeprecated], + messages.delete, # pyright: ignore[reportDeprecated], ) ) @@ -662,27 +662,27 @@ def __init__(self, messages: Messages) -> None: self.create = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - messages.create # pyright: ignore[reportDeprecated], + messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - messages.retrieve # pyright: ignore[reportDeprecated], + messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - messages.update # pyright: ignore[reportDeprecated], + messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - messages.list # pyright: ignore[reportDeprecated], + messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - messages.delete # pyright: ignore[reportDeprecated], + messages.delete, # pyright: ignore[reportDeprecated], ) ) @@ -693,26 +693,26 @@ def __init__(self, messages: AsyncMessages) -> None: self.create = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - messages.create # pyright: ignore[reportDeprecated], + messages.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - messages.retrieve # pyright: ignore[reportDeprecated], + messages.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - messages.update # pyright: ignore[reportDeprecated], + messages.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - messages.list # pyright: ignore[reportDeprecated], + messages.list, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - messages.delete # pyright: ignore[reportDeprecated], + messages.delete, # pyright: ignore[reportDeprecated], ) ) diff --git a/src/openai/resources/beta/threads/runs/runs.py b/src/openai/resources/beta/threads/runs/runs.py index 07b43e6471..e97d519a40 100644 --- a/src/openai/resources/beta/threads/runs/runs.py +++ b/src/openai/resources/beta/threads/runs/runs.py @@ -2926,32 +2926,32 @@ def __init__(self, runs: Runs) -> None: self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - runs.create # pyright: ignore[reportDeprecated], + runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - runs.retrieve # pyright: ignore[reportDeprecated], + runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - runs.update # pyright: ignore[reportDeprecated], + runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - runs.list # pyright: ignore[reportDeprecated], + runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - runs.cancel # pyright: ignore[reportDeprecated], + runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - runs.submit_tool_outputs # pyright: ignore[reportDeprecated], + runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) @@ -2966,32 +2966,32 @@ def __init__(self, runs: AsyncRuns) -> None: self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - runs.create # pyright: ignore[reportDeprecated], + runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - runs.retrieve # pyright: ignore[reportDeprecated], + runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - runs.update # pyright: ignore[reportDeprecated], + runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - runs.list # pyright: ignore[reportDeprecated], + runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - runs.cancel # pyright: ignore[reportDeprecated], + runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - runs.submit_tool_outputs # pyright: ignore[reportDeprecated], + runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) @@ -3006,32 +3006,32 @@ def __init__(self, runs: Runs) -> None: self.create = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - runs.create # pyright: ignore[reportDeprecated], + runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - runs.retrieve # pyright: ignore[reportDeprecated], + runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - runs.update # pyright: ignore[reportDeprecated], + runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - runs.list # pyright: ignore[reportDeprecated], + runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - runs.cancel # pyright: ignore[reportDeprecated], + runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - runs.submit_tool_outputs # pyright: ignore[reportDeprecated], + runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) @@ -3046,32 +3046,32 @@ def __init__(self, runs: AsyncRuns) -> None: self.create = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - runs.create # pyright: ignore[reportDeprecated], + runs.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - runs.retrieve # pyright: ignore[reportDeprecated], + runs.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - runs.update # pyright: ignore[reportDeprecated], + runs.update, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - runs.list # pyright: ignore[reportDeprecated], + runs.list, # pyright: ignore[reportDeprecated], ) ) self.cancel = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - runs.cancel # pyright: ignore[reportDeprecated], + runs.cancel, # pyright: ignore[reportDeprecated], ) ) self.submit_tool_outputs = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - runs.submit_tool_outputs # pyright: ignore[reportDeprecated], + runs.submit_tool_outputs, # pyright: ignore[reportDeprecated], ) ) diff --git a/src/openai/resources/beta/threads/runs/steps.py b/src/openai/resources/beta/threads/runs/steps.py index eebb2003b2..8e34210bd7 100644 --- a/src/openai/resources/beta/threads/runs/steps.py +++ b/src/openai/resources/beta/threads/runs/steps.py @@ -341,12 +341,12 @@ def __init__(self, steps: Steps) -> None: self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - steps.retrieve # pyright: ignore[reportDeprecated], + steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - steps.list # pyright: ignore[reportDeprecated], + steps.list, # pyright: ignore[reportDeprecated], ) ) @@ -357,12 +357,12 @@ def __init__(self, steps: AsyncSteps) -> None: self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - steps.retrieve # pyright: ignore[reportDeprecated], + steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - steps.list # pyright: ignore[reportDeprecated], + steps.list, # pyright: ignore[reportDeprecated], ) ) @@ -373,12 +373,12 @@ def __init__(self, steps: Steps) -> None: self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - steps.retrieve # pyright: ignore[reportDeprecated], + steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - steps.list # pyright: ignore[reportDeprecated], + steps.list, # pyright: ignore[reportDeprecated], ) ) @@ -389,11 +389,11 @@ def __init__(self, steps: AsyncSteps) -> None: self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - steps.retrieve # pyright: ignore[reportDeprecated], + steps.retrieve, # pyright: ignore[reportDeprecated], ) ) self.list = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - steps.list # pyright: ignore[reportDeprecated], + steps.list, # pyright: ignore[reportDeprecated], ) ) diff --git a/src/openai/resources/beta/threads/threads.py b/src/openai/resources/beta/threads/threads.py index dbe47d2d0e..7121851cab 100644 --- a/src/openai/resources/beta/threads/threads.py +++ b/src/openai/resources/beta/threads/threads.py @@ -1785,27 +1785,27 @@ def __init__(self, threads: Threads) -> None: self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - threads.create # pyright: ignore[reportDeprecated], + threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - threads.retrieve # pyright: ignore[reportDeprecated], + threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - threads.update # pyright: ignore[reportDeprecated], + threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - threads.delete # pyright: ignore[reportDeprecated], + threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - threads.create_and_run # pyright: ignore[reportDeprecated], + threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) @@ -1824,27 +1824,27 @@ def __init__(self, threads: AsyncThreads) -> None: self.create = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - threads.create # pyright: ignore[reportDeprecated], + threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - threads.retrieve # pyright: ignore[reportDeprecated], + threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - threads.update # pyright: ignore[reportDeprecated], + threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - threads.delete # pyright: ignore[reportDeprecated], + threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - threads.create_and_run # pyright: ignore[reportDeprecated], + threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) @@ -1863,27 +1863,27 @@ def __init__(self, threads: Threads) -> None: self.create = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - threads.create # pyright: ignore[reportDeprecated], + threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - threads.retrieve # pyright: ignore[reportDeprecated], + threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - threads.update # pyright: ignore[reportDeprecated], + threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - threads.delete # pyright: ignore[reportDeprecated], + threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - threads.create_and_run # pyright: ignore[reportDeprecated], + threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) @@ -1902,27 +1902,27 @@ def __init__(self, threads: AsyncThreads) -> None: self.create = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - threads.create # pyright: ignore[reportDeprecated], + threads.create, # pyright: ignore[reportDeprecated], ) ) self.retrieve = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - threads.retrieve # pyright: ignore[reportDeprecated], + threads.retrieve, # pyright: ignore[reportDeprecated], ) ) self.update = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - threads.update # pyright: ignore[reportDeprecated], + threads.update, # pyright: ignore[reportDeprecated], ) ) self.delete = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - threads.delete # pyright: ignore[reportDeprecated], + threads.delete, # pyright: ignore[reportDeprecated], ) ) self.create_and_run = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - threads.create_and_run # pyright: ignore[reportDeprecated], + threads.create_and_run, # pyright: ignore[reportDeprecated], ) ) diff --git a/src/openai/resources/files.py b/src/openai/resources/files.py index b45b8f303f..963c3c0a9f 100644 --- a/src/openai/resources/files.py +++ b/src/openai/resources/files.py @@ -687,7 +687,7 @@ def __init__(self, files: Files) -> None: ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] _legacy_response.to_raw_response_wrapper( - files.retrieve_content # pyright: ignore[reportDeprecated], + files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) @@ -713,7 +713,7 @@ def __init__(self, files: AsyncFiles) -> None: ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] _legacy_response.async_to_raw_response_wrapper( - files.retrieve_content # pyright: ignore[reportDeprecated], + files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) @@ -740,7 +740,7 @@ def __init__(self, files: Files) -> None: ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] to_streamed_response_wrapper( - files.retrieve_content # pyright: ignore[reportDeprecated], + files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) @@ -767,6 +767,6 @@ def __init__(self, files: AsyncFiles) -> None: ) self.retrieve_content = ( # pyright: ignore[reportDeprecated] async_to_streamed_response_wrapper( - files.retrieve_content # pyright: ignore[reportDeprecated], + files.retrieve_content, # pyright: ignore[reportDeprecated], ) ) diff --git a/src/openai/resources/responses/responses.py b/src/openai/resources/responses/responses.py index 062fd491f2..e04382a9ff 100644 --- a/src/openai/resources/responses/responses.py +++ b/src/openai/resources/responses/responses.py @@ -31,7 +31,6 @@ parse_response, type_to_text_format_param as _type_to_text_format_param, ) -from ...types.shared.chat_model import ChatModel from ...types.responses.response import Response from ...types.responses.tool_param import ToolParam, ParseableToolParam from ...types.shared_params.metadata import Metadata @@ -881,22 +880,29 @@ def stream( self, *, input: Union[str, ResponseInputParam], - model: Union[str, ChatModel], + model: ResponsesModel, background: Optional[bool] | NotGiven = NOT_GIVEN, text_format: type[TextFormatT] | NotGiven = NOT_GIVEN, tools: Iterable[ParseableToolParam] | NotGiven = NOT_GIVEN, + conversation: Optional[response_create_params.Conversation] | NotGiven = NOT_GIVEN, include: Optional[List[ResponseIncludable]] | NotGiven = NOT_GIVEN, instructions: Optional[str] | NotGiven = NOT_GIVEN, max_output_tokens: Optional[int] | NotGiven = NOT_GIVEN, + max_tool_calls: Optional[int] | NotGiven = NOT_GIVEN, metadata: Optional[Metadata] | NotGiven = NOT_GIVEN, parallel_tool_calls: Optional[bool] | NotGiven = NOT_GIVEN, previous_response_id: Optional[str] | NotGiven = NOT_GIVEN, + prompt: Optional[ResponsePromptParam] | NotGiven = NOT_GIVEN, + prompt_cache_key: str | NotGiven = NOT_GIVEN, reasoning: Optional[Reasoning] | NotGiven = NOT_GIVEN, + safety_identifier: str | NotGiven = NOT_GIVEN, + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | NotGiven = NOT_GIVEN, store: Optional[bool] | NotGiven = NOT_GIVEN, stream_options: Optional[response_create_params.StreamOptions] | NotGiven = NOT_GIVEN, temperature: Optional[float] | NotGiven = NOT_GIVEN, - text: ResponseTextConfigParam| NotGiven = NOT_GIVEN, + text: ResponseTextConfigParam | NotGiven = NOT_GIVEN, tool_choice: response_create_params.ToolChoice | NotGiven = NOT_GIVEN, + top_logprobs: Optional[int] | NotGiven = NOT_GIVEN, top_p: Optional[float] | NotGiven = NOT_GIVEN, truncation: Optional[Literal["auto", "disabled"]] | NotGiven = NOT_GIVEN, user: str | NotGiven = NOT_GIVEN, @@ -913,22 +919,29 @@ def stream( *, response_id: str | NotGiven = NOT_GIVEN, input: Union[str, ResponseInputParam] | NotGiven = NOT_GIVEN, - model: Union[str, ChatModel] | NotGiven = NOT_GIVEN, + model: ResponsesModel | NotGiven = NOT_GIVEN, background: Optional[bool] | NotGiven = NOT_GIVEN, text_format: type[TextFormatT] | NotGiven = NOT_GIVEN, tools: Iterable[ParseableToolParam] | NotGiven = NOT_GIVEN, + conversation: Optional[response_create_params.Conversation] | NotGiven = NOT_GIVEN, include: Optional[List[ResponseIncludable]] | NotGiven = NOT_GIVEN, instructions: Optional[str] | NotGiven = NOT_GIVEN, max_output_tokens: Optional[int] | NotGiven = NOT_GIVEN, + max_tool_calls: Optional[int] | NotGiven = NOT_GIVEN, metadata: Optional[Metadata] | NotGiven = NOT_GIVEN, parallel_tool_calls: Optional[bool] | NotGiven = NOT_GIVEN, previous_response_id: Optional[str] | NotGiven = NOT_GIVEN, + prompt: Optional[ResponsePromptParam] | NotGiven = NOT_GIVEN, + prompt_cache_key: str | NotGiven = NOT_GIVEN, reasoning: Optional[Reasoning] | NotGiven = NOT_GIVEN, + safety_identifier: str | NotGiven = NOT_GIVEN, + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | NotGiven = NOT_GIVEN, store: Optional[bool] | NotGiven = NOT_GIVEN, stream_options: Optional[response_create_params.StreamOptions] | NotGiven = NOT_GIVEN, temperature: Optional[float] | NotGiven = NOT_GIVEN, text: ResponseTextConfigParam | NotGiven = NOT_GIVEN, tool_choice: response_create_params.ToolChoice | NotGiven = NOT_GIVEN, + top_logprobs: Optional[int] | NotGiven = NOT_GIVEN, top_p: Optional[float] | NotGiven = NOT_GIVEN, truncation: Optional[Literal["auto", "disabled"]] | NotGiven = NOT_GIVEN, user: str | NotGiven = NOT_GIVEN, @@ -943,18 +956,25 @@ def stream( new_response_args = { "input": input, "model": model, + "conversation": conversation, "include": include, "instructions": instructions, "max_output_tokens": max_output_tokens, + "max_tool_calls": max_tool_calls, "metadata": metadata, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, + "prompt": prompt, + "prompt_cache_key": prompt_cache_key, "reasoning": reasoning, + "safety_identifier": safety_identifier, + "service_tier": service_tier, "store": store, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, + "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, @@ -989,12 +1009,16 @@ def stream( input=input, model=model, tools=tools, + conversation=conversation, include=include, instructions=instructions, max_output_tokens=max_output_tokens, + max_tool_calls=max_tool_calls, metadata=metadata, parallel_tool_calls=parallel_tool_calls, previous_response_id=previous_response_id, + prompt=prompt, + prompt_cache_key=prompt_cache_key, store=store, stream_options=stream_options, stream=True, @@ -1002,6 +1026,9 @@ def stream( text=text, tool_choice=tool_choice, reasoning=reasoning, + safety_identifier=safety_identifier, + service_tier=service_tier, + top_logprobs=top_logprobs, top_p=top_p, truncation=truncation, user=user, @@ -1057,7 +1084,7 @@ def parse( stream: Optional[Literal[False]] | Literal[True] | NotGiven = NOT_GIVEN, stream_options: Optional[response_create_params.StreamOptions] | NotGiven = NOT_GIVEN, temperature: Optional[float] | NotGiven = NOT_GIVEN, - text: ResponseTextConfigParam| NotGiven = NOT_GIVEN, + text: ResponseTextConfigParam | NotGiven = NOT_GIVEN, tool_choice: response_create_params.ToolChoice | NotGiven = NOT_GIVEN, tools: Iterable[ParseableToolParam] | NotGiven = NOT_GIVEN, top_logprobs: Optional[int] | NotGiven = NOT_GIVEN, @@ -2275,22 +2302,29 @@ def stream( self, *, input: Union[str, ResponseInputParam], - model: Union[str, ChatModel], + model: ResponsesModel, background: Optional[bool] | NotGiven = NOT_GIVEN, text_format: type[TextFormatT] | NotGiven = NOT_GIVEN, tools: Iterable[ParseableToolParam] | NotGiven = NOT_GIVEN, + conversation: Optional[response_create_params.Conversation] | NotGiven = NOT_GIVEN, include: Optional[List[ResponseIncludable]] | NotGiven = NOT_GIVEN, instructions: Optional[str] | NotGiven = NOT_GIVEN, max_output_tokens: Optional[int] | NotGiven = NOT_GIVEN, + max_tool_calls: Optional[int] | NotGiven = NOT_GIVEN, metadata: Optional[Metadata] | NotGiven = NOT_GIVEN, parallel_tool_calls: Optional[bool] | NotGiven = NOT_GIVEN, previous_response_id: Optional[str] | NotGiven = NOT_GIVEN, + prompt: Optional[ResponsePromptParam] | NotGiven = NOT_GIVEN, + prompt_cache_key: str | NotGiven = NOT_GIVEN, reasoning: Optional[Reasoning] | NotGiven = NOT_GIVEN, + safety_identifier: str | NotGiven = NOT_GIVEN, + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | NotGiven = NOT_GIVEN, store: Optional[bool] | NotGiven = NOT_GIVEN, stream_options: Optional[response_create_params.StreamOptions] | NotGiven = NOT_GIVEN, temperature: Optional[float] | NotGiven = NOT_GIVEN, - text: ResponseTextConfigParam| NotGiven = NOT_GIVEN, + text: ResponseTextConfigParam | NotGiven = NOT_GIVEN, tool_choice: response_create_params.ToolChoice | NotGiven = NOT_GIVEN, + top_logprobs: Optional[int] | NotGiven = NOT_GIVEN, top_p: Optional[float] | NotGiven = NOT_GIVEN, truncation: Optional[Literal["auto", "disabled"]] | NotGiven = NOT_GIVEN, user: str | NotGiven = NOT_GIVEN, @@ -2307,22 +2341,29 @@ def stream( *, response_id: str | NotGiven = NOT_GIVEN, input: Union[str, ResponseInputParam] | NotGiven = NOT_GIVEN, - model: Union[str, ChatModel] | NotGiven = NOT_GIVEN, + model: ResponsesModel | NotGiven = NOT_GIVEN, background: Optional[bool] | NotGiven = NOT_GIVEN, text_format: type[TextFormatT] | NotGiven = NOT_GIVEN, tools: Iterable[ParseableToolParam] | NotGiven = NOT_GIVEN, + conversation: Optional[response_create_params.Conversation] | NotGiven = NOT_GIVEN, include: Optional[List[ResponseIncludable]] | NotGiven = NOT_GIVEN, instructions: Optional[str] | NotGiven = NOT_GIVEN, max_output_tokens: Optional[int] | NotGiven = NOT_GIVEN, + max_tool_calls: Optional[int] | NotGiven = NOT_GIVEN, metadata: Optional[Metadata] | NotGiven = NOT_GIVEN, parallel_tool_calls: Optional[bool] | NotGiven = NOT_GIVEN, previous_response_id: Optional[str] | NotGiven = NOT_GIVEN, + prompt: Optional[ResponsePromptParam] | NotGiven = NOT_GIVEN, + prompt_cache_key: str | NotGiven = NOT_GIVEN, reasoning: Optional[Reasoning] | NotGiven = NOT_GIVEN, + safety_identifier: str | NotGiven = NOT_GIVEN, + service_tier: Optional[Literal["auto", "default", "flex", "scale", "priority"]] | NotGiven = NOT_GIVEN, store: Optional[bool] | NotGiven = NOT_GIVEN, stream_options: Optional[response_create_params.StreamOptions] | NotGiven = NOT_GIVEN, temperature: Optional[float] | NotGiven = NOT_GIVEN, - text: ResponseTextConfigParam| NotGiven = NOT_GIVEN, + text: ResponseTextConfigParam | NotGiven = NOT_GIVEN, tool_choice: response_create_params.ToolChoice | NotGiven = NOT_GIVEN, + top_logprobs: Optional[int] | NotGiven = NOT_GIVEN, top_p: Optional[float] | NotGiven = NOT_GIVEN, truncation: Optional[Literal["auto", "disabled"]] | NotGiven = NOT_GIVEN, user: str | NotGiven = NOT_GIVEN, @@ -2337,18 +2378,25 @@ def stream( new_response_args = { "input": input, "model": model, + "conversation": conversation, "include": include, "instructions": instructions, "max_output_tokens": max_output_tokens, + "max_tool_calls": max_tool_calls, "metadata": metadata, "parallel_tool_calls": parallel_tool_calls, "previous_response_id": previous_response_id, + "prompt": prompt, + "prompt_cache_key": prompt_cache_key, "reasoning": reasoning, + "safety_identifier": safety_identifier, + "service_tier": service_tier, "store": store, "stream_options": stream_options, "temperature": temperature, "text": text, "tool_choice": tool_choice, + "top_logprobs": top_logprobs, "top_p": top_p, "truncation": truncation, "user": user, @@ -2384,21 +2432,29 @@ def stream( model=model, stream=True, tools=tools, + conversation=conversation, include=include, instructions=instructions, max_output_tokens=max_output_tokens, + max_tool_calls=max_tool_calls, metadata=metadata, parallel_tool_calls=parallel_tool_calls, previous_response_id=previous_response_id, + prompt=prompt, + prompt_cache_key=prompt_cache_key, store=store, stream_options=stream_options, temperature=temperature, text=text, tool_choice=tool_choice, reasoning=reasoning, + safety_identifier=safety_identifier, + service_tier=service_tier, + top_logprobs=top_logprobs, top_p=top_p, truncation=truncation, user=user, + background=background, extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, @@ -2455,7 +2511,7 @@ async def parse( stream: Optional[Literal[False]] | Literal[True] | NotGiven = NOT_GIVEN, stream_options: Optional[response_create_params.StreamOptions] | NotGiven = NOT_GIVEN, temperature: Optional[float] | NotGiven = NOT_GIVEN, - text: ResponseTextConfigParam| NotGiven = NOT_GIVEN, + text: ResponseTextConfigParam | NotGiven = NOT_GIVEN, tool_choice: response_create_params.ToolChoice | NotGiven = NOT_GIVEN, tools: Iterable[ParseableToolParam] | NotGiven = NOT_GIVEN, top_logprobs: Optional[int] | NotGiven = NOT_GIVEN, diff --git a/tests/lib/chat/test_completions_streaming.py b/tests/lib/chat/test_completions_streaming.py index fa17f67177..548416dfe2 100644 --- a/tests/lib/chat/test_completions_streaming.py +++ b/tests/lib/chat/test_completions_streaming.py @@ -13,6 +13,7 @@ external, snapshot, outsource, # pyright: ignore[reportUnknownVariableType] + get_snapshot_value, ) import openai @@ -30,7 +31,7 @@ ) from openai.lib._parsing._completions import ResponseFormatT -from ..utils import print_obj, get_snapshot_value +from ..utils import print_obj from ...conftest import base_url _T = TypeVar("_T") diff --git a/tests/lib/responses/test_responses.py b/tests/lib/responses/test_responses.py index 8ce3462e76..8e5f16df95 100644 --- a/tests/lib/responses/test_responses.py +++ b/tests/lib/responses/test_responses.py @@ -6,7 +6,8 @@ from respx import MockRouter from inline_snapshot import snapshot -from openai import OpenAI +from openai import OpenAI, AsyncOpenAI +from openai._utils import assert_signatures_in_sync from ...conftest import base_url from ..snapshots import make_snapshot_request @@ -38,3 +39,25 @@ def test_output_text(client: OpenAI, respx_mock: MockRouter) -> None: assert response.output_text == snapshot( "I can't provide real-time updates, but you can easily check the current weather in San Francisco using a weather website or app. Typically, San Francisco has cool, foggy summers and mild winters, so it's good to be prepared for variable weather!" ) + + +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +def test_stream_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: + checking_client: OpenAI | AsyncOpenAI = client if sync else async_client + + assert_signatures_in_sync( + checking_client.responses.create, + checking_client.responses.stream, + exclude_params={"stream", "tools"}, + ) + + +@pytest.mark.parametrize("sync", [True, False], ids=["sync", "async"]) +def test_parse_method_definition_in_sync(sync: bool, client: OpenAI, async_client: AsyncOpenAI) -> None: + checking_client: OpenAI | AsyncOpenAI = client if sync else async_client + + assert_signatures_in_sync( + checking_client.responses.create, + checking_client.responses.parse, + exclude_params={"tools"}, + ) diff --git a/tests/lib/snapshots.py b/tests/lib/snapshots.py index ed53edebcb..91222acda1 100644 --- a/tests/lib/snapshots.py +++ b/tests/lib/snapshots.py @@ -7,11 +7,10 @@ import httpx from respx import MockRouter +from inline_snapshot import get_snapshot_value from openai import OpenAI, AsyncOpenAI -from .utils import get_snapshot_value - _T = TypeVar("_T") diff --git a/tests/lib/utils.py b/tests/lib/utils.py index 2129ee811a..e6b6a29434 100644 --- a/tests/lib/utils.py +++ b/tests/lib/utils.py @@ -52,15 +52,3 @@ def get_caller_name(*, stacklevel: int = 1) -> str: def clear_locals(string: str, *, stacklevel: int) -> str: caller = get_caller_name(stacklevel=stacklevel + 1) return string.replace(f"{caller}..", "") - - -def get_snapshot_value(snapshot: Any) -> Any: - if not hasattr(snapshot, "_old_value"): - return snapshot - - old = snapshot._old_value - if not hasattr(old, "value"): - return old - - loader = getattr(old.value, "_load_value", None) - return loader() if loader else old.value diff --git a/tests/utils.py b/tests/utils.py index 4cf5ce171b..7740ed3f7c 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -5,7 +5,7 @@ import inspect import traceback import contextlib -from typing import Any, TypeVar, Iterator, ForwardRef, cast +from typing import Any, TypeVar, Iterator, ForwardRef, Sequence, cast from datetime import date, datetime from typing_extensions import Literal, get_args, get_origin, assert_type @@ -18,6 +18,7 @@ is_list_type, is_union_type, extract_type_arg, + is_sequence_type, is_annotated_type, is_type_alias_type, ) @@ -78,6 +79,13 @@ def assert_matches_type( if is_list_type(type_): return _assert_list_type(type_, value) + if is_sequence_type(type_): + assert isinstance(value, Sequence) + inner_type = get_args(type_)[0] + for entry in value: # type: ignore + assert_type(inner_type, entry) # type: ignore + return + if origin == str: assert isinstance(value, str) elif origin == int: