diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4399a56..f79d778 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.18" + ".": "0.0.19" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 9aa0349..aea62f4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 40 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/plastic-labs%2Fhoncho-e4c301de216e3c01c130dfbf82f7d5272939867cc4b452aa00d6f0e081767bec.yml +configured_endpoints: 41 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/plastic-labs%2Fhoncho-9c89a1623da5f8289d05c3c8a8fa7778d7d89f8679e4e8a3589c1cb2735c70aa.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 7095f0b..6c51742 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.0.19 (2024-12-16) + +Full Changelog: [v0.0.18...v0.0.19](https://github.com/plastic-labs/honcho-python/compare/v0.0.18...v0.0.19) + +### Features + +* **api:** api update ([#82](https://github.com/plastic-labs/honcho-python/issues/82)) ([f295a74](https://github.com/plastic-labs/honcho-python/commit/f295a748dd5a168878b14515b5601d462f56a9d8)) + + +### Chores + +* **internal:** add support for TypeAliasType ([#78](https://github.com/plastic-labs/honcho-python/issues/78)) ([66e0d96](https://github.com/plastic-labs/honcho-python/commit/66e0d96e66ec4981bf2cd31eb717eff80fde9041)) +* **internal:** bump pydantic dependency ([#74](https://github.com/plastic-labs/honcho-python/issues/74)) ([43ea1de](https://github.com/plastic-labs/honcho-python/commit/43ea1dec3ad6e2a28fd5cbe101a63201c8937f8a)) +* **internal:** bump pyright ([#77](https://github.com/plastic-labs/honcho-python/issues/77)) ([b613832](https://github.com/plastic-labs/honcho-python/commit/b613832984ab0dbb5f82dc83808b679e87e6944e)) +* **internal:** codegen related update ([#79](https://github.com/plastic-labs/honcho-python/issues/79)) ([62d7c38](https://github.com/plastic-labs/honcho-python/commit/62d7c38c172a8761b880a0eb7996d01737d3786f)) +* **internal:** codegen related update ([#80](https://github.com/plastic-labs/honcho-python/issues/80)) ([e5b574e](https://github.com/plastic-labs/honcho-python/commit/e5b574e0b9897036ff2f06e725dc86492973a893)) +* **internal:** codegen related update ([#81](https://github.com/plastic-labs/honcho-python/issues/81)) ([9a4cd72](https://github.com/plastic-labs/honcho-python/commit/9a4cd72e6225d2a70870b2f1853e98039747e55c)) + + +### Documentation + +* **readme:** fix http client proxies example ([#76](https://github.com/plastic-labs/honcho-python/issues/76)) ([30cacbf](https://github.com/plastic-labs/honcho-python/commit/30cacbf37ea84226175ccc1dcef2964a8e7392ad)) + ## 0.0.18 (2024-12-04) Full Changelog: [v0.0.17...v0.0.18](https://github.com/plastic-labs/honcho-python/compare/v0.0.17...v0.0.18) diff --git a/README.md b/README.md index 3e2c945..200f918 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ client = Honcho( ) app = client.apps.create( - name="name", + name="x", ) print(app.id) ``` @@ -62,7 +62,7 @@ client = AsyncHoncho( async def main() -> None: app = await client.apps.create( - name="name", + name="x", ) print(app.id) @@ -169,7 +169,7 @@ client = Honcho() try: client.apps.create( - name="name", + name="x", ) except honcho.APIConnectionError as e: print("The server could not be reached") @@ -214,7 +214,7 @@ client = Honcho( # Or, configure per-request: client.with_options(max_retries=5).apps.create( - name="name", + name="x", ) ``` @@ -239,7 +239,7 @@ client = Honcho( # Override per-request: client.with_options(timeout=5.0).apps.create( - name="name", + name="x", ) ``` @@ -282,7 +282,7 @@ from honcho import Honcho client = Honcho() response = client.apps.with_raw_response.create( - name="name", + name="x", ) print(response.headers.get('X-My-Header')) @@ -302,7 +302,7 @@ To stream the response body, use `.with_streaming_response` instead, which requi ```python with client.apps.with_streaming_response.create( - name="name", + name="x", ) as response: print(response.headers.get("X-My-Header")) @@ -351,18 +351,19 @@ can also get all the extra fields on the Pydantic model as a dict with You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including: -- Support for proxies -- Custom transports +- Support for [proxies](https://www.python-httpx.org/advanced/proxies/) +- Custom [transports](https://www.python-httpx.org/advanced/transports/) - Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality ```python +import httpx from honcho import Honcho, DefaultHttpxClient client = Honcho( # Or use the `HONCHO_BASE_URL` env var base_url="http://my.test.server.example.com:8083", http_client=DefaultHttpxClient( - proxies="http://my.test.proxy.example.com", + proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0"), ), ) diff --git a/api.md b/api.md index d8a2cfe..2a88fcd 100644 --- a/api.md +++ b/api.md @@ -67,7 +67,7 @@ Methods: Types: ```python -from honcho.types.apps.users.sessions import Message, PageMessage +from honcho.types.apps.users.sessions import Message, PageMessage, MessageBatchResponse ``` Methods: @@ -75,6 +75,7 @@ Methods: - client.apps.users.sessions.messages.create(session_id, \*, app_id, user_id, \*\*params) -> Message - client.apps.users.sessions.messages.update(message_id, \*, app_id, user_id, session_id, \*\*params) -> Message - client.apps.users.sessions.messages.list(session_id, \*, app_id, user_id, \*\*params) -> SyncPage[Message] +- client.apps.users.sessions.messages.batch(session_id, \*, app_id, user_id, \*\*params) -> MessageBatchResponse - client.apps.users.sessions.messages.get(message_id, \*, app_id, user_id, session_id) -> Message #### Metamessages diff --git a/pyproject.toml b/pyproject.toml index 740791b..60e8a83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "honcho-ai" -version = "0.0.18" +version = "0.0.19" description = "The official Python library for the honcho API" dynamic = ["readme"] license = "Apache-2.0" @@ -10,7 +10,7 @@ authors = [ dependencies = [ "httpx>=0.23.0, <1", "pydantic>=1.9.0, <3", - "typing-extensions>=4.7, <5", + "typing-extensions>=4.10, <5", "anyio>=3.5.0, <5", "distro>=1.7.0, <2", "sniffio", diff --git a/requirements-dev.lock b/requirements-dev.lock index 08644e4..189f1f9 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -62,13 +62,13 @@ platformdirs==3.11.0 # via virtualenv pluggy==1.5.0 # via pytest -pydantic==2.9.2 +pydantic==2.10.3 # via honcho-ai -pydantic-core==2.23.4 +pydantic-core==2.27.1 # via pydantic pygments==2.18.0 # via rich -pyright==1.1.389 +pyright==1.1.390 pytest==8.3.3 # via pytest-asyncio pytest-asyncio==0.24.0 diff --git a/requirements.lock b/requirements.lock index 53fb9ab..32e8358 100644 --- a/requirements.lock +++ b/requirements.lock @@ -30,9 +30,9 @@ httpx==0.25.2 idna==3.4 # via anyio # via httpx -pydantic==2.9.2 +pydantic==2.10.3 # via honcho-ai -pydantic-core==2.23.4 +pydantic-core==2.27.1 # via pydantic sniffio==1.3.0 # via anyio diff --git a/src/honcho/_client.py b/src/honcho/_client.py index 844ae11..6da443c 100644 --- a/src/honcho/_client.py +++ b/src/honcho/_client.py @@ -8,7 +8,7 @@ import httpx -from . import resources, _exceptions +from . import _exceptions from ._qs import Querystring from ._types import ( NOT_GIVEN, @@ -31,6 +31,7 @@ SyncAPIClient, AsyncAPIClient, ) +from .resources.apps import apps __all__ = [ "ENVIRONMENTS", @@ -38,7 +39,6 @@ "Transport", "ProxiesTypes", "RequestOptions", - "resources", "Honcho", "AsyncHoncho", "Client", @@ -52,7 +52,7 @@ class Honcho(SyncAPIClient): - apps: resources.AppsResource + apps: apps.AppsResource with_raw_response: HonchoWithRawResponse with_streaming_response: HonchoWithStreamedResponse @@ -130,7 +130,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.apps = resources.AppsResource(self) + self.apps = apps.AppsResource(self) self.with_raw_response = HonchoWithRawResponse(self) self.with_streaming_response = HonchoWithStreamedResponse(self) @@ -244,7 +244,7 @@ def _make_status_error( class AsyncHoncho(AsyncAPIClient): - apps: resources.AsyncAppsResource + apps: apps.AsyncAppsResource with_raw_response: AsyncHonchoWithRawResponse with_streaming_response: AsyncHonchoWithStreamedResponse @@ -322,7 +322,7 @@ def __init__( _strict_response_validation=_strict_response_validation, ) - self.apps = resources.AsyncAppsResource(self) + self.apps = apps.AsyncAppsResource(self) self.with_raw_response = AsyncHonchoWithRawResponse(self) self.with_streaming_response = AsyncHonchoWithStreamedResponse(self) @@ -437,22 +437,22 @@ def _make_status_error( class HonchoWithRawResponse: def __init__(self, client: Honcho) -> None: - self.apps = resources.AppsResourceWithRawResponse(client.apps) + self.apps = apps.AppsResourceWithRawResponse(client.apps) class AsyncHonchoWithRawResponse: def __init__(self, client: AsyncHoncho) -> None: - self.apps = resources.AsyncAppsResourceWithRawResponse(client.apps) + self.apps = apps.AsyncAppsResourceWithRawResponse(client.apps) class HonchoWithStreamedResponse: def __init__(self, client: Honcho) -> None: - self.apps = resources.AppsResourceWithStreamingResponse(client.apps) + self.apps = apps.AppsResourceWithStreamingResponse(client.apps) class AsyncHonchoWithStreamedResponse: def __init__(self, client: AsyncHoncho) -> None: - self.apps = resources.AsyncAppsResourceWithStreamingResponse(client.apps) + self.apps = apps.AsyncAppsResourceWithStreamingResponse(client.apps) Client = Honcho diff --git a/src/honcho/_models.py b/src/honcho/_models.py index 6cb469e..7a547ce 100644 --- a/src/honcho/_models.py +++ b/src/honcho/_models.py @@ -46,6 +46,7 @@ strip_not_given, extract_type_arg, is_annotated_type, + is_type_alias_type, strip_annotated_type, ) from ._compat import ( @@ -428,6 +429,8 @@ def construct_type(*, value: object, type_: object) -> object: # we allow `object` as the input type because otherwise, passing things like # `Literal['value']` will be reported as a type error by type checkers type_ = cast("type[object]", type_) + if is_type_alias_type(type_): + type_ = type_.__value__ # type: ignore[unreachable] # unwrap `Annotated[T, ...]` -> `T` if is_annotated_type(type_): diff --git a/src/honcho/_response.py b/src/honcho/_response.py index 3bf2a87..d27333b 100644 --- a/src/honcho/_response.py +++ b/src/honcho/_response.py @@ -25,7 +25,7 @@ import pydantic from ._types import NoneType -from ._utils import is_given, extract_type_arg, is_annotated_type, extract_type_var_from_base +from ._utils import is_given, extract_type_arg, is_annotated_type, is_type_alias_type, extract_type_var_from_base from ._models import BaseModel, is_basemodel from ._constants import RAW_RESPONSE_HEADER, OVERRIDE_CAST_TO_HEADER from ._streaming import Stream, AsyncStream, is_stream_class_type, extract_stream_chunk_type @@ -126,9 +126,15 @@ def __repr__(self) -> str: ) def _parse(self, *, to: type[_T] | None = None) -> R | _T: + cast_to = to if to is not None else self._cast_to + + # unwrap `TypeAlias('Name', T)` -> `T` + if is_type_alias_type(cast_to): + cast_to = cast_to.__value__ # type: ignore[unreachable] + # unwrap `Annotated[T, ...]` -> `T` - if to and is_annotated_type(to): - to = extract_type_arg(to, 0) + if cast_to and is_annotated_type(cast_to): + cast_to = extract_type_arg(cast_to, 0) if self._is_sse_stream: if to: @@ -164,18 +170,12 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T: return cast( R, stream_cls( - cast_to=self._cast_to, + cast_to=cast_to, response=self.http_response, client=cast(Any, self._client), ), ) - cast_to = to if to is not None else self._cast_to - - # unwrap `Annotated[T, ...]` -> `T` - if is_annotated_type(cast_to): - cast_to = extract_type_arg(cast_to, 0) - if cast_to is NoneType: return cast(R, None) diff --git a/src/honcho/_types.py b/src/honcho/_types.py index b993317..df95613 100644 --- a/src/honcho/_types.py +++ b/src/honcho/_types.py @@ -192,10 +192,8 @@ def get(self, __key: str) -> str | None: ... StrBytesIntFloat = Union[str, bytes, int, float] # Note: copied from Pydantic -# https://github.com/pydantic/pydantic/blob/32ea570bf96e84234d2992e1ddf40ab8a565925a/pydantic/main.py#L49 -IncEx: TypeAlias = Union[ - Set[int], Set[str], Mapping[int, Union["IncEx", Literal[True]]], Mapping[str, Union["IncEx", Literal[True]]] -] +# https://github.com/pydantic/pydantic/blob/6f31f8f68ef011f84357330186f603ff295312fd/pydantic/main.py#L79 +IncEx: TypeAlias = Union[Set[int], Set[str], Mapping[int, Union["IncEx", bool]], Mapping[str, Union["IncEx", bool]]] PostParser = Callable[[Any], Any] diff --git a/src/honcho/_utils/__init__.py b/src/honcho/_utils/__init__.py index a7cff3c..d4fda26 100644 --- a/src/honcho/_utils/__init__.py +++ b/src/honcho/_utils/__init__.py @@ -39,6 +39,7 @@ is_iterable_type as is_iterable_type, is_required_type as is_required_type, is_annotated_type as is_annotated_type, + is_type_alias_type as is_type_alias_type, strip_annotated_type as strip_annotated_type, extract_type_var_from_base as extract_type_var_from_base, ) diff --git a/src/honcho/_utils/_typing.py b/src/honcho/_utils/_typing.py index c036991..278749b 100644 --- a/src/honcho/_utils/_typing.py +++ b/src/honcho/_utils/_typing.py @@ -1,8 +1,17 @@ from __future__ import annotations +import sys +import typing +import typing_extensions from typing import Any, TypeVar, Iterable, cast from collections import abc as _c_abc -from typing_extensions import Required, Annotated, get_args, get_origin +from typing_extensions import ( + TypeIs, + Required, + Annotated, + get_args, + get_origin, +) from .._types import InheritsGeneric from .._compat import is_union as _is_union @@ -36,6 +45,26 @@ def is_typevar(typ: type) -> bool: return type(typ) == TypeVar # type: ignore +_TYPE_ALIAS_TYPES: tuple[type[typing_extensions.TypeAliasType], ...] = (typing_extensions.TypeAliasType,) +if sys.version_info >= (3, 12): + _TYPE_ALIAS_TYPES = (*_TYPE_ALIAS_TYPES, typing.TypeAliasType) + + +def is_type_alias_type(tp: Any, /) -> TypeIs[typing_extensions.TypeAliasType]: + """Return whether the provided argument is an instance of `TypeAliasType`. + + ```python + type Int = int + is_type_alias_type(Int) + # > True + Str = TypeAliasType("Str", str) + is_type_alias_type(Str) + # > True + ``` + """ + return isinstance(tp, _TYPE_ALIAS_TYPES) + + # Extracts T from Annotated[T, ...] or from Required[Annotated[T, ...]] def strip_annotated_type(typ: type) -> type: if is_required_type(typ) or is_annotated_type(typ): diff --git a/src/honcho/_version.py b/src/honcho/_version.py index f4fd253..cbd11a5 100644 --- a/src/honcho/_version.py +++ b/src/honcho/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "honcho" -__version__ = "0.0.18" # x-release-please-version +__version__ = "0.0.19" # x-release-please-version diff --git a/src/honcho/resources/apps/apps.py b/src/honcho/resources/apps/apps.py index cc5013e..2138f32 100644 --- a/src/honcho/resources/apps/apps.py +++ b/src/honcho/resources/apps/apps.py @@ -6,14 +6,6 @@ import httpx -from .users import ( - UsersResource, - AsyncUsersResource, - UsersResourceWithRawResponse, - AsyncUsersResourceWithRawResponse, - UsersResourceWithStreamingResponse, - AsyncUsersResourceWithStreamingResponse, -) from ...types import app_create_params, app_update_params from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ..._utils import ( @@ -29,7 +21,14 @@ async_to_streamed_response_wrapper, ) from ...types.app import App -from .users.users import UsersResource, AsyncUsersResource +from .users.users import ( + UsersResource, + AsyncUsersResource, + UsersResourceWithRawResponse, + AsyncUsersResourceWithRawResponse, + UsersResourceWithStreamingResponse, + AsyncUsersResourceWithStreamingResponse, +) from ..._base_client import make_request_options __all__ = ["AppsResource", "AsyncAppsResource"] diff --git a/src/honcho/resources/apps/users/collections/collections.py b/src/honcho/resources/apps/users/collections/collections.py index 847bec5..46a2bf7 100644 --- a/src/honcho/resources/apps/users/collections/collections.py +++ b/src/honcho/resources/apps/users/collections/collections.py @@ -65,7 +65,7 @@ def create( *, app_id: str, name: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -358,7 +358,7 @@ async def create( *, app_id: str, name: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/honcho/resources/apps/users/collections/documents.py b/src/honcho/resources/apps/users/collections/documents.py index cd6f010..de7a276 100644 --- a/src/honcho/resources/apps/users/collections/documents.py +++ b/src/honcho/resources/apps/users/collections/documents.py @@ -60,7 +60,7 @@ def create( app_id: str, user_id: str, content: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -375,7 +375,7 @@ async def create( app_id: str, user_id: str, content: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/honcho/resources/apps/users/sessions/messages.py b/src/honcho/resources/apps/users/sessions/messages.py index 944eff5..88b040b 100644 --- a/src/honcho/resources/apps/users/sessions/messages.py +++ b/src/honcho/resources/apps/users/sessions/messages.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict, Iterable, Optional import httpx @@ -21,8 +21,14 @@ ) from .....pagination import SyncPage, AsyncPage from ....._base_client import AsyncPaginator, make_request_options -from .....types.apps.users.sessions import message_list_params, message_create_params, message_update_params +from .....types.apps.users.sessions import ( + message_list_params, + message_batch_params, + message_create_params, + message_update_params, +) from .....types.apps.users.sessions.message import Message +from .....types.apps.users.sessions.message_batch_response import MessageBatchResponse __all__ = ["MessagesResource", "AsyncMessagesResource"] @@ -104,7 +110,7 @@ def update( app_id: str, user_id: str, session_id: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -202,6 +208,49 @@ def list( method="post", ) + def batch( + self, + session_id: str, + *, + app_id: str, + user_id: str, + messages: Iterable[message_batch_params.Message], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MessageBatchResponse: + """Bulk create messages for a session while maintaining order. + + Maximum 100 messages + per batch. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not app_id: + raise ValueError(f"Expected a non-empty value for `app_id` but received {app_id!r}") + if not user_id: + raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}") + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + return self._post( + f"/v1/apps/{app_id}/users/{user_id}/sessions/{session_id}/messages/batch", + body=maybe_transform({"messages": messages}, message_batch_params.MessageBatchParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MessageBatchResponse, + ) + def get( self, message_id: str, @@ -322,7 +371,7 @@ async def update( app_id: str, user_id: str, session_id: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -420,6 +469,49 @@ def list( method="post", ) + async def batch( + self, + session_id: str, + *, + app_id: str, + user_id: str, + messages: Iterable[message_batch_params.Message], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> MessageBatchResponse: + """Bulk create messages for a session while maintaining order. + + Maximum 100 messages + per batch. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not app_id: + raise ValueError(f"Expected a non-empty value for `app_id` but received {app_id!r}") + if not user_id: + raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}") + if not session_id: + raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}") + return await self._post( + f"/v1/apps/{app_id}/users/{user_id}/sessions/{session_id}/messages/batch", + body=await async_maybe_transform({"messages": messages}, message_batch_params.MessageBatchParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MessageBatchResponse, + ) + async def get( self, message_id: str, @@ -476,6 +568,9 @@ def __init__(self, messages: MessagesResource) -> None: self.list = to_raw_response_wrapper( messages.list, ) + self.batch = to_raw_response_wrapper( + messages.batch, + ) self.get = to_raw_response_wrapper( messages.get, ) @@ -494,6 +589,9 @@ def __init__(self, messages: AsyncMessagesResource) -> None: self.list = async_to_raw_response_wrapper( messages.list, ) + self.batch = async_to_raw_response_wrapper( + messages.batch, + ) self.get = async_to_raw_response_wrapper( messages.get, ) @@ -512,6 +610,9 @@ def __init__(self, messages: MessagesResource) -> None: self.list = to_streamed_response_wrapper( messages.list, ) + self.batch = to_streamed_response_wrapper( + messages.batch, + ) self.get = to_streamed_response_wrapper( messages.get, ) @@ -530,6 +631,9 @@ def __init__(self, messages: AsyncMessagesResource) -> None: self.list = async_to_streamed_response_wrapper( messages.list, ) + self.batch = async_to_streamed_response_wrapper( + messages.batch, + ) self.get = async_to_streamed_response_wrapper( messages.get, ) diff --git a/src/honcho/resources/apps/users/sessions/metamessages.py b/src/honcho/resources/apps/users/sessions/metamessages.py index 087d839..f6edab2 100644 --- a/src/honcho/resources/apps/users/sessions/metamessages.py +++ b/src/honcho/resources/apps/users/sessions/metamessages.py @@ -61,7 +61,7 @@ def create( content: str, message_id: str, metamessage_type: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -304,7 +304,7 @@ async def create( content: str, message_id: str, metamessage_type: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/honcho/resources/apps/users/sessions/sessions.py b/src/honcho/resources/apps/users/sessions/sessions.py index 4fe1948..0a6fa5c 100644 --- a/src/honcho/resources/apps/users/sessions/sessions.py +++ b/src/honcho/resources/apps/users/sessions/sessions.py @@ -123,7 +123,7 @@ def update( *, app_id: str, user_id: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -507,7 +507,7 @@ async def update( *, app_id: str, user_id: str, - metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, + metadata: Dict[str, object], # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, diff --git a/src/honcho/resources/apps/users/users.py b/src/honcho/resources/apps/users/users.py index 1c10672..77cb387 100644 --- a/src/honcho/resources/apps/users/users.py +++ b/src/honcho/resources/apps/users/users.py @@ -6,28 +6,12 @@ import httpx -from .sessions import ( - SessionsResource, - AsyncSessionsResource, - SessionsResourceWithRawResponse, - AsyncSessionsResourceWithRawResponse, - SessionsResourceWithStreamingResponse, - AsyncSessionsResourceWithStreamingResponse, -) from ...._types import NOT_GIVEN, Body, Query, Headers, NotGiven from ...._utils import ( maybe_transform, async_maybe_transform, ) from ...._compat import cached_property -from .collections import ( - CollectionsResource, - AsyncCollectionsResource, - CollectionsResourceWithRawResponse, - AsyncCollectionsResourceWithRawResponse, - CollectionsResourceWithStreamingResponse, - AsyncCollectionsResourceWithStreamingResponse, -) from ...._resource import SyncAPIResource, AsyncAPIResource from ...._response import ( to_raw_response_wrapper, @@ -46,9 +30,23 @@ from ....pagination import SyncPage, AsyncPage from ....types.apps import user_list_params, user_create_params, user_update_params from ...._base_client import AsyncPaginator, make_request_options -from .sessions.sessions import SessionsResource, AsyncSessionsResource +from .sessions.sessions import ( + SessionsResource, + AsyncSessionsResource, + SessionsResourceWithRawResponse, + AsyncSessionsResourceWithRawResponse, + SessionsResourceWithStreamingResponse, + AsyncSessionsResourceWithStreamingResponse, +) from ....types.apps.user import User -from .collections.collections import CollectionsResource, AsyncCollectionsResource +from .collections.collections import ( + CollectionsResource, + AsyncCollectionsResource, + CollectionsResourceWithRawResponse, + AsyncCollectionsResourceWithRawResponse, + CollectionsResourceWithStreamingResponse, + AsyncCollectionsResourceWithStreamingResponse, +) __all__ = ["UsersResource", "AsyncUsersResource"] diff --git a/src/honcho/types/apps/users/collection_create_params.py b/src/honcho/types/apps/users/collection_create_params.py index 434b8f9..c98672f 100644 --- a/src/honcho/types/apps/users/collection_create_params.py +++ b/src/honcho/types/apps/users/collection_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict from typing_extensions import Required, TypedDict __all__ = ["CollectionCreateParams"] @@ -13,4 +13,4 @@ class CollectionCreateParams(TypedDict, total=False): name: Required[str] - metadata: Optional[Dict[str, object]] + metadata: Dict[str, object] diff --git a/src/honcho/types/apps/users/collections/document_create_params.py b/src/honcho/types/apps/users/collections/document_create_params.py index f014a94..5851a39 100644 --- a/src/honcho/types/apps/users/collections/document_create_params.py +++ b/src/honcho/types/apps/users/collections/document_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict from typing_extensions import Required, TypedDict __all__ = ["DocumentCreateParams"] @@ -15,4 +15,4 @@ class DocumentCreateParams(TypedDict, total=False): content: Required[str] - metadata: Optional[Dict[str, object]] + metadata: Dict[str, object] diff --git a/src/honcho/types/apps/users/session_update_params.py b/src/honcho/types/apps/users/session_update_params.py index 49da04e..19fbe26 100644 --- a/src/honcho/types/apps/users/session_update_params.py +++ b/src/honcho/types/apps/users/session_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict from typing_extensions import Required, TypedDict __all__ = ["SessionUpdateParams"] @@ -13,4 +13,4 @@ class SessionUpdateParams(TypedDict, total=False): user_id: Required[str] - metadata: Optional[Dict[str, object]] + metadata: Required[Dict[str, object]] diff --git a/src/honcho/types/apps/users/sessions/__init__.py b/src/honcho/types/apps/users/sessions/__init__.py index 54bcf9b..58d1a9f 100644 --- a/src/honcho/types/apps/users/sessions/__init__.py +++ b/src/honcho/types/apps/users/sessions/__init__.py @@ -7,8 +7,10 @@ from .page_message import PageMessage as PageMessage from .page_metamessage import PageMetamessage as PageMetamessage from .message_list_params import MessageListParams as MessageListParams +from .message_batch_params import MessageBatchParams as MessageBatchParams from .message_create_params import MessageCreateParams as MessageCreateParams from .message_update_params import MessageUpdateParams as MessageUpdateParams +from .message_batch_response import MessageBatchResponse as MessageBatchResponse from .metamessage_get_params import MetamessageGetParams as MetamessageGetParams from .metamessage_list_params import MetamessageListParams as MetamessageListParams from .metamessage_create_params import MetamessageCreateParams as MetamessageCreateParams diff --git a/src/honcho/types/apps/users/sessions/message_batch_params.py b/src/honcho/types/apps/users/sessions/message_batch_params.py new file mode 100644 index 0000000..af30a67 --- /dev/null +++ b/src/honcho/types/apps/users/sessions/message_batch_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Iterable +from typing_extensions import Required, TypedDict + +__all__ = ["MessageBatchParams", "Message"] + + +class MessageBatchParams(TypedDict, total=False): + app_id: Required[str] + + user_id: Required[str] + + messages: Required[Iterable[Message]] + + +class Message(TypedDict, total=False): + content: Required[str] + + is_user: Required[bool] + + metadata: Dict[str, object] diff --git a/src/honcho/types/apps/users/sessions/message_batch_response.py b/src/honcho/types/apps/users/sessions/message_batch_response.py new file mode 100644 index 0000000..e114857 --- /dev/null +++ b/src/honcho/types/apps/users/sessions/message_batch_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import TypeAlias + +from .message import Message + +__all__ = ["MessageBatchResponse"] + +MessageBatchResponse: TypeAlias = List[Message] diff --git a/src/honcho/types/apps/users/sessions/message_update_params.py b/src/honcho/types/apps/users/sessions/message_update_params.py index df422aa..e3409be 100644 --- a/src/honcho/types/apps/users/sessions/message_update_params.py +++ b/src/honcho/types/apps/users/sessions/message_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict from typing_extensions import Required, TypedDict __all__ = ["MessageUpdateParams"] @@ -15,4 +15,4 @@ class MessageUpdateParams(TypedDict, total=False): session_id: Required[str] - metadata: Optional[Dict[str, object]] + metadata: Required[Dict[str, object]] diff --git a/src/honcho/types/apps/users/sessions/metamessage_create_params.py b/src/honcho/types/apps/users/sessions/metamessage_create_params.py index 71a60d1..7632849 100644 --- a/src/honcho/types/apps/users/sessions/metamessage_create_params.py +++ b/src/honcho/types/apps/users/sessions/metamessage_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict from typing_extensions import Required, TypedDict __all__ = ["MetamessageCreateParams"] @@ -19,4 +19,4 @@ class MetamessageCreateParams(TypedDict, total=False): metamessage_type: Required[str] - metadata: Optional[Dict[str, object]] + metadata: Dict[str, object] diff --git a/tests/api_resources/apps/test_users.py b/tests/api_resources/apps/test_users.py index d8623af..0df68a7 100644 --- a/tests/api_resources/apps/test_users.py +++ b/tests/api_resources/apps/test_users.py @@ -22,7 +22,7 @@ class TestUsers: def test_method_create(self, client: Honcho) -> None: user = client.apps.users.create( app_id="app_id", - name="name", + name="x", ) assert_matches_type(User, user, path=["response"]) @@ -30,7 +30,7 @@ def test_method_create(self, client: Honcho) -> None: def test_method_create_with_all_params(self, client: Honcho) -> None: user = client.apps.users.create( app_id="app_id", - name="name", + name="x", metadata={"foo": "bar"}, ) assert_matches_type(User, user, path=["response"]) @@ -39,7 +39,7 @@ def test_method_create_with_all_params(self, client: Honcho) -> None: def test_raw_response_create(self, client: Honcho) -> None: response = client.apps.users.with_raw_response.create( app_id="app_id", - name="name", + name="x", ) assert response.is_closed is True @@ -51,7 +51,7 @@ def test_raw_response_create(self, client: Honcho) -> None: def test_streaming_response_create(self, client: Honcho) -> None: with client.apps.users.with_streaming_response.create( app_id="app_id", - name="name", + name="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -66,7 +66,7 @@ def test_path_params_create(self, client: Honcho) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `app_id` but received ''"): client.apps.users.with_raw_response.create( app_id="", - name="name", + name="x", ) @parametrize @@ -328,7 +328,7 @@ class TestAsyncUsers: async def test_method_create(self, async_client: AsyncHoncho) -> None: user = await async_client.apps.users.create( app_id="app_id", - name="name", + name="x", ) assert_matches_type(User, user, path=["response"]) @@ -336,7 +336,7 @@ async def test_method_create(self, async_client: AsyncHoncho) -> None: async def test_method_create_with_all_params(self, async_client: AsyncHoncho) -> None: user = await async_client.apps.users.create( app_id="app_id", - name="name", + name="x", metadata={"foo": "bar"}, ) assert_matches_type(User, user, path=["response"]) @@ -345,7 +345,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncHoncho) -> async def test_raw_response_create(self, async_client: AsyncHoncho) -> None: response = await async_client.apps.users.with_raw_response.create( app_id="app_id", - name="name", + name="x", ) assert response.is_closed is True @@ -357,7 +357,7 @@ async def test_raw_response_create(self, async_client: AsyncHoncho) -> None: async def test_streaming_response_create(self, async_client: AsyncHoncho) -> None: async with async_client.apps.users.with_streaming_response.create( app_id="app_id", - name="name", + name="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -372,7 +372,7 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `app_id` but received ''"): await async_client.apps.users.with_raw_response.create( app_id="", - name="name", + name="x", ) @parametrize diff --git a/tests/api_resources/apps/users/collections/test_documents.py b/tests/api_resources/apps/users/collections/test_documents.py index a2c4f2f..afddd2d 100644 --- a/tests/api_resources/apps/users/collections/test_documents.py +++ b/tests/api_resources/apps/users/collections/test_documents.py @@ -27,7 +27,7 @@ def test_method_create(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", ) assert_matches_type(Document, document, path=["response"]) @@ -37,7 +37,7 @@ def test_method_create_with_all_params(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", metadata={"foo": "bar"}, ) assert_matches_type(Document, document, path=["response"]) @@ -48,7 +48,7 @@ def test_raw_response_create(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", ) assert response.is_closed is True @@ -62,7 +62,7 @@ def test_streaming_response_create(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -79,7 +79,7 @@ def test_path_params_create(self, client: Honcho) -> None: collection_id="collection_id", app_id="", user_id="user_id", - content="content", + content="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -87,7 +87,7 @@ def test_path_params_create(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="", - content="content", + content="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `collection_id` but received ''"): @@ -95,7 +95,7 @@ def test_path_params_create(self, client: Honcho) -> None: collection_id="", app_id="app_id", user_id="user_id", - content="content", + content="x", ) @parametrize @@ -115,7 +115,7 @@ def test_method_update_with_all_params(self, client: Honcho) -> None: app_id="app_id", user_id="user_id", collection_id="collection_id", - content="content", + content="x", metadata={"foo": "bar"}, ) assert_matches_type(Document, document, path=["response"]) @@ -411,7 +411,7 @@ def test_method_query(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", ) assert_matches_type(DocumentQueryResponse, document, path=["response"]) @@ -421,9 +421,9 @@ def test_method_query_with_all_params(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", filter={"foo": "bar"}, - top_k=0, + top_k=1, ) assert_matches_type(DocumentQueryResponse, document, path=["response"]) @@ -433,7 +433,7 @@ def test_raw_response_query(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", ) assert response.is_closed is True @@ -447,7 +447,7 @@ def test_streaming_response_query(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -464,7 +464,7 @@ def test_path_params_query(self, client: Honcho) -> None: collection_id="collection_id", app_id="", user_id="user_id", - query="query", + query="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -472,7 +472,7 @@ def test_path_params_query(self, client: Honcho) -> None: collection_id="collection_id", app_id="app_id", user_id="", - query="query", + query="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `collection_id` but received ''"): @@ -480,7 +480,7 @@ def test_path_params_query(self, client: Honcho) -> None: collection_id="", app_id="app_id", user_id="user_id", - query="query", + query="x", ) @@ -493,7 +493,7 @@ async def test_method_create(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", ) assert_matches_type(Document, document, path=["response"]) @@ -503,7 +503,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncHoncho) -> collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", metadata={"foo": "bar"}, ) assert_matches_type(Document, document, path=["response"]) @@ -514,7 +514,7 @@ async def test_raw_response_create(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", ) assert response.is_closed is True @@ -528,7 +528,7 @@ async def test_streaming_response_create(self, async_client: AsyncHoncho) -> Non collection_id="collection_id", app_id="app_id", user_id="user_id", - content="content", + content="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -545,7 +545,7 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="", user_id="user_id", - content="content", + content="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -553,7 +553,7 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="app_id", user_id="", - content="content", + content="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `collection_id` but received ''"): @@ -561,7 +561,7 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: collection_id="", app_id="app_id", user_id="user_id", - content="content", + content="x", ) @parametrize @@ -581,7 +581,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncHoncho) -> app_id="app_id", user_id="user_id", collection_id="collection_id", - content="content", + content="x", metadata={"foo": "bar"}, ) assert_matches_type(Document, document, path=["response"]) @@ -877,7 +877,7 @@ async def test_method_query(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", ) assert_matches_type(DocumentQueryResponse, document, path=["response"]) @@ -887,9 +887,9 @@ async def test_method_query_with_all_params(self, async_client: AsyncHoncho) -> collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", filter={"foo": "bar"}, - top_k=0, + top_k=1, ) assert_matches_type(DocumentQueryResponse, document, path=["response"]) @@ -899,7 +899,7 @@ async def test_raw_response_query(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", ) assert response.is_closed is True @@ -913,7 +913,7 @@ async def test_streaming_response_query(self, async_client: AsyncHoncho) -> None collection_id="collection_id", app_id="app_id", user_id="user_id", - query="query", + query="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -930,7 +930,7 @@ async def test_path_params_query(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="", user_id="user_id", - query="query", + query="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -938,7 +938,7 @@ async def test_path_params_query(self, async_client: AsyncHoncho) -> None: collection_id="collection_id", app_id="app_id", user_id="", - query="query", + query="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `collection_id` but received ''"): @@ -946,5 +946,5 @@ async def test_path_params_query(self, async_client: AsyncHoncho) -> None: collection_id="", app_id="app_id", user_id="user_id", - query="query", + query="x", ) diff --git a/tests/api_resources/apps/users/sessions/test_messages.py b/tests/api_resources/apps/users/sessions/test_messages.py index f1288d9..211fa2c 100644 --- a/tests/api_resources/apps/users/sessions/test_messages.py +++ b/tests/api_resources/apps/users/sessions/test_messages.py @@ -10,7 +10,10 @@ from honcho import Honcho, AsyncHoncho from tests.utils import assert_matches_type from honcho.pagination import SyncPage, AsyncPage -from honcho.types.apps.users.sessions import Message +from honcho.types.apps.users.sessions import ( + Message, + MessageBatchResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -104,16 +107,6 @@ def test_path_params_create(self, client: Honcho) -> None: @parametrize def test_method_update(self, client: Honcho) -> None: - message = client.apps.users.sessions.messages.update( - message_id="message_id", - app_id="app_id", - user_id="user_id", - session_id="session_id", - ) - assert_matches_type(Message, message, path=["response"]) - - @parametrize - def test_method_update_with_all_params(self, client: Honcho) -> None: message = client.apps.users.sessions.messages.update( message_id="message_id", app_id="app_id", @@ -130,6 +123,7 @@ def test_raw_response_update(self, client: Honcho) -> None: app_id="app_id", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) assert response.is_closed is True @@ -144,6 +138,7 @@ def test_streaming_response_update(self, client: Honcho) -> None: app_id="app_id", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -161,6 +156,7 @@ def test_path_params_update(self, client: Honcho) -> None: app_id="", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -169,6 +165,7 @@ def test_path_params_update(self, client: Honcho) -> None: app_id="app_id", user_id="", session_id="session_id", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -177,6 +174,7 @@ def test_path_params_update(self, client: Honcho) -> None: app_id="app_id", user_id="user_id", session_id="", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): @@ -185,6 +183,7 @@ def test_path_params_update(self, client: Honcho) -> None: app_id="app_id", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) @parametrize @@ -260,6 +259,102 @@ def test_path_params_list(self, client: Honcho) -> None: user_id="user_id", ) + @parametrize + def test_method_batch(self, client: Honcho) -> None: + message = client.apps.users.sessions.messages.batch( + session_id="session_id", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + assert_matches_type(MessageBatchResponse, message, path=["response"]) + + @parametrize + def test_raw_response_batch(self, client: Honcho) -> None: + response = client.apps.users.sessions.messages.with_raw_response.batch( + session_id="session_id", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + message = response.parse() + assert_matches_type(MessageBatchResponse, message, path=["response"]) + + @parametrize + def test_streaming_response_batch(self, client: Honcho) -> None: + with client.apps.users.sessions.messages.with_streaming_response.batch( + session_id="session_id", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + message = response.parse() + assert_matches_type(MessageBatchResponse, message, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_batch(self, client: Honcho) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `app_id` but received ''"): + client.apps.users.sessions.messages.with_raw_response.batch( + session_id="session_id", + app_id="", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): + client.apps.users.sessions.messages.with_raw_response.batch( + session_id="session_id", + app_id="app_id", + user_id="", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + client.apps.users.sessions.messages.with_raw_response.batch( + session_id="", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + @parametrize def test_method_get(self, client: Honcho) -> None: message = client.apps.users.sessions.messages.get( @@ -424,16 +519,6 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: @parametrize async def test_method_update(self, async_client: AsyncHoncho) -> None: - message = await async_client.apps.users.sessions.messages.update( - message_id="message_id", - app_id="app_id", - user_id="user_id", - session_id="session_id", - ) - assert_matches_type(Message, message, path=["response"]) - - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncHoncho) -> None: message = await async_client.apps.users.sessions.messages.update( message_id="message_id", app_id="app_id", @@ -450,6 +535,7 @@ async def test_raw_response_update(self, async_client: AsyncHoncho) -> None: app_id="app_id", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) assert response.is_closed is True @@ -464,6 +550,7 @@ async def test_streaming_response_update(self, async_client: AsyncHoncho) -> Non app_id="app_id", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -481,6 +568,7 @@ async def test_path_params_update(self, async_client: AsyncHoncho) -> None: app_id="", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -489,6 +577,7 @@ async def test_path_params_update(self, async_client: AsyncHoncho) -> None: app_id="app_id", user_id="", session_id="session_id", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -497,6 +586,7 @@ async def test_path_params_update(self, async_client: AsyncHoncho) -> None: app_id="app_id", user_id="user_id", session_id="", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): @@ -505,6 +595,7 @@ async def test_path_params_update(self, async_client: AsyncHoncho) -> None: app_id="app_id", user_id="user_id", session_id="session_id", + metadata={"foo": "bar"}, ) @parametrize @@ -580,6 +671,102 @@ async def test_path_params_list(self, async_client: AsyncHoncho) -> None: user_id="user_id", ) + @parametrize + async def test_method_batch(self, async_client: AsyncHoncho) -> None: + message = await async_client.apps.users.sessions.messages.batch( + session_id="session_id", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + assert_matches_type(MessageBatchResponse, message, path=["response"]) + + @parametrize + async def test_raw_response_batch(self, async_client: AsyncHoncho) -> None: + response = await async_client.apps.users.sessions.messages.with_raw_response.batch( + session_id="session_id", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + message = await response.parse() + assert_matches_type(MessageBatchResponse, message, path=["response"]) + + @parametrize + async def test_streaming_response_batch(self, async_client: AsyncHoncho) -> None: + async with async_client.apps.users.sessions.messages.with_streaming_response.batch( + session_id="session_id", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + message = await response.parse() + assert_matches_type(MessageBatchResponse, message, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_batch(self, async_client: AsyncHoncho) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `app_id` but received ''"): + await async_client.apps.users.sessions.messages.with_raw_response.batch( + session_id="session_id", + app_id="", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): + await async_client.apps.users.sessions.messages.with_raw_response.batch( + session_id="session_id", + app_id="app_id", + user_id="", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): + await async_client.apps.users.sessions.messages.with_raw_response.batch( + session_id="", + app_id="app_id", + user_id="user_id", + messages=[ + { + "content": "content", + "is_user": True, + } + ], + ) + @parametrize async def test_method_get(self, async_client: AsyncHoncho) -> None: message = await async_client.apps.users.sessions.messages.get( diff --git a/tests/api_resources/apps/users/sessions/test_metamessages.py b/tests/api_resources/apps/users/sessions/test_metamessages.py index 4fcd638..3a89acf 100644 --- a/tests/api_resources/apps/users/sessions/test_metamessages.py +++ b/tests/api_resources/apps/users/sessions/test_metamessages.py @@ -28,7 +28,7 @@ def test_method_create(self, client: Honcho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) assert_matches_type(Metamessage, metamessage, path=["response"]) @@ -40,7 +40,7 @@ def test_method_create_with_all_params(self, client: Honcho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", metadata={"foo": "bar"}, ) assert_matches_type(Metamessage, metamessage, path=["response"]) @@ -53,7 +53,7 @@ def test_raw_response_create(self, client: Honcho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) assert response.is_closed is True @@ -69,7 +69,7 @@ def test_streaming_response_create(self, client: Honcho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -88,7 +88,7 @@ def test_path_params_create(self, client: Honcho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -98,7 +98,7 @@ def test_path_params_create(self, client: Honcho) -> None: user_id="", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -108,7 +108,7 @@ def test_path_params_create(self, client: Honcho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) @parametrize @@ -373,7 +373,7 @@ async def test_method_create(self, async_client: AsyncHoncho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) assert_matches_type(Metamessage, metamessage, path=["response"]) @@ -385,7 +385,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncHoncho) -> user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", metadata={"foo": "bar"}, ) assert_matches_type(Metamessage, metamessage, path=["response"]) @@ -398,7 +398,7 @@ async def test_raw_response_create(self, async_client: AsyncHoncho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) assert response.is_closed is True @@ -414,7 +414,7 @@ async def test_streaming_response_create(self, async_client: AsyncHoncho) -> Non user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -433,7 +433,7 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -443,7 +443,7 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: user_id="", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -453,7 +453,7 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: user_id="user_id", content="content", message_id="message_id", - metamessage_type="metamessage_type", + metamessage_type="x", ) @parametrize diff --git a/tests/api_resources/apps/users/test_collections.py b/tests/api_resources/apps/users/test_collections.py index 7295226..b9dc989 100644 --- a/tests/api_resources/apps/users/test_collections.py +++ b/tests/api_resources/apps/users/test_collections.py @@ -25,7 +25,7 @@ def test_method_create(self, client: Honcho) -> None: collection = client.apps.users.collections.create( user_id="user_id", app_id="app_id", - name="name", + name="x", ) assert_matches_type(Collection, collection, path=["response"]) @@ -34,7 +34,7 @@ def test_method_create_with_all_params(self, client: Honcho) -> None: collection = client.apps.users.collections.create( user_id="user_id", app_id="app_id", - name="name", + name="x", metadata={"foo": "bar"}, ) assert_matches_type(Collection, collection, path=["response"]) @@ -44,7 +44,7 @@ def test_raw_response_create(self, client: Honcho) -> None: response = client.apps.users.collections.with_raw_response.create( user_id="user_id", app_id="app_id", - name="name", + name="x", ) assert response.is_closed is True @@ -57,7 +57,7 @@ def test_streaming_response_create(self, client: Honcho) -> None: with client.apps.users.collections.with_streaming_response.create( user_id="user_id", app_id="app_id", - name="name", + name="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -73,14 +73,14 @@ def test_path_params_create(self, client: Honcho) -> None: client.apps.users.collections.with_raw_response.create( user_id="user_id", app_id="", - name="name", + name="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): client.apps.users.collections.with_raw_response.create( user_id="", app_id="app_id", - name="name", + name="x", ) @parametrize @@ -403,7 +403,7 @@ async def test_method_create(self, async_client: AsyncHoncho) -> None: collection = await async_client.apps.users.collections.create( user_id="user_id", app_id="app_id", - name="name", + name="x", ) assert_matches_type(Collection, collection, path=["response"]) @@ -412,7 +412,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncHoncho) -> collection = await async_client.apps.users.collections.create( user_id="user_id", app_id="app_id", - name="name", + name="x", metadata={"foo": "bar"}, ) assert_matches_type(Collection, collection, path=["response"]) @@ -422,7 +422,7 @@ async def test_raw_response_create(self, async_client: AsyncHoncho) -> None: response = await async_client.apps.users.collections.with_raw_response.create( user_id="user_id", app_id="app_id", - name="name", + name="x", ) assert response.is_closed is True @@ -435,7 +435,7 @@ async def test_streaming_response_create(self, async_client: AsyncHoncho) -> Non async with async_client.apps.users.collections.with_streaming_response.create( user_id="user_id", app_id="app_id", - name="name", + name="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -451,14 +451,14 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: await async_client.apps.users.collections.with_raw_response.create( user_id="user_id", app_id="", - name="name", + name="x", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): await async_client.apps.users.collections.with_raw_response.create( user_id="", app_id="app_id", - name="name", + name="x", ) @parametrize diff --git a/tests/api_resources/apps/users/test_sessions.py b/tests/api_resources/apps/users/test_sessions.py index 1218405..46cdcfe 100644 --- a/tests/api_resources/apps/users/test_sessions.py +++ b/tests/api_resources/apps/users/test_sessions.py @@ -80,15 +80,6 @@ def test_path_params_create(self, client: Honcho) -> None: @parametrize def test_method_update(self, client: Honcho) -> None: - session = client.apps.users.sessions.update( - session_id="session_id", - app_id="app_id", - user_id="user_id", - ) - assert_matches_type(Session, session, path=["response"]) - - @parametrize - def test_method_update_with_all_params(self, client: Honcho) -> None: session = client.apps.users.sessions.update( session_id="session_id", app_id="app_id", @@ -103,6 +94,7 @@ def test_raw_response_update(self, client: Honcho) -> None: session_id="session_id", app_id="app_id", user_id="user_id", + metadata={"foo": "bar"}, ) assert response.is_closed is True @@ -116,6 +108,7 @@ def test_streaming_response_update(self, client: Honcho) -> None: session_id="session_id", app_id="app_id", user_id="user_id", + metadata={"foo": "bar"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -132,6 +125,7 @@ def test_path_params_update(self, client: Honcho) -> None: session_id="session_id", app_id="", user_id="user_id", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -139,6 +133,7 @@ def test_path_params_update(self, client: Honcho) -> None: session_id="session_id", app_id="app_id", user_id="", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -146,6 +141,7 @@ def test_path_params_update(self, client: Honcho) -> None: session_id="", app_id="app_id", user_id="user_id", + metadata={"foo": "bar"}, ) @parametrize @@ -595,15 +591,6 @@ async def test_path_params_create(self, async_client: AsyncHoncho) -> None: @parametrize async def test_method_update(self, async_client: AsyncHoncho) -> None: - session = await async_client.apps.users.sessions.update( - session_id="session_id", - app_id="app_id", - user_id="user_id", - ) - assert_matches_type(Session, session, path=["response"]) - - @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncHoncho) -> None: session = await async_client.apps.users.sessions.update( session_id="session_id", app_id="app_id", @@ -618,6 +605,7 @@ async def test_raw_response_update(self, async_client: AsyncHoncho) -> None: session_id="session_id", app_id="app_id", user_id="user_id", + metadata={"foo": "bar"}, ) assert response.is_closed is True @@ -631,6 +619,7 @@ async def test_streaming_response_update(self, async_client: AsyncHoncho) -> Non session_id="session_id", app_id="app_id", user_id="user_id", + metadata={"foo": "bar"}, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -647,6 +636,7 @@ async def test_path_params_update(self, async_client: AsyncHoncho) -> None: session_id="session_id", app_id="", user_id="user_id", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `user_id` but received ''"): @@ -654,6 +644,7 @@ async def test_path_params_update(self, async_client: AsyncHoncho) -> None: session_id="session_id", app_id="app_id", user_id="", + metadata={"foo": "bar"}, ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"): @@ -661,6 +652,7 @@ async def test_path_params_update(self, async_client: AsyncHoncho) -> None: session_id="", app_id="app_id", user_id="user_id", + metadata={"foo": "bar"}, ) @parametrize diff --git a/tests/api_resources/test_apps.py b/tests/api_resources/test_apps.py index 07cc27e..91e8c2e 100644 --- a/tests/api_resources/test_apps.py +++ b/tests/api_resources/test_apps.py @@ -20,14 +20,14 @@ class TestApps: @parametrize def test_method_create(self, client: Honcho) -> None: app = client.apps.create( - name="name", + name="x", ) assert_matches_type(App, app, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: Honcho) -> None: app = client.apps.create( - name="name", + name="x", metadata={"foo": "bar"}, ) assert_matches_type(App, app, path=["response"]) @@ -35,7 +35,7 @@ def test_method_create_with_all_params(self, client: Honcho) -> None: @parametrize def test_raw_response_create(self, client: Honcho) -> None: response = client.apps.with_raw_response.create( - name="name", + name="x", ) assert response.is_closed is True @@ -46,7 +46,7 @@ def test_raw_response_create(self, client: Honcho) -> None: @parametrize def test_streaming_response_create(self, client: Honcho) -> None: with client.apps.with_streaming_response.create( - name="name", + name="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -224,14 +224,14 @@ class TestAsyncApps: @parametrize async def test_method_create(self, async_client: AsyncHoncho) -> None: app = await async_client.apps.create( - name="name", + name="x", ) assert_matches_type(App, app, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncHoncho) -> None: app = await async_client.apps.create( - name="name", + name="x", metadata={"foo": "bar"}, ) assert_matches_type(App, app, path=["response"]) @@ -239,7 +239,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncHoncho) -> @parametrize async def test_raw_response_create(self, async_client: AsyncHoncho) -> None: response = await async_client.apps.with_raw_response.create( - name="name", + name="x", ) assert response.is_closed is True @@ -250,7 +250,7 @@ async def test_raw_response_create(self, async_client: AsyncHoncho) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncHoncho) -> None: async with async_client.apps.with_streaming_response.create( - name="name", + name="x", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/test_client.py b/tests/test_client.py index 080317c..37451fe 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -717,7 +717,7 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> No with pytest.raises(APITimeoutError): self.client.post( "/v1/apps", - body=cast(object, dict(name="name")), + body=cast(object, dict(name="x")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -732,7 +732,7 @@ def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> Non with pytest.raises(APIStatusError): self.client.post( "/v1/apps", - body=cast(object, dict(name="name")), + body=cast(object, dict(name="x")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -765,7 +765,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/apps").mock(side_effect=retry_handler) - response = client.apps.with_raw_response.create(name="name") + response = client.apps.with_raw_response.create(name="x") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -789,7 +789,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/apps").mock(side_effect=retry_handler) - response = client.apps.with_raw_response.create(name="name", extra_headers={"x-stainless-retry-count": Omit()}) + response = client.apps.with_raw_response.create(name="x", extra_headers={"x-stainless-retry-count": Omit()}) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -812,7 +812,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/apps").mock(side_effect=retry_handler) - response = client.apps.with_raw_response.create(name="name", extra_headers={"x-stainless-retry-count": "42"}) + response = client.apps.with_raw_response.create(name="x", extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1501,7 +1501,7 @@ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) with pytest.raises(APITimeoutError): await self.client.post( "/v1/apps", - body=cast(object, dict(name="name")), + body=cast(object, dict(name="x")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1516,7 +1516,7 @@ async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) with pytest.raises(APIStatusError): await self.client.post( "/v1/apps", - body=cast(object, dict(name="name")), + body=cast(object, dict(name="x")), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1550,7 +1550,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/apps").mock(side_effect=retry_handler) - response = await client.apps.with_raw_response.create(name="name") + response = await client.apps.with_raw_response.create(name="x") assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1576,7 +1576,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/apps").mock(side_effect=retry_handler) response = await client.apps.with_raw_response.create( - name="name", extra_headers={"x-stainless-retry-count": Omit()} + name="x", extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1601,9 +1601,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: respx_mock.post("/v1/apps").mock(side_effect=retry_handler) - response = await client.apps.with_raw_response.create( - name="name", extra_headers={"x-stainless-retry-count": "42"} - ) + response = await client.apps.with_raw_response.create(name="x", extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" diff --git a/tests/test_models.py b/tests/test_models.py index 5e8bcf0..12b56d7 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,7 +1,7 @@ import json from typing import Any, Dict, List, Union, Optional, cast from datetime import datetime, timezone -from typing_extensions import Literal, Annotated +from typing_extensions import Literal, Annotated, TypeAliasType import pytest import pydantic @@ -828,3 +828,19 @@ class B(BaseModel): # if the discriminator details object stays the same between invocations then # we hit the cache assert UnionType.__discriminator__ is discriminator + + +@pytest.mark.skipif(not PYDANTIC_V2, reason="TypeAliasType is not supported in Pydantic v1") +def test_type_alias_type() -> None: + Alias = TypeAliasType("Alias", str) + + class Model(BaseModel): + alias: Alias + union: Union[int, Alias] + + m = construct_type(value={"alias": "foo", "union": "bar"}, type_=Model) + assert isinstance(m, Model) + assert isinstance(m.alias, str) + assert m.alias == "foo" + assert isinstance(m.union, str) + assert m.union == "bar" diff --git a/tests/utils.py b/tests/utils.py index cac35bb..6e9b19f 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -16,6 +16,7 @@ is_union_type, extract_type_arg, is_annotated_type, + is_type_alias_type, ) from honcho._compat import PYDANTIC_V2, field_outer_type, get_model_fields from honcho._models import BaseModel @@ -51,6 +52,9 @@ def assert_matches_type( path: list[str], allow_none: bool = False, ) -> None: + if is_type_alias_type(type_): + type_ = type_.__value__ + # unwrap `Annotated[T, ...]` -> `T` if is_annotated_type(type_): type_ = extract_type_arg(type_, 0)