diff --git a/.stats.yml b/.stats.yml index 73df72e5..571d6bb0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 14 +configured_endpoints: 15 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brainbase-egrigokhan%2Fbrainbase-0c00485d66a3b7505f3247467ef293fa5fb43a64e90a8b03a4127a2d9b15e6ab.yml diff --git a/README.md b/README.md index bd87518a..9981e1b9 100644 --- a/README.md +++ b/README.md @@ -24,32 +24,25 @@ pip install --pre brainbase-labs The full API of this library can be found in [api.md](api.md). ```python -import os from brainbase import Brainbase client = Brainbase( - api_key=os.environ.get("BRAINBASE_API_KEY"), # This is the default and can be omitted + bearer_token="My Bearer Token", ) client.workers.list() ``` -While you can provide an `api_key` keyword argument, -we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/) -to add `BRAINBASE_API_KEY="My API Key"` to your `.env` file -so that your API Key is not stored in source control. - ## Async usage Simply import `AsyncBrainbase` instead of `Brainbase` and use `await` with each API call: ```python -import os import asyncio from brainbase import AsyncBrainbase client = AsyncBrainbase( - api_key=os.environ.get("BRAINBASE_API_KEY"), # This is the default and can be omitted + bearer_token="My Bearer Token", ) @@ -84,7 +77,9 @@ All errors inherit from `brainbase.APIError`. import brainbase from brainbase import Brainbase -client = Brainbase() +client = Brainbase( + bearer_token="My Bearer Token", +) try: client.workers.list() @@ -127,6 +122,7 @@ from brainbase import Brainbase client = Brainbase( # default is 2 max_retries=0, + bearer_token="My Bearer Token", ) # Or, configure per-request: @@ -145,11 +141,13 @@ from brainbase import Brainbase client = Brainbase( # 20 seconds (default is 1 minute) timeout=20.0, + bearer_token="My Bearer Token", ) # More granular control: client = Brainbase( timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0), + bearer_token="My Bearer Token", ) # Override per-request: @@ -193,7 +191,9 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to ```py from brainbase import Brainbase -client = Brainbase() +client = Brainbase( + bearer_token="My Bearer Token", +) response = client.workers.with_raw_response.list() print(response.headers.get('X-My-Header')) @@ -274,6 +274,7 @@ client = Brainbase( proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0"), ), + bearer_token="My Bearer Token", ) ``` @@ -290,7 +291,9 @@ By default the library closes underlying HTTP connections whenever the client is ```py from brainbase import Brainbase -with Brainbase() as client: +with Brainbase( + bearer_token="My Bearer Token", +) as client: # make requests here ... diff --git a/api.md b/api.md index 6f634335..4e25a402 100644 --- a/api.md +++ b/api.md @@ -4,6 +4,7 @@ Methods: - client.workers.create(\*\*params) -> None - client.workers.retrieve(id) -> None +- client.workers.update(id, \*\*params) -> None - client.workers.list() -> None - client.workers.delete(id) -> None diff --git a/src/brainbase/_client.py b/src/brainbase/_client.py index 9192a946..3c4f9565 100644 --- a/src/brainbase/_client.py +++ b/src/brainbase/_client.py @@ -51,12 +51,12 @@ class Brainbase(SyncAPIClient): with_streaming_response: BrainbaseWithStreamedResponse # client options - api_key: str + bearer_token: str def __init__( self, *, - api_key: str | None = None, + bearer_token: str | None = None, base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, @@ -78,15 +78,15 @@ def __init__( ) -> None: """Construct a new synchronous brainbase client instance. - This automatically infers the `api_key` argument from the `BRAINBASE_API_KEY` environment variable if it is not provided. + This automatically infers the `bearer_token` argument from the `BEARER_TOKEN` environment variable if it is not provided. """ - if api_key is None: - api_key = os.environ.get("BRAINBASE_API_KEY") - if api_key is None: + if bearer_token is None: + bearer_token = os.environ.get("BEARER_TOKEN") + if bearer_token is None: raise BrainbaseError( - "The api_key client option must be set either by passing api_key to the client or by setting the BRAINBASE_API_KEY environment variable" + "The bearer_token client option must be set either by passing bearer_token to the client or by setting the BEARER_TOKEN environment variable" ) - self.api_key = api_key + self.bearer_token = bearer_token if base_url is None: base_url = os.environ.get("BRAINBASE_BASE_URL") @@ -113,12 +113,6 @@ def __init__( def qs(self) -> Querystring: return Querystring(array_format="comma") - @property - @override - def auth_headers(self) -> dict[str, str]: - api_key = self.api_key - return {"x-api-key": api_key} - @property @override def default_headers(self) -> dict[str, str | Omit]: @@ -131,7 +125,7 @@ def default_headers(self) -> dict[str, str | Omit]: def copy( self, *, - api_key: str | None = None, + bearer_token: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.Client | None = None, @@ -165,7 +159,7 @@ def copy( http_client = http_client or self._client return self.__class__( - api_key=api_key or self.api_key, + bearer_token=bearer_token or self.bearer_token, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, @@ -219,12 +213,12 @@ class AsyncBrainbase(AsyncAPIClient): with_streaming_response: AsyncBrainbaseWithStreamedResponse # client options - api_key: str + bearer_token: str def __init__( self, *, - api_key: str | None = None, + bearer_token: str | None = None, base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, @@ -246,15 +240,15 @@ def __init__( ) -> None: """Construct a new async brainbase client instance. - This automatically infers the `api_key` argument from the `BRAINBASE_API_KEY` environment variable if it is not provided. + This automatically infers the `bearer_token` argument from the `BEARER_TOKEN` environment variable if it is not provided. """ - if api_key is None: - api_key = os.environ.get("BRAINBASE_API_KEY") - if api_key is None: + if bearer_token is None: + bearer_token = os.environ.get("BEARER_TOKEN") + if bearer_token is None: raise BrainbaseError( - "The api_key client option must be set either by passing api_key to the client or by setting the BRAINBASE_API_KEY environment variable" + "The bearer_token client option must be set either by passing bearer_token to the client or by setting the BEARER_TOKEN environment variable" ) - self.api_key = api_key + self.bearer_token = bearer_token if base_url is None: base_url = os.environ.get("BRAINBASE_BASE_URL") @@ -281,12 +275,6 @@ def __init__( def qs(self) -> Querystring: return Querystring(array_format="comma") - @property - @override - def auth_headers(self) -> dict[str, str]: - api_key = self.api_key - return {"x-api-key": api_key} - @property @override def default_headers(self) -> dict[str, str | Omit]: @@ -299,7 +287,7 @@ def default_headers(self) -> dict[str, str | Omit]: def copy( self, *, - api_key: str | None = None, + bearer_token: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.AsyncClient | None = None, @@ -333,7 +321,7 @@ def copy( http_client = http_client or self._client return self.__class__( - api_key=api_key or self.api_key, + bearer_token=bearer_token or self.bearer_token, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, diff --git a/src/brainbase/resources/workers/workers.py b/src/brainbase/resources/workers/workers.py index 9d2eb83c..323da4da 100644 --- a/src/brainbase/resources/workers/workers.py +++ b/src/brainbase/resources/workers/workers.py @@ -12,7 +12,7 @@ FlowsResourceWithStreamingResponse, AsyncFlowsResourceWithStreamingResponse, ) -from ...types import worker_create_params +from ...types import worker_create_params, worker_update_params from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._utils import ( maybe_transform, @@ -143,6 +143,51 @@ def retrieve( cast_to=NoneType, ) + def update( + self, + id: str, + *, + description: str | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + status: str | 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """ + Update a worker + + 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 id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._post( + f"/api/workers/{id}", + body=maybe_transform( + { + "description": description, + "name": name, + "status": status, + }, + worker_update_params.WorkerUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + def list( self, *, @@ -302,6 +347,51 @@ async def retrieve( cast_to=NoneType, ) + async def update( + self, + id: str, + *, + description: str | NotGiven = NOT_GIVEN, + name: str | NotGiven = NOT_GIVEN, + status: str | 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> None: + """ + Update a worker + + 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 id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._post( + f"/api/workers/{id}", + body=await async_maybe_transform( + { + "description": description, + "name": name, + "status": status, + }, + worker_update_params.WorkerUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + async def list( self, *, @@ -367,6 +457,9 @@ def __init__(self, workers: WorkersResource) -> None: self.retrieve = to_raw_response_wrapper( workers.retrieve, ) + self.update = to_raw_response_wrapper( + workers.update, + ) self.list = to_raw_response_wrapper( workers.list, ) @@ -393,6 +486,9 @@ def __init__(self, workers: AsyncWorkersResource) -> None: self.retrieve = async_to_raw_response_wrapper( workers.retrieve, ) + self.update = async_to_raw_response_wrapper( + workers.update, + ) self.list = async_to_raw_response_wrapper( workers.list, ) @@ -419,6 +515,9 @@ def __init__(self, workers: WorkersResource) -> None: self.retrieve = to_streamed_response_wrapper( workers.retrieve, ) + self.update = to_streamed_response_wrapper( + workers.update, + ) self.list = to_streamed_response_wrapper( workers.list, ) @@ -445,6 +544,9 @@ def __init__(self, workers: AsyncWorkersResource) -> None: self.retrieve = async_to_streamed_response_wrapper( workers.retrieve, ) + self.update = async_to_streamed_response_wrapper( + workers.update, + ) self.list = async_to_streamed_response_wrapper( workers.list, ) diff --git a/src/brainbase/types/__init__.py b/src/brainbase/types/__init__.py index 5976bd7c..065250e2 100644 --- a/src/brainbase/types/__init__.py +++ b/src/brainbase/types/__init__.py @@ -3,3 +3,4 @@ from __future__ import annotations from .worker_create_params import WorkerCreateParams as WorkerCreateParams +from .worker_update_params import WorkerUpdateParams as WorkerUpdateParams diff --git a/src/brainbase/types/worker_update_params.py b/src/brainbase/types/worker_update_params.py new file mode 100644 index 00000000..bfa7a019 --- /dev/null +++ b/src/brainbase/types/worker_update_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["WorkerUpdateParams"] + + +class WorkerUpdateParams(TypedDict, total=False): + description: str + + name: str + + status: str diff --git a/tests/api_resources/test_workers.py b/tests/api_resources/test_workers.py index 5f524f47..2a9a36aa 100644 --- a/tests/api_resources/test_workers.py +++ b/tests/api_resources/test_workers.py @@ -101,6 +101,59 @@ def test_path_params_retrieve(self, client: Brainbase) -> None: "", ) + @pytest.mark.skip() + @parametrize + def test_method_update(self, client: Brainbase) -> None: + worker = client.workers.update( + id="id", + ) + assert worker is None + + @pytest.mark.skip() + @parametrize + def test_method_update_with_all_params(self, client: Brainbase) -> None: + worker = client.workers.update( + id="id", + description="description", + name="name", + status="status", + ) + assert worker is None + + @pytest.mark.skip() + @parametrize + def test_raw_response_update(self, client: Brainbase) -> None: + response = client.workers.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + worker = response.parse() + assert worker is None + + @pytest.mark.skip() + @parametrize + def test_streaming_response_update(self, client: Brainbase) -> None: + with client.workers.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + worker = response.parse() + assert worker is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + def test_path_params_update(self, client: Brainbase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.workers.with_raw_response.update( + id="", + ) + @pytest.mark.skip() @parametrize def test_method_list(self, client: Brainbase) -> None: @@ -261,6 +314,59 @@ async def test_path_params_retrieve(self, async_client: AsyncBrainbase) -> None: "", ) + @pytest.mark.skip() + @parametrize + async def test_method_update(self, async_client: AsyncBrainbase) -> None: + worker = await async_client.workers.update( + id="id", + ) + assert worker is None + + @pytest.mark.skip() + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncBrainbase) -> None: + worker = await async_client.workers.update( + id="id", + description="description", + name="name", + status="status", + ) + assert worker is None + + @pytest.mark.skip() + @parametrize + async def test_raw_response_update(self, async_client: AsyncBrainbase) -> None: + response = await async_client.workers.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + worker = await response.parse() + assert worker is None + + @pytest.mark.skip() + @parametrize + async def test_streaming_response_update(self, async_client: AsyncBrainbase) -> None: + async with async_client.workers.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + worker = await response.parse() + assert worker is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip() + @parametrize + async def test_path_params_update(self, async_client: AsyncBrainbase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.workers.with_raw_response.update( + id="", + ) + @pytest.mark.skip() @parametrize async def test_method_list(self, async_client: AsyncBrainbase) -> None: diff --git a/tests/conftest.py b/tests/conftest.py index 8e89d982..9a8b7c7c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,7 +28,7 @@ def pytest_collection_modifyitems(items: list[pytest.Function]) -> None: base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -api_key = "My API Key" +bearer_token = "My Bearer Token" @pytest.fixture(scope="session") @@ -37,7 +37,7 @@ def client(request: FixtureRequest) -> Iterator[Brainbase]: if not isinstance(strict, bool): raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") - with Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: + with Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=strict) as client: yield client @@ -47,5 +47,7 @@ async def async_client(request: FixtureRequest) -> AsyncIterator[AsyncBrainbase] if not isinstance(strict, bool): raise TypeError(f"Unexpected fixture parameter type {type(strict)}, expected {bool}") - async with AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: + async with AsyncBrainbase( + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=strict + ) as client: yield client diff --git a/tests/test_client.py b/tests/test_client.py index 4bf71630..fa4581c7 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -25,7 +25,7 @@ from brainbase._types import Omit from brainbase._models import BaseModel, FinalRequestOptions from brainbase._constants import RAW_RESPONSE_HEADER -from brainbase._exceptions import APIStatusError, BrainbaseError, APITimeoutError, APIResponseValidationError +from brainbase._exceptions import APIStatusError, APITimeoutError, APIResponseValidationError from brainbase._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, @@ -36,7 +36,7 @@ from .utils import update_env base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -api_key = "My API Key" +bearer_token = "My Bearer Token" def _get_params(client: BaseClient[Any, Any]) -> dict[str, str]: @@ -58,7 +58,7 @@ def _get_open_connections(client: Brainbase | AsyncBrainbase) -> int: class TestBrainbase: - client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) @pytest.mark.respx(base_url=base_url) def test_raw_response(self, respx_mock: MockRouter) -> None: @@ -84,9 +84,9 @@ def test_copy(self) -> None: copied = self.client.copy() assert id(copied) != id(self.client) - copied = self.client.copy(api_key="another My API Key") - assert copied.api_key == "another My API Key" - assert self.client.api_key == "My API Key" + copied = self.client.copy(bearer_token="another My Bearer Token") + assert copied.bearer_token == "another My Bearer Token" + assert self.client.bearer_token == "My Bearer Token" def test_copy_default_options(self) -> None: # options that have a default are overridden correctly @@ -106,7 +106,10 @@ def test_copy_default_options(self) -> None: def test_copy_default_headers(self) -> None: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, ) assert client.default_headers["X-Foo"] == "bar" @@ -140,7 +143,7 @@ def test_copy_default_headers(self) -> None: def test_copy_default_query(self) -> None: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" @@ -265,7 +268,7 @@ def test_request_timeout(self) -> None: def test_client_timeout_option(self) -> None: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, timeout=httpx.Timeout(0) ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -276,7 +279,7 @@ def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used with httpx.Client(timeout=None) as http_client: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -286,7 +289,7 @@ def test_http_client_timeout_option(self) -> None: # no timeout given to the httpx client should not use the httpx default with httpx.Client() as http_client: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -296,7 +299,7 @@ def test_http_client_timeout_option(self) -> None: # explicitly passing the default timeout currently results in it being ignored with httpx.Client(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -308,14 +311,17 @@ async def test_invalid_http_client(self) -> None: async with httpx.AsyncClient() as http_client: Brainbase( base_url=base_url, - api_key=api_key, + bearer_token=bearer_token, _strict_response_validation=True, http_client=cast(Any, http_client), ) def test_default_headers_option(self) -> None: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" @@ -323,7 +329,7 @@ def test_default_headers_option(self) -> None: client2 = Brainbase( base_url=base_url, - api_key=api_key, + bearer_token=bearer_token, _strict_response_validation=True, default_headers={ "X-Foo": "stainless", @@ -334,19 +340,12 @@ def test_default_headers_option(self) -> None: assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" - def test_validate_headers(self) -> None: - client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-api-key") == api_key - - with pytest.raises(BrainbaseError): - with update_env(**{"BRAINBASE_API_KEY": Omit()}): - client2 = Brainbase(base_url=base_url, api_key=None, _strict_response_validation=True) - _ = client2 - def test_default_query_option(self) -> None: client = Brainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + default_query={"query_param": "bar"}, ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) @@ -546,7 +545,9 @@ class Model(BaseModel): assert response.foo == 2 def test_base_url_setter(self) -> None: - client = Brainbase(base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True) + client = Brainbase( + base_url="https://example.com/from_init", bearer_token=bearer_token, _strict_response_validation=True + ) assert client.base_url == "https://example.com/from_init/" client.base_url = "https://example.com/from_setter" # type: ignore[assignment] @@ -555,16 +556,20 @@ def test_base_url_setter(self) -> None: def test_base_url_env(self) -> None: with update_env(BRAINBASE_BASE_URL="http://localhost:5000/from/env"): - client = Brainbase(api_key=api_key, _strict_response_validation=True) + client = Brainbase(bearer_token=bearer_token, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @pytest.mark.parametrize( "client", [ - Brainbase(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), Brainbase( base_url="http://localhost:5000/custom/path/", - api_key=api_key, + bearer_token=bearer_token, + _strict_response_validation=True, + ), + Brainbase( + base_url="http://localhost:5000/custom/path/", + bearer_token=bearer_token, _strict_response_validation=True, http_client=httpx.Client(), ), @@ -584,10 +589,14 @@ def test_base_url_trailing_slash(self, client: Brainbase) -> None: @pytest.mark.parametrize( "client", [ - Brainbase(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), Brainbase( base_url="http://localhost:5000/custom/path/", - api_key=api_key, + bearer_token=bearer_token, + _strict_response_validation=True, + ), + Brainbase( + base_url="http://localhost:5000/custom/path/", + bearer_token=bearer_token, _strict_response_validation=True, http_client=httpx.Client(), ), @@ -607,10 +616,14 @@ def test_base_url_no_trailing_slash(self, client: Brainbase) -> None: @pytest.mark.parametrize( "client", [ - Brainbase(base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True), Brainbase( base_url="http://localhost:5000/custom/path/", - api_key=api_key, + bearer_token=bearer_token, + _strict_response_validation=True, + ), + Brainbase( + base_url="http://localhost:5000/custom/path/", + bearer_token=bearer_token, _strict_response_validation=True, http_client=httpx.Client(), ), @@ -628,7 +641,7 @@ def test_absolute_request_url(self, client: Brainbase) -> None: assert request.url == "https://myapi.com/foo" def test_copied_client_does_not_close_http(self) -> None: - client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) assert not client.is_closed() copied = client.copy() @@ -639,7 +652,7 @@ def test_copied_client_does_not_close_http(self) -> None: assert not client.is_closed() def test_client_context_manager(self) -> None: - client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) with client as c2: assert c2 is client assert not c2.is_closed() @@ -660,7 +673,12 @@ class Model(BaseModel): def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): - Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None)) + Brainbase( + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + max_retries=cast(Any, None), + ) @pytest.mark.respx(base_url=base_url) def test_received_text_for_expected_json(self, respx_mock: MockRouter) -> None: @@ -669,12 +687,12 @@ class Model(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) - strict_client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + strict_client = Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) - client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=False) + client = Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=False) response = client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] @@ -702,7 +720,7 @@ class Model(BaseModel): ) @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) @@ -812,7 +830,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: class TestAsyncBrainbase: - client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio @@ -840,9 +858,9 @@ def test_copy(self) -> None: copied = self.client.copy() assert id(copied) != id(self.client) - copied = self.client.copy(api_key="another My API Key") - assert copied.api_key == "another My API Key" - assert self.client.api_key == "My API Key" + copied = self.client.copy(bearer_token="another My Bearer Token") + assert copied.bearer_token == "another My Bearer Token" + assert self.client.bearer_token == "My Bearer Token" def test_copy_default_options(self) -> None: # options that have a default are overridden correctly @@ -862,7 +880,10 @@ def test_copy_default_options(self) -> None: def test_copy_default_headers(self) -> None: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, ) assert client.default_headers["X-Foo"] == "bar" @@ -896,7 +917,7 @@ def test_copy_default_headers(self) -> None: def test_copy_default_query(self) -> None: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" @@ -1021,7 +1042,7 @@ async def test_request_timeout(self) -> None: async def test_client_timeout_option(self) -> None: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, timeout=httpx.Timeout(0) ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1032,7 +1053,7 @@ async def test_http_client_timeout_option(self) -> None: # custom timeout given to the httpx client should be used async with httpx.AsyncClient(timeout=None) as http_client: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1042,7 +1063,7 @@ async def test_http_client_timeout_option(self) -> None: # no timeout given to the httpx client should not use the httpx default async with httpx.AsyncClient() as http_client: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1052,7 +1073,7 @@ async def test_http_client_timeout_option(self) -> None: # explicitly passing the default timeout currently results in it being ignored async with httpx.AsyncClient(timeout=HTTPX_DEFAULT_TIMEOUT) as http_client: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client + base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1064,14 +1085,17 @@ def test_invalid_http_client(self) -> None: with httpx.Client() as http_client: AsyncBrainbase( base_url=base_url, - api_key=api_key, + bearer_token=bearer_token, _strict_response_validation=True, http_client=cast(Any, http_client), ) def test_default_headers_option(self) -> None: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + default_headers={"X-Foo": "bar"}, ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) assert request.headers.get("x-foo") == "bar" @@ -1079,7 +1103,7 @@ def test_default_headers_option(self) -> None: client2 = AsyncBrainbase( base_url=base_url, - api_key=api_key, + bearer_token=bearer_token, _strict_response_validation=True, default_headers={ "X-Foo": "stainless", @@ -1090,19 +1114,12 @@ def test_default_headers_option(self) -> None: assert request.headers.get("x-foo") == "stainless" assert request.headers.get("x-stainless-lang") == "my-overriding-header" - def test_validate_headers(self) -> None: - client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) - request = client._build_request(FinalRequestOptions(method="get", url="/foo")) - assert request.headers.get("x-api-key") == api_key - - with pytest.raises(BrainbaseError): - with update_env(**{"BRAINBASE_API_KEY": Omit()}): - client2 = AsyncBrainbase(base_url=base_url, api_key=None, _strict_response_validation=True) - _ = client2 - def test_default_query_option(self) -> None: client = AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + default_query={"query_param": "bar"}, ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) @@ -1303,7 +1320,7 @@ class Model(BaseModel): def test_base_url_setter(self) -> None: client = AsyncBrainbase( - base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True + base_url="https://example.com/from_init", bearer_token=bearer_token, _strict_response_validation=True ) assert client.base_url == "https://example.com/from_init/" @@ -1313,18 +1330,20 @@ def test_base_url_setter(self) -> None: def test_base_url_env(self) -> None: with update_env(BRAINBASE_BASE_URL="http://localhost:5000/from/env"): - client = AsyncBrainbase(api_key=api_key, _strict_response_validation=True) + client = AsyncBrainbase(bearer_token=bearer_token, _strict_response_validation=True) assert client.base_url == "http://localhost:5000/from/env/" @pytest.mark.parametrize( "client", [ AsyncBrainbase( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True + base_url="http://localhost:5000/custom/path/", + bearer_token=bearer_token, + _strict_response_validation=True, ), AsyncBrainbase( base_url="http://localhost:5000/custom/path/", - api_key=api_key, + bearer_token=bearer_token, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), @@ -1345,11 +1364,13 @@ def test_base_url_trailing_slash(self, client: AsyncBrainbase) -> None: "client", [ AsyncBrainbase( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True + base_url="http://localhost:5000/custom/path/", + bearer_token=bearer_token, + _strict_response_validation=True, ), AsyncBrainbase( base_url="http://localhost:5000/custom/path/", - api_key=api_key, + bearer_token=bearer_token, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), @@ -1370,11 +1391,13 @@ def test_base_url_no_trailing_slash(self, client: AsyncBrainbase) -> None: "client", [ AsyncBrainbase( - base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True + base_url="http://localhost:5000/custom/path/", + bearer_token=bearer_token, + _strict_response_validation=True, ), AsyncBrainbase( base_url="http://localhost:5000/custom/path/", - api_key=api_key, + bearer_token=bearer_token, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), @@ -1392,7 +1415,7 @@ def test_absolute_request_url(self, client: AsyncBrainbase) -> None: assert request.url == "https://myapi.com/foo" async def test_copied_client_does_not_close_http(self) -> None: - client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) assert not client.is_closed() copied = client.copy() @@ -1404,7 +1427,7 @@ async def test_copied_client_does_not_close_http(self) -> None: assert not client.is_closed() async def test_client_context_manager(self) -> None: - client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) async with client as c2: assert c2 is client assert not c2.is_closed() @@ -1427,7 +1450,10 @@ class Model(BaseModel): async def test_client_max_retries_validation(self) -> None: with pytest.raises(TypeError, match=r"max_retries cannot be None"): AsyncBrainbase( - base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None) + base_url=base_url, + bearer_token=bearer_token, + _strict_response_validation=True, + max_retries=cast(Any, None), ) @pytest.mark.respx(base_url=base_url) @@ -1438,12 +1464,12 @@ class Model(BaseModel): respx_mock.get("/foo").mock(return_value=httpx.Response(200, text="my-custom-format")) - strict_client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + strict_client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) - client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=False) + client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=False) response = await client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] @@ -1472,7 +1498,7 @@ class Model(BaseModel): @mock.patch("time.time", mock.MagicMock(return_value=1696004797)) @pytest.mark.asyncio async def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str, timeout: float) -> None: - client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3)