diff --git a/.release-please-manifest.json b/.release-please-manifest.json index cce9d1c6..c523ce19 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.7.0" + ".": "1.8.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 681b4257..571d6bb0 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brainbase-egrigokhan%2Fbrainbase-a197a88d1abbdbd5c886875d2cf12ffd6abf79aec7d4dbd0439ed50197692eba.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brainbase-egrigokhan%2Fbrainbase-0c00485d66a3b7505f3247467ef293fa5fb43a64e90a8b03a4127a2d9b15e6ab.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b0d6c72..1e015572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 1.8.0 (2025-02-04) + +Full Changelog: [v1.7.0...v1.8.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.7.0...v1.8.0) + +### Features + +* **api:** update via SDK Studio ([#35](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/35)) ([7dd48a6](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/7dd48a6db45effaa20e9a3263d3c0b9b4803bef3)) + ## 1.7.0 (2025-02-04) Full Changelog: [v1.6.0...v1.7.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.6.0...v1.7.0) diff --git a/README.md b/README.md index 0868a8cb..722adcc3 100644 --- a/README.md +++ b/README.md @@ -24,25 +24,32 @@ pip install 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="My API Key", + api_key=os.environ.get("BRAINBASE_API_KEY"), # This is the default and can be omitted ) 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="My API Key", + api_key=os.environ.get("BRAINBASE_API_KEY"), # This is the default and can be omitted ) @@ -77,9 +84,7 @@ All errors inherit from `brainbase.APIError`. import brainbase from brainbase import Brainbase -client = Brainbase( - api_key="My API Key", -) +client = Brainbase() try: client.workers.list() @@ -122,7 +127,6 @@ from brainbase import Brainbase client = Brainbase( # default is 2 max_retries=0, - api_key="My API Key", ) # Or, configure per-request: @@ -141,13 +145,11 @@ from brainbase import Brainbase client = Brainbase( # 20 seconds (default is 1 minute) timeout=20.0, - api_key="My API Key", ) # More granular control: client = Brainbase( timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0), - api_key="My API Key", ) # Override per-request: @@ -191,9 +193,7 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to ```py from brainbase import Brainbase -client = Brainbase( - api_key="My API Key", -) +client = Brainbase() response = client.workers.with_raw_response.list() print(response.headers.get('X-My-Header')) @@ -274,7 +274,6 @@ client = Brainbase( proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0"), ), - api_key="My API Key", ) ``` @@ -291,9 +290,7 @@ By default the library closes underlying HTTP connections whenever the client is ```py from brainbase import Brainbase -with Brainbase( - api_key="My API Key", -) as client: +with Brainbase() as client: # make requests here ... diff --git a/pyproject.toml b/pyproject.toml index 7171cda0..5e7846e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "brainbase-labs" -version = "1.7.0" +version = "1.8.0" description = "The official Python library for the brainbase API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/brainbase/_client.py b/src/brainbase/_client.py index bbe9a56d..9192a946 100644 --- a/src/brainbase/_client.py +++ b/src/brainbase/_client.py @@ -113,6 +113,12 @@ 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]: @@ -275,6 +281,12 @@ 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]: diff --git a/src/brainbase/_version.py b/src/brainbase/_version.py index f17fa6d4..70e7e1d3 100644 --- a/src/brainbase/_version.py +++ b/src/brainbase/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "brainbase" -__version__ = "1.7.0" # x-release-please-version +__version__ = "1.8.0" # x-release-please-version diff --git a/tests/test_client.py b/tests/test_client.py index c4074ec6..4bf71630 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, APITimeoutError, APIResponseValidationError +from brainbase._exceptions import APIStatusError, BrainbaseError, APITimeoutError, APIResponseValidationError from brainbase._base_client import ( DEFAULT_TIMEOUT, HTTPX_DEFAULT_TIMEOUT, @@ -334,6 +334,16 @@ 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"} @@ -1080,6 +1090,16 @@ 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"}