From 0e67a8af5daf9da029d2bd4bdf341cc8a494254a Mon Sep 17 00:00:00 2001 From: Stainless Bot Date: Mon, 28 Oct 2024 12:28:17 +0000 Subject: [PATCH] chore(internal): bump pytest to v8 & pydantic (#1829) --- requirements-dev.lock | 43 +++++++++---------- requirements.lock | 18 ++++---- src/openai/_compat.py | 2 +- src/openai/_models.py | 10 ++--- src/openai/_types.py | 6 ++- src/openai/lib/streaming/chat/_completions.py | 18 +++++--- tests/conftest.py | 14 +++--- tests/lib/test_old_api.py | 2 +- 8 files changed, 60 insertions(+), 53 deletions(-) diff --git a/requirements-dev.lock b/requirements-dev.lock index 902a80c6ed..2df8a39c76 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -18,14 +18,13 @@ argcomplete==3.1.2 # via nox asttokens==2.4.1 # via inline-snapshot -attrs==23.1.0 +attrs==24.2.0 # via outcome - # via pytest # via trio -azure-core==1.30.1 +azure-core==1.31.0 # via azure-identity -azure-identity==1.15.0 -black==24.4.2 +azure-identity==1.19.0 +black==24.10.0 # via inline-snapshot certifi==2023.7.22 # via httpcore @@ -49,10 +48,11 @@ distlib==0.3.7 # via virtualenv distro==1.8.0 # via openai -exceptiongroup==1.1.3 +exceptiongroup==1.2.2 # via anyio + # via pytest # via trio -executing==2.0.1 +executing==2.1.0 # via inline-snapshot filelock==3.12.4 # via virtualenv @@ -78,7 +78,7 @@ markdown-it-py==3.0.0 # via rich mdurl==0.1.2 # via markdown-it-py -msal==1.29.0 +msal==1.31.0 # via azure-identity # via msal-extensions msal-extensions==1.2.0 @@ -109,26 +109,24 @@ pathspec==0.12.1 platformdirs==3.11.0 # via black # via virtualenv -pluggy==1.3.0 +pluggy==1.5.0 # via pytest -portalocker==2.8.2 +portalocker==2.10.1 # via msal-extensions -py==1.11.0 - # via pytest pycparser==2.22 # via cffi -pydantic==2.7.1 +pydantic==2.9.2 # via openai -pydantic-core==2.18.2 +pydantic-core==2.23.4 # via pydantic pygments==2.18.0 # via rich pyjwt==2.8.0 # via msal pyright==1.1.380 -pytest==7.1.1 +pytest==8.3.3 # via pytest-asyncio -pytest-asyncio==0.21.1 +pytest-asyncio==0.24.0 python-dateutil==2.8.2 # via pandas # via time-machine @@ -158,21 +156,22 @@ sortedcontainers==2.4.0 time-machine==2.9.0 toml==0.10.2 # via inline-snapshot -tomli==2.0.1 +tomli==2.0.2 # via black # via mypy # via pytest -tqdm==4.66.1 +tqdm==4.66.5 # via openai -trio==0.22.2 -types-pyaudio==0.2.16.20240106 -types-pytz==2024.1.0.20240417 +trio==0.27.0 +types-pyaudio==0.2.16.20240516 +types-pytz==2024.2.0.20241003 # via pandas-stubs types-toml==0.10.8.20240310 # via inline-snapshot -types-tqdm==4.66.0.2 +types-tqdm==4.66.0.20240417 typing-extensions==4.12.2 # via azure-core + # via azure-identity # via black # via mypy # via openai diff --git a/requirements.lock b/requirements.lock index de632aefbd..019dfcb4c5 100644 --- a/requirements.lock +++ b/requirements.lock @@ -19,7 +19,7 @@ certifi==2023.7.22 # via httpx distro==1.8.0 # via openai -exceptiongroup==1.1.3 +exceptiongroup==1.2.2 # via anyio h11==0.14.0 # via httpcore @@ -30,19 +30,19 @@ httpx==0.25.2 idna==3.4 # via anyio # via httpx -jiter==0.5.0 +jiter==0.6.1 # via openai -numpy==1.26.4 +numpy==2.0.2 # via openai # via pandas # via pandas-stubs -pandas==2.2.2 +pandas==2.2.3 # via openai -pandas-stubs==2.2.1.240316 +pandas-stubs==2.2.2.240807 # via openai -pydantic==2.7.1 +pydantic==2.9.2 # via openai -pydantic-core==2.18.2 +pydantic-core==2.23.4 # via pydantic python-dateutil==2.9.0.post0 # via pandas @@ -54,9 +54,9 @@ sniffio==1.3.0 # via anyio # via httpx # via openai -tqdm==4.66.1 +tqdm==4.66.5 # via openai -types-pytz==2024.1.0.20240417 +types-pytz==2024.2.0.20241003 # via pandas-stubs typing-extensions==4.12.2 # via openai diff --git a/src/openai/_compat.py b/src/openai/_compat.py index 78851277eb..4dfa23845d 100644 --- a/src/openai/_compat.py +++ b/src/openai/_compat.py @@ -133,7 +133,7 @@ def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: def model_dump( model: pydantic.BaseModel, *, - exclude: IncEx = None, + exclude: IncEx | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, warnings: bool = True, diff --git a/src/openai/_models.py b/src/openai/_models.py index 710401defd..4100328c22 100644 --- a/src/openai/_models.py +++ b/src/openai/_models.py @@ -201,7 +201,7 @@ def __str__(self) -> str: # Based on https://github.com/samuelcolvin/pydantic/issues/1168#issuecomment-817742836. @classmethod @override - def construct( + def construct( # pyright: ignore[reportIncompatibleMethodOverride] cls: Type[ModelT], _fields_set: set[str] | None = None, **values: object, @@ -273,8 +273,8 @@ def model_dump( self, *, mode: Literal["json", "python"] | str = "python", - include: IncEx = None, - exclude: IncEx = None, + include: IncEx | None = None, + exclude: IncEx | None = None, by_alias: bool = False, exclude_unset: bool = False, exclude_defaults: bool = False, @@ -328,8 +328,8 @@ def model_dump_json( self, *, indent: int | None = None, - include: IncEx = None, - exclude: IncEx = None, + include: IncEx | None = None, + exclude: IncEx | None = None, by_alias: bool = False, exclude_unset: bool = False, exclude_defaults: bool = False, diff --git a/src/openai/_types.py b/src/openai/_types.py index 5611b2d38f..c8f4d5a922 100644 --- a/src/openai/_types.py +++ b/src/openai/_types.py @@ -16,7 +16,7 @@ Optional, Sequence, ) -from typing_extensions import Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable +from typing_extensions import Set, Literal, Protocol, TypeAlias, TypedDict, override, runtime_checkable import httpx import pydantic @@ -195,7 +195,9 @@ def get(self, __key: str) -> str | None: ... # Note: copied from Pydantic # https://github.com/pydantic/pydantic/blob/32ea570bf96e84234d2992e1ddf40ab8a565925a/pydantic/main.py#L49 -IncEx: TypeAlias = "set[int] | set[str] | dict[int, Any] | dict[str, Any] | None" +IncEx: TypeAlias = Union[ + Set[int], Set[str], Mapping[int, Union["IncEx", Literal[True]]], Mapping[str, Union["IncEx", Literal[True]]] +] PostParser = Callable[[Any], Any] diff --git a/src/openai/lib/streaming/chat/_completions.py b/src/openai/lib/streaming/chat/_completions.py index a4b0f856f7..8518de967f 100644 --- a/src/openai/lib/streaming/chat/_completions.py +++ b/src/openai/lib/streaming/chat/_completions.py @@ -23,7 +23,7 @@ FunctionToolCallArgumentsDeltaEvent, ) from .._deltas import accumulate_delta -from ...._types import NOT_GIVEN, NotGiven +from ...._types import NOT_GIVEN, IncEx, NotGiven from ...._utils import is_given, consume_sync_iterator, consume_async_iterator from ...._compat import model_dump from ...._models import build, construct_type @@ -352,13 +352,17 @@ def _accumulate_chunk(self, chunk: ChatCompletionChunk) -> ParsedChatCompletionS # we don't want to serialise / deserialise our custom properties # as they won't appear in the delta and we don't want to have to # continuosly reparse the content - exclude={ - "parsed": True, - "tool_calls": { - idx: {"function": {"parsed_arguments": True}} - for idx, _ in enumerate(choice_snapshot.message.tool_calls or []) + exclude=cast( + # cast required as mypy isn't smart enough to infer `True` here to `Literal[True]` + IncEx, + { + "parsed": True, + "tool_calls": { + idx: {"function": {"parsed_arguments": True}} + for idx, _ in enumerate(choice_snapshot.message.tool_calls or []) + }, }, - }, + ), ), ), cast("dict[object, object]", choice.delta.to_dict()), diff --git a/tests/conftest.py b/tests/conftest.py index 15af57e770..fa82d39d86 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,11 +1,11 @@ from __future__ import annotations import os -import asyncio import logging from typing import TYPE_CHECKING, Iterator, AsyncIterator import pytest +from pytest_asyncio import is_async_test from openai import OpenAI, AsyncOpenAI @@ -17,11 +17,13 @@ logging.getLogger("openai").setLevel(logging.DEBUG) -@pytest.fixture(scope="session") -def event_loop() -> Iterator[asyncio.AbstractEventLoop]: - loop = asyncio.new_event_loop() - yield loop - loop.close() +# automatically add `pytest.mark.asyncio()` to all of our async tests +# so we don't have to add that boilerplate everywhere +def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: + pytest_asyncio_tests = (item for item in items if is_async_test(item)) + session_scope_marker = pytest.mark.asyncio(loop_scope="session") + for async_test in pytest_asyncio_tests: + async_test.add_marker(session_scope_marker, append=False) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") diff --git a/tests/lib/test_old_api.py b/tests/lib/test_old_api.py index 261b8acb94..bdb2a5398d 100644 --- a/tests/lib/test_old_api.py +++ b/tests/lib/test_old_api.py @@ -6,7 +6,7 @@ def test_basic_attribute_access_works() -> None: for attr in dir(openai): - dir(getattr(openai, attr)) + getattr(openai, attr) def test_helpful_error_is_raised() -> None: