diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 83bca8f..ac9a2e7 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} USER vscode -RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.24.0" RYE_INSTALL_OPTION="--yes" bash +RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.35.0" RYE_INSTALL_OPTION="--yes" bash ENV PATH=/home/vscode/.rye/shims:$PATH RUN echo "[[ -d .venv ]] && source .venv/bin/activate" >> /home/vscode/.bashrc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c33944..4029396 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,7 @@ on: pull_request: branches: - main + - next jobs: lint: @@ -21,7 +22,7 @@ jobs: curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: 0.24.0 + RYE_VERSION: '0.35.0' RYE_INSTALL_OPTION: '--yes' - name: Install dependencies @@ -41,7 +42,7 @@ jobs: curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: 0.24.0 + RYE_VERSION: '0.35.0' RYE_INSTALL_OPTION: '--yes' - name: Bootstrap diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 2b4a1c8..467cd8d 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -21,8 +21,8 @@ jobs: curl -sSf https://rye.astral.sh/get | bash echo "$HOME/.rye/shims" >> $GITHUB_PATH env: - RYE_VERSION: 0.24.0 - RYE_INSTALL_OPTION: "--yes" + RYE_VERSION: '0.35.0' + RYE_INSTALL_OPTION: '--yes' - name: Publish to PyPI run: | diff --git a/.gitignore b/.gitignore index 0f9a66a..8779740 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.prism.log .vscode _dev diff --git a/README.md b/README.md index bb9d149..ccd158b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ It is generated with [Stainless](https://www.stainlessapi.com/). ## Documentation -The REST API documentation can be found [on console.groq.com](https://console.groq.com/docs). The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [console.groq.com](https://console.groq.com/docs). The full API of this library can be found in [api.md](api.md). ## Installation diff --git a/pyproject.toml b/pyproject.toml index a2b78f2..3c82469 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,7 @@ dev-dependencies = [ "nox", "dirty-equals>=0.6.0", "importlib-metadata>=6.7.0", + "rich>=13.7.1", ] @@ -99,6 +100,21 @@ include = [ [tool.hatch.build.targets.wheel] packages = ["src/groq"] +[tool.hatch.build.targets.sdist] +# Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc) +include = [ + "/*.toml", + "/*.json", + "/*.lock", + "/*.md", + "/mypy.ini", + "/noxfile.py", + "bin/*", + "examples/*", + "src/*", + "tests/*", +] + [tool.hatch.metadata.hooks.fancy-pypi-readme] content-type = "text/markdown" diff --git a/requirements-dev.lock b/requirements-dev.lock index 5902e8a..3ee1ee4 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -11,7 +11,7 @@ -e file:. annotated-types==0.6.0 # via pydantic -anyio==4.1.0 +anyio==4.4.0 # via groq # via httpx argcomplete==3.1.2 @@ -45,7 +45,11 @@ idna==3.4 importlib-metadata==7.0.0 iniconfig==2.0.0 # via pytest -mypy==1.7.1 +markdown-it-py==3.0.0 + # via rich +mdurl==0.1.2 + # via markdown-it-py +mypy==1.10.1 mypy-extensions==1.0.0 # via mypy nodeenv==1.8.0 @@ -64,6 +68,8 @@ pydantic==2.7.1 # via groq pydantic-core==2.18.2 # via pydantic +pygments==2.18.0 + # via rich pyright==1.1.364 pytest==7.1.1 # via pytest-asyncio @@ -73,6 +79,7 @@ python-dateutil==2.8.2 pytz==2023.3.post1 # via dirty-equals respx==0.20.2 +rich==13.7.1 ruff==0.1.9 setuptools==68.2.2 # via nodeenv @@ -87,6 +94,7 @@ tomli==2.0.1 # via mypy # via pytest typing-extensions==4.8.0 + # via anyio # via groq # via mypy # via pydantic diff --git a/requirements.lock b/requirements.lock index 9f310d0..874a3cb 100644 --- a/requirements.lock +++ b/requirements.lock @@ -11,7 +11,7 @@ -e file:. annotated-types==0.6.0 # via pydantic -anyio==4.1.0 +anyio==4.4.0 # via groq # via httpx certifi==2023.7.22 @@ -39,6 +39,7 @@ sniffio==1.3.0 # via groq # via httpx typing-extensions==4.8.0 + # via anyio # via groq # via pydantic # via pydantic-core diff --git a/src/groq/_base_client.py b/src/groq/_base_client.py index 51b73a4..4b3ddd1 100644 --- a/src/groq/_base_client.py +++ b/src/groq/_base_client.py @@ -58,6 +58,7 @@ HttpxSendArgs, AsyncTransport, RequestOptions, + HttpxRequestFiles, ModelBuilderProtocol, ) from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping @@ -459,6 +460,7 @@ def _build_request( headers = self._build_headers(options) params = _merge_mappings(self.default_query, options.params) content_type = headers.get("Content-Type") + files = options.files # If the given Content-Type header is multipart/form-data then it # has to be removed so that httpx can generate the header with @@ -472,7 +474,7 @@ def _build_request( headers.pop("Content-Type") # As we are now sending multipart/form-data instead of application/json - # we need to tell httpx to use it, https://www.python-httpx.org/advanced/#multipart-file-encoding + # we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding if json_data: if not is_dict(json_data): raise TypeError( @@ -480,6 +482,15 @@ def _build_request( ) kwargs["data"] = self._serialize_multipartform(json_data) + # httpx determines whether or not to send a "multipart/form-data" + # request based on the truthiness of the "files" argument. + # This gets around that issue by generating a dict value that + # evaluates to true. + # + # https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186 + if not files: + files = cast(HttpxRequestFiles, ForceMultipartDict()) + # TODO: report this error to httpx return self._client.build_request( # pyright: ignore[reportUnknownMemberType] headers=headers, @@ -492,7 +503,7 @@ def _build_request( # https://github.com/microsoft/pyright/issues/3526#event-6715453066 params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None, json=json_data, - files=options.files, + files=files, **kwargs, ) @@ -868,9 +879,9 @@ def __exit__( def _prepare_options( self, options: FinalRequestOptions, # noqa: ARG002 - ) -> None: + ) -> FinalRequestOptions: """Hook for mutating the given options""" - return None + return options def _prepare_request( self, @@ -944,8 +955,13 @@ def _request( stream: bool, stream_cls: type[_StreamT] | None, ) -> ResponseT | _StreamT: + # create a copy of the options we were given so that if the + # options are mutated later & we then retry, the retries are + # given the original options + input_options = model_copy(options) + cast_to = self._maybe_override_cast_to(cast_to, options) - self._prepare_options(options) + options = self._prepare_options(options) retries = self._remaining_retries(remaining_retries, options) request = self._build_request(options) @@ -968,7 +984,7 @@ def _request( if retries > 0: return self._retry_request( - options, + input_options, cast_to, retries, stream=stream, @@ -983,7 +999,7 @@ def _request( if retries > 0: return self._retry_request( - options, + input_options, cast_to, retries, stream=stream, @@ -1011,7 +1027,7 @@ def _request( if retries > 0 and self._should_retry(err.response): err.response.close() return self._retry_request( - options, + input_options, cast_to, retries, err.response.headers, @@ -1426,9 +1442,9 @@ async def __aexit__( async def _prepare_options( self, options: FinalRequestOptions, # noqa: ARG002 - ) -> None: + ) -> FinalRequestOptions: """Hook for mutating the given options""" - return None + return options async def _prepare_request( self, @@ -1507,8 +1523,13 @@ async def _request( # execute it earlier while we are in an async context self._platform = await asyncify(get_platform)() + # create a copy of the options we were given so that if the + # options are mutated later & we then retry, the retries are + # given the original options + input_options = model_copy(options) + cast_to = self._maybe_override_cast_to(cast_to, options) - await self._prepare_options(options) + options = await self._prepare_options(options) retries = self._remaining_retries(remaining_retries, options) request = self._build_request(options) @@ -1529,7 +1550,7 @@ async def _request( if retries > 0: return await self._retry_request( - options, + input_options, cast_to, retries, stream=stream, @@ -1544,7 +1565,7 @@ async def _request( if retries > 0: return await self._retry_request( - options, + input_options, cast_to, retries, stream=stream, @@ -1567,7 +1588,7 @@ async def _request( if retries > 0 and self._should_retry(err.response): await err.response.aclose() return await self._retry_request( - options, + input_options, cast_to, retries, err.response.headers, @@ -1863,6 +1884,11 @@ def make_request_options( return options +class ForceMultipartDict(Dict[str, None]): + def __bool__(self) -> bool: + return True + + class OtherPlatform: def __init__(self, name: str) -> None: self.name = name diff --git a/src/groq/_compat.py b/src/groq/_compat.py index 74c7639..c919b5a 100644 --- a/src/groq/_compat.py +++ b/src/groq/_compat.py @@ -118,10 +118,10 @@ def get_model_fields(model: type[pydantic.BaseModel]) -> dict[str, FieldInfo]: return model.__fields__ # type: ignore -def model_copy(model: _ModelT) -> _ModelT: +def model_copy(model: _ModelT, *, deep: bool = False) -> _ModelT: if PYDANTIC_V2: - return model.model_copy() - return model.copy() # type: ignore + return model.model_copy(deep=deep) + return model.copy(deep=deep) # type: ignore def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str: diff --git a/src/groq/_models.py b/src/groq/_models.py index 75c68cc..eb7ce3b 100644 --- a/src/groq/_models.py +++ b/src/groq/_models.py @@ -10,6 +10,7 @@ ClassVar, Protocol, Required, + ParamSpec, TypedDict, TypeGuard, final, @@ -67,6 +68,9 @@ __all__ = ["BaseModel", "GenericModel"] _T = TypeVar("_T") +_BaseModelT = TypeVar("_BaseModelT", bound="BaseModel") + +P = ParamSpec("P") @runtime_checkable @@ -379,6 +383,29 @@ def is_basemodel_type(type_: type) -> TypeGuard[type[BaseModel] | type[GenericMo return issubclass(origin, BaseModel) or issubclass(origin, GenericModel) +def build( + base_model_cls: Callable[P, _BaseModelT], + *args: P.args, + **kwargs: P.kwargs, +) -> _BaseModelT: + """Construct a BaseModel class without validation. + + This is useful for cases where you need to instantiate a `BaseModel` + from an API response as this provides type-safe params which isn't supported + by helpers like `construct_type()`. + + ```py + build(MyModel, my_field_a="foo", my_field_b=123) + ``` + """ + if args: + raise TypeError( + "Received positional arguments which are not supported; Keyword arguments must be used instead", + ) + + return cast(_BaseModelT, construct_type(type_=base_model_cls, value=kwargs)) + + def construct_type(*, value: object, type_: object) -> object: """Loose coercion to the expected type with construction of nested values. @@ -616,6 +643,14 @@ def validate_type(*, type_: type[_T], value: object) -> _T: return cast(_T, _validate_non_model_type(type_=type_, value=value)) +def set_pydantic_config(typ: Any, config: pydantic.ConfigDict) -> None: + """Add a pydantic config for the given type. + + Note: this is a no-op on Pydantic v1. + """ + setattr(typ, "__pydantic_config__", config) # noqa: B010 + + # our use of subclasssing here causes weirdness for type checkers, # so we just pretend that we don't subclass if TYPE_CHECKING: diff --git a/src/groq/_utils/__init__.py b/src/groq/_utils/__init__.py index 667e247..3efe66c 100644 --- a/src/groq/_utils/__init__.py +++ b/src/groq/_utils/__init__.py @@ -49,4 +49,7 @@ maybe_transform as maybe_transform, async_maybe_transform as async_maybe_transform, ) -from ._reflection import function_has_argument as function_has_argument +from ._reflection import ( + function_has_argument as function_has_argument, + assert_signatures_in_sync as assert_signatures_in_sync, +) diff --git a/src/groq/_utils/_reflection.py b/src/groq/_utils/_reflection.py index e134f58..9a53c7b 100644 --- a/src/groq/_utils/_reflection.py +++ b/src/groq/_utils/_reflection.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import inspect from typing import Any, Callable @@ -6,3 +8,35 @@ def function_has_argument(func: Callable[..., Any], arg_name: str) -> bool: """Returns whether or not the given function has a specific parameter""" sig = inspect.signature(func) return arg_name in sig.parameters + + +def assert_signatures_in_sync( + source_func: Callable[..., Any], + check_func: Callable[..., Any], + *, + exclude_params: set[str] = set(), +) -> None: + """Ensure that the signature of the second function matches the first.""" + + check_sig = inspect.signature(check_func) + source_sig = inspect.signature(source_func) + + errors: list[str] = [] + + for name, source_param in source_sig.parameters.items(): + if name in exclude_params: + continue + + custom_param = check_sig.parameters.get(name) + if not custom_param: + errors.append(f"the `{name}` param is missing") + continue + + if custom_param.annotation != source_param.annotation: + errors.append( + f"types for the `{name}` param are do not match; source={repr(source_param.annotation)} checking={repr(source_param.annotation)}" + ) + continue + + if errors: + raise AssertionError(f"{len(errors)} errors encountered when comparing signatures:\n\n" + "\n\n".join(errors)) diff --git a/src/groq/resources/audio/transcriptions.py b/src/groq/resources/audio/transcriptions.py index fabbc02..e7d7b89 100644 --- a/src/groq/resources/audio/transcriptions.py +++ b/src/groq/resources/audio/transcriptions.py @@ -23,9 +23,7 @@ async_to_streamed_response_wrapper, ) from ...types.audio import transcription_create_params -from ..._base_client import ( - make_request_options, -) +from ..._base_client import make_request_options from ...types.audio.transcription import Transcription __all__ = ["Transcriptions", "AsyncTranscriptions"] @@ -215,11 +213,10 @@ def create( } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/openai/v1/audio/transcriptions", body=maybe_transform(body, transcription_create_params.TranscriptionCreateParams), @@ -415,11 +412,10 @@ async def create( } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/openai/v1/audio/transcriptions", body=await async_maybe_transform(body, transcription_create_params.TranscriptionCreateParams), diff --git a/src/groq/resources/audio/translations.py b/src/groq/resources/audio/translations.py index 095cde9..101a797 100644 --- a/src/groq/resources/audio/translations.py +++ b/src/groq/resources/audio/translations.py @@ -23,9 +23,7 @@ async_to_streamed_response_wrapper, ) from ...types.audio import translation_create_params -from ..._base_client import ( - make_request_options, -) +from ..._base_client import make_request_options from ...types.audio.translation import Translation __all__ = ["Translations", "AsyncTranslations"] @@ -95,11 +93,10 @@ def create( } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/openai/v1/audio/translations", body=maybe_transform(body, translation_create_params.TranslationCreateParams), @@ -175,11 +172,10 @@ async def create( } ) files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) - if files: - # It should be noted that the actual Content-Type header that will be - # sent to the server will contain a `boundary` parameter, e.g. - # multipart/form-data; boundary=---abc-- - extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/openai/v1/audio/translations", body=await async_maybe_transform(body, translation_create_params.TranslationCreateParams), diff --git a/src/groq/resources/chat/completions.py b/src/groq/resources/chat/completions.py index e4d20b7..487cf37 100644 --- a/src/groq/resources/chat/completions.py +++ b/src/groq/resources/chat/completions.py @@ -22,9 +22,7 @@ ) from ..._streaming import Stream, AsyncStream from ...types.chat import completion_create_params -from ..._base_client import ( - make_request_options, -) +from ..._base_client import make_request_options from ...types.chat.chat_completion import ChatCompletion from ...types.chat.chat_completion_chunk import ChatCompletionChunk from ...types.chat.chat_completion_tool_param import ChatCompletionToolParam diff --git a/src/groq/resources/embeddings.py b/src/groq/resources/embeddings.py index e58980b..d52fd5e 100644 --- a/src/groq/resources/embeddings.py +++ b/src/groq/resources/embeddings.py @@ -21,9 +21,7 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from .._base_client import ( - make_request_options, -) +from .._base_client import make_request_options from ..types.create_embedding_response import CreateEmbeddingResponse __all__ = ["Embeddings", "AsyncEmbeddings"] diff --git a/src/groq/resources/models.py b/src/groq/resources/models.py index 7aada47..e81a21c 100644 --- a/src/groq/resources/models.py +++ b/src/groq/resources/models.py @@ -14,9 +14,7 @@ async_to_streamed_response_wrapper, ) from ..types.model import Model -from .._base_client import ( - make_request_options, -) +from .._base_client import make_request_options from ..types.model_deleted import ModelDeleted from ..types.model_list_response import ModelListResponse diff --git a/tests/api_resources/audio/test_transcriptions.py b/tests/api_resources/audio/test_transcriptions.py index b54784b..1ced07b 100644 --- a/tests/api_resources/audio/test_transcriptions.py +++ b/tests/api_resources/audio/test_transcriptions.py @@ -31,7 +31,7 @@ def test_method_create_with_all_params(self, client: Groq) -> None: file=b"raw file contents", model="whisper-large-v3", language="string", - prompt="string", + prompt="prompt", response_format="json", temperature=0, timestamp_granularities=["word", "segment"], @@ -82,7 +82,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGroq) -> N file=b"raw file contents", model="whisper-large-v3", language="string", - prompt="string", + prompt="prompt", response_format="json", temperature=0, timestamp_granularities=["word", "segment"], diff --git a/tests/api_resources/audio/test_translations.py b/tests/api_resources/audio/test_translations.py index a0dc9bc..ef616fd 100644 --- a/tests/api_resources/audio/test_translations.py +++ b/tests/api_resources/audio/test_translations.py @@ -30,7 +30,7 @@ def test_method_create_with_all_params(self, client: Groq) -> None: translation = client.audio.translations.create( file=b"raw file contents", model="whisper-1", - prompt="string", + prompt="prompt", response_format="json", temperature=0, ) @@ -79,7 +79,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGroq) -> N translation = await async_client.audio.translations.create( file=b"raw file contents", model="whisper-1", - prompt="string", + prompt="prompt", response_format="json", temperature=0, ) diff --git a/tests/api_resources/chat/test_completions.py b/tests/api_resources/chat/test_completions.py index d689f95..4e51043 100644 --- a/tests/api_resources/chat/test_completions.py +++ b/tests/api_resources/chat/test_completions.py @@ -22,7 +22,7 @@ def test_method_create(self, client: Groq) -> None: completion = client.chat.completions.create( messages=[ { - "content": "string", + "content": "content", "role": "system", } ], @@ -35,10 +35,10 @@ def test_method_create_with_all_params(self, client: Groq) -> None: completion = client.chat.completions.create( messages=[ { - "content": "string", + "content": "content", "role": "system", - "name": "string", - "tool_call_id": "string", + "name": "name", + "tool_call_id": "tool_call_id", } ], model="string", @@ -46,18 +46,18 @@ def test_method_create_with_all_params(self, client: Groq) -> None: function_call="none", functions=[ { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, ], @@ -78,31 +78,31 @@ def test_method_create_with_all_params(self, client: Groq) -> None: { "type": "function", "function": { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, }, { "type": "function", "function": { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, }, { "type": "function", "function": { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, }, ], top_logprobs=0, top_p=1, - user="string", + user="user", ) assert_matches_type(ChatCompletion, completion, path=["response"]) @@ -111,7 +111,7 @@ def test_raw_response_create(self, client: Groq) -> None: response = client.chat.completions.with_raw_response.create( messages=[ { - "content": "string", + "content": "content", "role": "system", } ], @@ -128,7 +128,7 @@ def test_streaming_response_create(self, client: Groq) -> None: with client.chat.completions.with_streaming_response.create( messages=[ { - "content": "string", + "content": "content", "role": "system", } ], @@ -151,7 +151,7 @@ async def test_method_create(self, async_client: AsyncGroq) -> None: completion = await async_client.chat.completions.create( messages=[ { - "content": "string", + "content": "content", "role": "system", } ], @@ -164,10 +164,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncGroq) -> N completion = await async_client.chat.completions.create( messages=[ { - "content": "string", + "content": "content", "role": "system", - "name": "string", - "tool_call_id": "string", + "name": "name", + "tool_call_id": "tool_call_id", } ], model="string", @@ -175,18 +175,18 @@ async def test_method_create_with_all_params(self, async_client: AsyncGroq) -> N function_call="none", functions=[ { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, ], @@ -207,31 +207,31 @@ async def test_method_create_with_all_params(self, async_client: AsyncGroq) -> N { "type": "function", "function": { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, }, { "type": "function", "function": { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, }, { "type": "function", "function": { - "description": "string", - "name": "string", + "description": "description", + "name": "name", "parameters": {"foo": "bar"}, }, }, ], top_logprobs=0, top_p=1, - user="string", + user="user", ) assert_matches_type(ChatCompletion, completion, path=["response"]) @@ -240,7 +240,7 @@ async def test_raw_response_create(self, async_client: AsyncGroq) -> None: response = await async_client.chat.completions.with_raw_response.create( messages=[ { - "content": "string", + "content": "content", "role": "system", } ], @@ -257,7 +257,7 @@ async def test_streaming_response_create(self, async_client: AsyncGroq) -> None: async with async_client.chat.completions.with_streaming_response.create( messages=[ { - "content": "string", + "content": "content", "role": "system", } ], diff --git a/tests/api_resources/test_embeddings.py b/tests/api_resources/test_embeddings.py index 9e663d1..baa1d1c 100644 --- a/tests/api_resources/test_embeddings.py +++ b/tests/api_resources/test_embeddings.py @@ -31,7 +31,7 @@ def test_method_create_with_all_params(self, client: Groq) -> None: input="The quick brown fox jumped over the lazy dog", model="nomic-embed-text-v1_5", encoding_format="float", - user="string", + user="user", ) assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) @@ -79,7 +79,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncGroq) -> N input="The quick brown fox jumped over the lazy dog", model="nomic-embed-text-v1_5", encoding_format="float", - user="string", + user="user", ) assert_matches_type(CreateEmbeddingResponse, embedding, path=["response"]) diff --git a/tests/api_resources/test_models.py b/tests/api_resources/test_models.py index 55969db..e2eb0d4 100644 --- a/tests/api_resources/test_models.py +++ b/tests/api_resources/test_models.py @@ -20,14 +20,14 @@ class TestModels: @parametrize def test_method_retrieve(self, client: Groq) -> None: model = client.models.retrieve( - "string", + "model", ) assert_matches_type(Model, model, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: Groq) -> None: response = client.models.with_raw_response.retrieve( - "string", + "model", ) assert response.is_closed is True @@ -38,7 +38,7 @@ def test_raw_response_retrieve(self, client: Groq) -> None: @parametrize def test_streaming_response_retrieve(self, client: Groq) -> None: with client.models.with_streaming_response.retrieve( - "string", + "model", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -83,14 +83,14 @@ def test_streaming_response_list(self, client: Groq) -> None: @parametrize def test_method_delete(self, client: Groq) -> None: model = client.models.delete( - "string", + "model", ) assert_matches_type(ModelDeleted, model, path=["response"]) @parametrize def test_raw_response_delete(self, client: Groq) -> None: response = client.models.with_raw_response.delete( - "string", + "model", ) assert response.is_closed is True @@ -101,7 +101,7 @@ def test_raw_response_delete(self, client: Groq) -> None: @parametrize def test_streaming_response_delete(self, client: Groq) -> None: with client.models.with_streaming_response.delete( - "string", + "model", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -125,14 +125,14 @@ class TestAsyncModels: @parametrize async def test_method_retrieve(self, async_client: AsyncGroq) -> None: model = await async_client.models.retrieve( - "string", + "model", ) assert_matches_type(Model, model, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncGroq) -> None: response = await async_client.models.with_raw_response.retrieve( - "string", + "model", ) assert response.is_closed is True @@ -143,7 +143,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncGroq) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncGroq) -> None: async with async_client.models.with_streaming_response.retrieve( - "string", + "model", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -188,14 +188,14 @@ async def test_streaming_response_list(self, async_client: AsyncGroq) -> None: @parametrize async def test_method_delete(self, async_client: AsyncGroq) -> None: model = await async_client.models.delete( - "string", + "model", ) assert_matches_type(ModelDeleted, model, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncGroq) -> None: response = await async_client.models.with_raw_response.delete( - "string", + "model", ) assert response.is_closed is True @@ -206,7 +206,7 @@ async def test_raw_response_delete(self, async_client: AsyncGroq) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncGroq) -> None: async with async_client.models.with_streaming_response.delete( - "string", + "model", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python"