From cce79248b7058f58c4fe7d98ea36ed534403c7a7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:03:36 +0000 Subject: [PATCH 1/5] chore: sync repo --- .github/workflows/publish-pypi.yml | 31 ---- .github/workflows/release-doctor.yml | 21 --- .release-please-manifest.json | 3 - .stats.yml | 4 +- CHANGELOG.md | 107 ------------- CONTRIBUTING.md | 4 +- README.md | 42 +++--- api.md | 3 +- bin/check-release-environment | 21 --- pyproject.toml | 10 +- release-please-config.json | 66 --------- requirements-dev.lock | 12 +- requirements.lock | 12 +- src/brainbase/_client.py | 12 -- src/brainbase/_version.py | 2 +- .../workers/deployments/deployments.py | 8 +- .../resources/workers/deployments/voice.py | 8 +- src/brainbase/resources/workers/flows.py | 8 +- src/brainbase/resources/workers/workers.py | 134 +++-------------- src/brainbase/types/__init__.py | 1 - src/brainbase/types/worker_create_params.py | 6 +- src/brainbase/types/worker_update_params.py | 15 -- tests/api_resources/test_workers.py | 140 ++++-------------- tests/test_client.py | 22 +-- 24 files changed, 108 insertions(+), 584 deletions(-) delete mode 100644 .github/workflows/publish-pypi.yml delete mode 100644 .github/workflows/release-doctor.yml delete mode 100644 .release-please-manifest.json delete mode 100644 CHANGELOG.md delete mode 100644 bin/check-release-environment delete mode 100644 release-please-config.json delete mode 100644 src/brainbase/types/worker_update_params.py diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml deleted file mode 100644 index 3fbc99f8..00000000 --- a/.github/workflows/publish-pypi.yml +++ /dev/null @@ -1,31 +0,0 @@ -# This workflow is triggered when a GitHub release is created. -# It can also be run manually to re-publish to PyPI in case it failed for some reason. -# You can run this workflow by navigating to https://www.github.com/BrainbaseHQ/brainbase-python-sdk/actions/workflows/publish-pypi.yml -name: Publish PyPI -on: - workflow_dispatch: - - release: - types: [published] - -jobs: - publish: - name: publish - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Rye - run: | - curl -sSf https://rye.astral.sh/get | bash - echo "$HOME/.rye/shims" >> $GITHUB_PATH - env: - RYE_VERSION: '0.35.0' - RYE_INSTALL_OPTION: '--yes' - - - name: Publish to PyPI - run: | - bash ./bin/publish-pypi - env: - PYPI_TOKEN: ${{ secrets.BRAINBASE_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml deleted file mode 100644 index 7c642abf..00000000 --- a/.github/workflows/release-doctor.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Release Doctor -on: - pull_request: - branches: - - main - workflow_dispatch: - -jobs: - release_doctor: - name: release doctor - runs-on: ubuntu-latest - if: github.repository == 'BrainbaseHQ/brainbase-python-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') - - steps: - - uses: actions/checkout@v4 - - - name: Check release environment - run: | - bash ./bin/check-release-environment - env: - PYPI_TOKEN: ${{ secrets.BRAINBASE_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json deleted file mode 100644 index c523ce19..00000000 --- a/.release-please-manifest.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - ".": "1.8.0" -} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 571d6bb0..e09e1277 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-0c00485d66a3b7505f3247467ef293fa5fb43a64e90a8b03a4127a2d9b15e6ab.yml +configured_endpoints: 14 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brainbase-egrigokhan%2Fbrainbase-6f838e7577a70ce7ba003119a6923a3cc26aaf0deede2045104dfcf4beebf664.yml diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 1e015572..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,107 +0,0 @@ -# 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) - -### Features - -* **api:** update via SDK Studio ([#33](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/33)) ([1a43ad3](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/1a43ad3644983ec2d83f2ed24e87142cf7088c28)) - - -### Chores - -* remove custom code ([67dfb3e](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/67dfb3e6cd1e11368ec1eb934f7004987014ec3c)) - -## 1.6.0 (2025-02-04) - -Full Changelog: [v1.5.0...v1.6.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.5.0...v1.6.0) - -### Features - -* **api:** update via SDK Studio ([#23](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/23)) ([b2bbdf6](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/b2bbdf640fa7b0b9163f0a7a6b8ab964cb2c1fa5)) - -## 1.5.0 (2025-02-04) - -Full Changelog: [v1.4.0...v1.5.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.4.0...v1.5.0) - -### Features - -* **api:** update via SDK Studio ([#10](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/10)) ([4fb75c8](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/4fb75c8c78c172cb0a80be304334803956968247)) -* **api:** update via SDK Studio ([#12](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/12)) ([a363549](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/a3635498129383f20cae75014ad9720e18cc7ec6)) -* **api:** update via SDK Studio ([#18](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/18)) ([5f5451c](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/5f5451cebcda05a40deef4104207be19e5f8e8ac)) -* **api:** update via SDK Studio ([#8](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/8)) ([312b657](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/312b657cf73569a314b3c64ed83521ca2bb576a5)) - - -### Chores - -* go live ([#1](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/1)) ([db8a29c](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/db8a29c23e871872bcfc26b15bc7e4b27b0b08b3)) -* update SDK settings ([#3](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/3)) ([c5e3c22](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/c5e3c223ba6a7df56e290877e55c31e81c1d4b52)) -* update SDK settings ([#5](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/5)) ([1e74403](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/1e744032bc5800bb1b4f97a703cfdd1a7a7dd922)) - -## 1.4.0 (2025-02-04) - -Full Changelog: [v1.3.0...v1.4.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.3.0...v1.4.0) - -### Features - -* **api:** update via SDK Studio ([#18](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/18)) ([0f710ec](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/0f710eccb1efe39a492b9c905b1d2c29ab8532b6)) - -## 1.3.0 (2025-02-04) - -Full Changelog: [v1.2.0...v1.3.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.2.0...v1.3.0) - -### Features - -* **api:** update via SDK Studio ([#10](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/10)) ([4fb75c8](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/4fb75c8c78c172cb0a80be304334803956968247)) -* **api:** update via SDK Studio ([#12](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/12)) ([a363549](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/a3635498129383f20cae75014ad9720e18cc7ec6)) -* **api:** update via SDK Studio ([#8](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/8)) ([312b657](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/312b657cf73569a314b3c64ed83521ca2bb576a5)) - - -### Chores - -* go live ([#1](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/1)) ([db8a29c](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/db8a29c23e871872bcfc26b15bc7e4b27b0b08b3)) -* update SDK settings ([#3](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/3)) ([c5e3c22](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/c5e3c223ba6a7df56e290877e55c31e81c1d4b52)) -* update SDK settings ([#5](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/5)) ([1e74403](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/1e744032bc5800bb1b4f97a703cfdd1a7a7dd922)) - -## 1.2.0 (2025-02-04) - -Full Changelog: [v1.1.0...v1.2.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.1.0...v1.2.0) - -### Features - -* **api:** update via SDK Studio ([#12](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/12)) ([a363549](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/a3635498129383f20cae75014ad9720e18cc7ec6)) - -## 1.1.0 (2025-02-04) - -Full Changelog: [v1.0.1...v1.1.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.0.1...v1.1.0) - -### Features - -* **api:** update via SDK Studio ([#10](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/10)) ([4fb75c8](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/4fb75c8c78c172cb0a80be304334803956968247)) -* **api:** update via SDK Studio ([#8](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/8)) ([312b657](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/312b657cf73569a314b3c64ed83521ca2bb576a5)) - -## 1.0.1 (2025-02-04) - -Full Changelog: [v1.0.0...v1.0.1](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v1.0.0...v1.0.1) - -### Chores - -* update SDK settings ([#5](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/5)) ([1e74403](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/1e744032bc5800bb1b4f97a703cfdd1a7a7dd922)) - -## 1.0.0 (2025-02-04) - -Full Changelog: [v0.0.1-alpha.0...v1.0.0](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v0.0.1-alpha.0...v1.0.0) - -### Chores - -* go live ([#1](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/1)) ([db8a29c](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/db8a29c23e871872bcfc26b15bc7e4b27b0b08b3)) -* update SDK settings ([#3](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/3)) ([c5e3c22](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/c5e3c223ba6a7df56e290877e55c31e81c1d4b52)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2cf8f44a..59ea9089 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,7 +63,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ pip install git+ssh://git@github.com/BrainbaseHQ/brainbase-python-sdk.git +$ pip install git+ssh://git@github.com/stainless-sdks/brainbase-python.git ``` Alternatively, you can build from source and install the wheel file: @@ -121,7 +121,7 @@ the changes aren't made through the automated pipeline, you may want to make rel ### Publish with a GitHub workflow -You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/BrainbaseHQ/brainbase-python-sdk/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. +You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/stainless-sdks/brainbase-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. ### Publish manually diff --git a/README.md b/README.md index 722adcc3..6787b111 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Brainbase Python API library -[![PyPI version](https://img.shields.io/pypi/v/brainbase-labs.svg)](https://pypi.org/project/brainbase-labs/) +[![PyPI version](https://img.shields.io/pypi/v/brainbase.svg)](https://pypi.org/project/brainbase/) The Brainbase Python library provides convenient access to the Brainbase REST API from any Python 3.8+ application. The library includes type definitions for all request params and response fields, @@ -15,41 +15,37 @@ The REST API documentation can be found on [docs.brainbase.com](https://docs.bra ## Installation ```sh -# install from PyPI -pip install brainbase-labs +# install from this staging repo +pip install git+ssh://git@github.com/stainless-sdks/brainbase-python.git ``` +> [!NOTE] +> Once this package is [published to PyPI](https://app.stainlessapi.com/docs/guides/publish), this will become: `pip install --pre brainbase` + ## Usage 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 + api_key="My API Key", ) 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 + api_key="My API Key", ) @@ -84,7 +80,9 @@ All errors inherit from `brainbase.APIError`. import brainbase from brainbase import Brainbase -client = Brainbase() +client = Brainbase( + api_key="My API Key", +) try: client.workers.list() @@ -127,6 +125,7 @@ from brainbase import Brainbase client = Brainbase( # default is 2 max_retries=0, + api_key="My API Key", ) # Or, configure per-request: @@ -145,11 +144,13 @@ 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: @@ -193,7 +194,9 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to ```py from brainbase import Brainbase -client = Brainbase() +client = Brainbase( + api_key="My API Key", +) response = client.workers.with_raw_response.list() print(response.headers.get('X-My-Header')) @@ -201,9 +204,9 @@ worker = response.parse() # get the object that `workers.list()` would have ret print(worker) ``` -These methods return an [`APIResponse`](https://github.com/BrainbaseHQ/brainbase-python-sdk/tree/main/src/brainbase/_response.py) object. +These methods return an [`APIResponse`](https://github.com/stainless-sdks/brainbase-python/tree/main/src/brainbase/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/BrainbaseHQ/brainbase-python-sdk/tree/main/src/brainbase/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. +The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/brainbase-python/tree/main/src/brainbase/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -274,6 +277,7 @@ client = Brainbase( proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0"), ), + api_key="My API Key", ) ``` @@ -290,7 +294,9 @@ By default the library closes underlying HTTP connections whenever the client is ```py from brainbase import Brainbase -with Brainbase() as client: +with Brainbase( + api_key="My API Key", +) as client: # make requests here ... @@ -307,7 +313,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -We are keen for your feedback; please open an [issue](https://www.github.com/BrainbaseHQ/brainbase-python-sdk/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/brainbase-python/issues) with questions, bugs, or suggestions. ### Determining the installed version diff --git a/api.md b/api.md index 4e25a402..77b07ee9 100644 --- a/api.md +++ b/api.md @@ -2,9 +2,8 @@ Methods: -- client.workers.create(\*\*params) -> None +- client.workers.create(id, \*\*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/bin/check-release-environment b/bin/check-release-environment deleted file mode 100644 index 59422a48..00000000 --- a/bin/check-release-environment +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -errors=() - -if [ -z "${PYPI_TOKEN}" ]; then - errors+=("The BRAINBASE_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") -fi - -lenErrors=${#errors[@]} - -if [[ lenErrors -gt 0 ]]; then - echo -e "Found the following errors in the release environment:\n" - - for error in "${errors[@]}"; do - echo -e "- $error\n" - done - - exit 1 -fi - -echo "The environment is ready to push releases!" diff --git a/pyproject.toml b/pyproject.toml index 5e7846e6..d8ace7b9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] -name = "brainbase-labs" -version = "1.8.0" +name = "brainbase" +version = "0.0.1-alpha.0" description = "The official Python library for the brainbase API" dynamic = ["readme"] license = "Apache-2.0" @@ -34,8 +34,8 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/BrainbaseHQ/brainbase-python-sdk" -Repository = "https://github.com/BrainbaseHQ/brainbase-python-sdk" +Homepage = "https://github.com/stainless-sdks/brainbase-python" +Repository = "https://github.com/stainless-sdks/brainbase-python" @@ -122,7 +122,7 @@ path = "README.md" [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]] # replace relative links with absolute links pattern = '\[(.+?)\]\(((?!https?://)\S+?)\)' -replacement = '[\1](https://github.com/BrainbaseHQ/brainbase-python-sdk/tree/main/\g<2>)' +replacement = '[\1](https://github.com/stainless-sdks/brainbase-python/tree/main/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/release-please-config.json b/release-please-config.json deleted file mode 100644 index 3f255933..00000000 --- a/release-please-config.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "packages": { - ".": {} - }, - "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", - "include-v-in-tag": true, - "include-component-in-tag": false, - "versioning": "prerelease", - "prerelease": true, - "bump-minor-pre-major": true, - "bump-patch-for-minor-pre-major": false, - "pull-request-header": "Automated Release PR", - "pull-request-title-pattern": "release: ${version}", - "changelog-sections": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "perf", - "section": "Performance Improvements" - }, - { - "type": "revert", - "section": "Reverts" - }, - { - "type": "chore", - "section": "Chores" - }, - { - "type": "docs", - "section": "Documentation" - }, - { - "type": "style", - "section": "Styles" - }, - { - "type": "refactor", - "section": "Refactors" - }, - { - "type": "test", - "section": "Tests", - "hidden": true - }, - { - "type": "build", - "section": "Build System" - }, - { - "type": "ci", - "section": "Continuous Integration", - "hidden": true - } - ], - "release-type": "python", - "extra-files": [ - "src/brainbase/_version.py" - ] -} \ No newline at end of file diff --git a/requirements-dev.lock b/requirements-dev.lock index 2ccbd89c..8ab32139 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -12,7 +12,7 @@ annotated-types==0.6.0 # via pydantic anyio==4.4.0 - # via brainbase-labs + # via brainbase # via httpx argcomplete==3.1.2 # via nox @@ -25,7 +25,7 @@ dirty-equals==0.6.0 distlib==0.3.7 # via virtualenv distro==1.8.0 - # via brainbase-labs + # via brainbase exceptiongroup==1.2.2 # via anyio # via pytest @@ -36,7 +36,7 @@ h11==0.14.0 httpcore==1.0.2 # via httpx httpx==0.28.1 - # via brainbase-labs + # via brainbase # via respx idna==3.4 # via anyio @@ -63,7 +63,7 @@ platformdirs==3.11.0 pluggy==1.5.0 # via pytest pydantic==2.10.3 - # via brainbase-labs + # via brainbase pydantic-core==2.27.1 # via pydantic pygments==2.18.0 @@ -85,14 +85,14 @@ six==1.16.0 # via python-dateutil sniffio==1.3.0 # via anyio - # via brainbase-labs + # via brainbase time-machine==2.9.0 tomli==2.0.2 # via mypy # via pytest typing-extensions==4.12.2 # via anyio - # via brainbase-labs + # via brainbase # via mypy # via pydantic # via pydantic-core diff --git a/requirements.lock b/requirements.lock index ab585024..c06830b2 100644 --- a/requirements.lock +++ b/requirements.lock @@ -12,13 +12,13 @@ annotated-types==0.6.0 # via pydantic anyio==4.4.0 - # via brainbase-labs + # via brainbase # via httpx certifi==2023.7.22 # via httpcore # via httpx distro==1.8.0 - # via brainbase-labs + # via brainbase exceptiongroup==1.2.2 # via anyio h11==0.14.0 @@ -26,19 +26,19 @@ h11==0.14.0 httpcore==1.0.2 # via httpx httpx==0.28.1 - # via brainbase-labs + # via brainbase idna==3.4 # via anyio # via httpx pydantic==2.10.3 - # via brainbase-labs + # via brainbase pydantic-core==2.27.1 # via pydantic sniffio==1.3.0 # via anyio - # via brainbase-labs + # via brainbase typing-extensions==4.12.2 # via anyio - # via brainbase-labs + # via brainbase # via pydantic # via pydantic-core diff --git a/src/brainbase/_client.py b/src/brainbase/_client.py index 9192a946..bbe9a56d 100644 --- a/src/brainbase/_client.py +++ b/src/brainbase/_client.py @@ -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]: @@ -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]: diff --git a/src/brainbase/_version.py b/src/brainbase/_version.py index 70e7e1d3..f41cdb5a 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.8.0" # x-release-please-version +__version__ = "0.0.1-alpha.0" diff --git a/src/brainbase/resources/workers/deployments/deployments.py b/src/brainbase/resources/workers/deployments/deployments.py index 93735470..13a0ae86 100644 --- a/src/brainbase/resources/workers/deployments/deployments.py +++ b/src/brainbase/resources/workers/deployments/deployments.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> DeploymentsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return DeploymentsResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> DeploymentsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return DeploymentsResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncDeploymentsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return AsyncDeploymentsResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncDeploymentsResourceWithStreamingRespon """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return AsyncDeploymentsResourceWithStreamingResponse(self) diff --git a/src/brainbase/resources/workers/deployments/voice.py b/src/brainbase/resources/workers/deployments/voice.py index 57cc1313..b82a3386 100644 --- a/src/brainbase/resources/workers/deployments/voice.py +++ b/src/brainbase/resources/workers/deployments/voice.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> VoiceResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return VoiceResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> VoiceResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return VoiceResourceWithStreamingResponse(self) @@ -264,7 +264,7 @@ def with_raw_response(self) -> AsyncVoiceResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return AsyncVoiceResourceWithRawResponse(self) @@ -273,7 +273,7 @@ def with_streaming_response(self) -> AsyncVoiceResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return AsyncVoiceResourceWithStreamingResponse(self) diff --git a/src/brainbase/resources/workers/flows.py b/src/brainbase/resources/workers/flows.py index f91b1a3b..2b27f22d 100644 --- a/src/brainbase/resources/workers/flows.py +++ b/src/brainbase/resources/workers/flows.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> FlowsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return FlowsResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> FlowsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return FlowsResourceWithStreamingResponse(self) @@ -252,7 +252,7 @@ def with_raw_response(self) -> AsyncFlowsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return AsyncFlowsResourceWithRawResponse(self) @@ -261,7 +261,7 @@ def with_streaming_response(self) -> AsyncFlowsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return AsyncFlowsResourceWithStreamingResponse(self) diff --git a/src/brainbase/resources/workers/workers.py b/src/brainbase/resources/workers/workers.py index 323da4da..ced9ec05 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, worker_update_params +from ...types import worker_create_params from ..._types import NOT_GIVEN, Body, Query, Headers, NoneType, NotGiven from ..._utils import ( maybe_transform, @@ -54,7 +54,7 @@ def with_raw_response(self) -> WorkersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return WorkersResourceWithRawResponse(self) @@ -63,15 +63,16 @@ def with_streaming_response(self) -> WorkersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return WorkersResourceWithStreamingResponse(self) def create( self, + id: str, *, - name: 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. @@ -81,7 +82,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: """ - Create a new worker + Update a worker Args: extra_headers: Send extra headers @@ -92,13 +93,15 @@ def create( 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( - "/api/workers", + f"/api/workers/{id}", body=maybe_transform( { - "name": name, "description": description, + "name": name, "status": status, }, worker_create_params.WorkerCreateParams, @@ -143,51 +146,6 @@ 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, *, @@ -258,7 +216,7 @@ def with_raw_response(self) -> AsyncWorkersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers """ return AsyncWorkersResourceWithRawResponse(self) @@ -267,15 +225,16 @@ def with_streaming_response(self) -> AsyncWorkersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response + For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response """ return AsyncWorkersResourceWithStreamingResponse(self) async def create( self, + id: str, *, - name: 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. @@ -285,7 +244,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: """ - Create a new worker + Update a worker Args: extra_headers: Send extra headers @@ -296,13 +255,15 @@ async def create( 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( - "/api/workers", + f"/api/workers/{id}", body=await async_maybe_transform( { - "name": name, "description": description, + "name": name, "status": status, }, worker_create_params.WorkerCreateParams, @@ -347,51 +308,6 @@ 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, *, @@ -457,9 +373,6 @@ 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, ) @@ -486,9 +399,6 @@ 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, ) @@ -515,9 +425,6 @@ 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, ) @@ -544,9 +451,6 @@ 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 065250e2..5976bd7c 100644 --- a/src/brainbase/types/__init__.py +++ b/src/brainbase/types/__init__.py @@ -3,4 +3,3 @@ 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_create_params.py b/src/brainbase/types/worker_create_params.py index 757c0420..f84e516c 100644 --- a/src/brainbase/types/worker_create_params.py +++ b/src/brainbase/types/worker_create_params.py @@ -2,14 +2,14 @@ from __future__ import annotations -from typing_extensions import Required, TypedDict +from typing_extensions import TypedDict __all__ = ["WorkerCreateParams"] class WorkerCreateParams(TypedDict, total=False): - name: Required[str] - description: str + name: str + status: str diff --git a/src/brainbase/types/worker_update_params.py b/src/brainbase/types/worker_update_params.py deleted file mode 100644 index bfa7a019..00000000 --- a/src/brainbase/types/worker_update_params.py +++ /dev/null @@ -1,15 +0,0 @@ -# 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 2a9a36aa..a6c4d926 100644 --- a/tests/api_resources/test_workers.py +++ b/tests/api_resources/test_workers.py @@ -19,7 +19,7 @@ class TestWorkers: @parametrize def test_method_create(self, client: Brainbase) -> None: worker = client.workers.create( - name="name", + id="id", ) assert worker is None @@ -27,8 +27,9 @@ def test_method_create(self, client: Brainbase) -> None: @parametrize def test_method_create_with_all_params(self, client: Brainbase) -> None: worker = client.workers.create( - name="name", + id="id", description="description", + name="name", status="status", ) assert worker is None @@ -37,7 +38,7 @@ def test_method_create_with_all_params(self, client: Brainbase) -> None: @parametrize def test_raw_response_create(self, client: Brainbase) -> None: response = client.workers.with_raw_response.create( - name="name", + id="id", ) assert response.is_closed is True @@ -49,7 +50,7 @@ def test_raw_response_create(self, client: Brainbase) -> None: @parametrize def test_streaming_response_create(self, client: Brainbase) -> None: with client.workers.with_streaming_response.create( - name="name", + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -59,6 +60,14 @@ def test_streaming_response_create(self, client: Brainbase) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip() + @parametrize + def test_path_params_create(self, client: Brainbase) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.workers.with_raw_response.create( + id="", + ) + @pytest.mark.skip() @parametrize def test_method_retrieve(self, client: Brainbase) -> None: @@ -101,59 +110,6 @@ 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: @@ -232,7 +188,7 @@ class TestAsyncWorkers: @parametrize async def test_method_create(self, async_client: AsyncBrainbase) -> None: worker = await async_client.workers.create( - name="name", + id="id", ) assert worker is None @@ -240,8 +196,9 @@ async def test_method_create(self, async_client: AsyncBrainbase) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncBrainbase) -> None: worker = await async_client.workers.create( - name="name", + id="id", description="description", + name="name", status="status", ) assert worker is None @@ -250,7 +207,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncBrainbase) @parametrize async def test_raw_response_create(self, async_client: AsyncBrainbase) -> None: response = await async_client.workers.with_raw_response.create( - name="name", + id="id", ) assert response.is_closed is True @@ -262,7 +219,7 @@ async def test_raw_response_create(self, async_client: AsyncBrainbase) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncBrainbase) -> None: async with async_client.workers.with_streaming_response.create( - name="name", + id="id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -272,6 +229,14 @@ async def test_streaming_response_create(self, async_client: AsyncBrainbase) -> assert cast(Any, response.is_closed) is True + @pytest.mark.skip() + @parametrize + async def test_path_params_create(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.create( + id="", + ) + @pytest.mark.skip() @parametrize async def test_method_retrieve(self, async_client: AsyncBrainbase) -> None: @@ -314,59 +279,6 @@ 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/test_client.py b/tests/test_client.py index 4bf71630..c4074ec6 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, @@ -334,16 +334,6 @@ 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"} @@ -1090,16 +1080,6 @@ 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"} From bc32c04421def2b0a84a5def7f5a4bb08546d704 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:03:58 +0000 Subject: [PATCH 2/5] feat(api): update via SDK Studio (#38) --- .github/workflows/publish-pypi.yml | 31 +++++++++ .github/workflows/release-doctor.yml | 21 ++++++ .release-please-manifest.json | 3 + .stats.yml | 2 +- CONTRIBUTING.md | 4 +- README.md | 42 +++++------- api.md | 2 +- bin/check-release-environment | 21 ++++++ pyproject.toml | 8 +-- release-please-config.json | 66 +++++++++++++++++++ requirements-dev.lock | 12 ++-- requirements.lock | 12 ++-- src/brainbase/_client.py | 12 ++++ src/brainbase/_version.py | 2 +- .../workers/deployments/deployments.py | 8 +-- .../resources/workers/deployments/voice.py | 8 +-- src/brainbase/resources/workers/flows.py | 8 +-- src/brainbase/resources/workers/workers.py | 30 ++++----- src/brainbase/types/worker_create_params.py | 6 +- tests/api_resources/test_workers.py | 34 +++------- tests/test_client.py | 22 ++++++- 21 files changed, 249 insertions(+), 105 deletions(-) create mode 100644 .github/workflows/publish-pypi.yml create mode 100644 .github/workflows/release-doctor.yml create mode 100644 .release-please-manifest.json create mode 100644 bin/check-release-environment create mode 100644 release-please-config.json diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml new file mode 100644 index 00000000..3fbc99f8 --- /dev/null +++ b/.github/workflows/publish-pypi.yml @@ -0,0 +1,31 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to PyPI in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/BrainbaseHQ/brainbase-python-sdk/actions/workflows/publish-pypi.yml +name: Publish PyPI +on: + workflow_dispatch: + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Install Rye + run: | + curl -sSf https://rye.astral.sh/get | bash + echo "$HOME/.rye/shims" >> $GITHUB_PATH + env: + RYE_VERSION: '0.35.0' + RYE_INSTALL_OPTION: '--yes' + + - name: Publish to PyPI + run: | + bash ./bin/publish-pypi + env: + PYPI_TOKEN: ${{ secrets.BRAINBASE_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 00000000..7c642abf --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,21 @@ +name: Release Doctor +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'BrainbaseHQ/brainbase-python-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v4 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + env: + PYPI_TOKEN: ${{ secrets.BRAINBASE_PYPI_TOKEN || secrets.PYPI_TOKEN }} diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 00000000..c4762802 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1-alpha.0" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index e09e1277..73df72e5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 14 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brainbase-egrigokhan%2Fbrainbase-6f838e7577a70ce7ba003119a6923a3cc26aaf0deede2045104dfcf4beebf664.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/brainbase-egrigokhan%2Fbrainbase-0c00485d66a3b7505f3247467ef293fa5fb43a64e90a8b03a4127a2d9b15e6ab.yml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 59ea9089..2cf8f44a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,7 +63,7 @@ If you’d like to use the repository from source, you can either install from g To install via git: ```sh -$ pip install git+ssh://git@github.com/stainless-sdks/brainbase-python.git +$ pip install git+ssh://git@github.com/BrainbaseHQ/brainbase-python-sdk.git ``` Alternatively, you can build from source and install the wheel file: @@ -121,7 +121,7 @@ the changes aren't made through the automated pipeline, you may want to make rel ### Publish with a GitHub workflow -You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/stainless-sdks/brainbase-python/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. +You can release to package managers by using [the `Publish PyPI` GitHub action](https://www.github.com/BrainbaseHQ/brainbase-python-sdk/actions/workflows/publish-pypi.yml). This requires a setup organization or repository secret to be set up. ### Publish manually diff --git a/README.md b/README.md index 6787b111..bd87518a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Brainbase Python API library -[![PyPI version](https://img.shields.io/pypi/v/brainbase.svg)](https://pypi.org/project/brainbase/) +[![PyPI version](https://img.shields.io/pypi/v/brainbase-labs.svg)](https://pypi.org/project/brainbase-labs/) The Brainbase Python library provides convenient access to the Brainbase REST API from any Python 3.8+ application. The library includes type definitions for all request params and response fields, @@ -15,37 +15,41 @@ The REST API documentation can be found on [docs.brainbase.com](https://docs.bra ## Installation ```sh -# install from this staging repo -pip install git+ssh://git@github.com/stainless-sdks/brainbase-python.git +# install from PyPI +pip install --pre brainbase-labs ``` -> [!NOTE] -> Once this package is [published to PyPI](https://app.stainlessapi.com/docs/guides/publish), this will become: `pip install --pre brainbase` - ## Usage 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 ) @@ -80,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() @@ -125,7 +127,6 @@ from brainbase import Brainbase client = Brainbase( # default is 2 max_retries=0, - api_key="My API Key", ) # Or, configure per-request: @@ -144,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: @@ -194,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')) @@ -204,9 +201,9 @@ worker = response.parse() # get the object that `workers.list()` would have ret print(worker) ``` -These methods return an [`APIResponse`](https://github.com/stainless-sdks/brainbase-python/tree/main/src/brainbase/_response.py) object. +These methods return an [`APIResponse`](https://github.com/BrainbaseHQ/brainbase-python-sdk/tree/main/src/brainbase/_response.py) object. -The async client returns an [`AsyncAPIResponse`](https://github.com/stainless-sdks/brainbase-python/tree/main/src/brainbase/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. +The async client returns an [`AsyncAPIResponse`](https://github.com/BrainbaseHQ/brainbase-python-sdk/tree/main/src/brainbase/_response.py) with the same structure, the only difference being `await`able methods for reading the response content. #### `.with_streaming_response` @@ -277,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", ) ``` @@ -294,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 ... @@ -313,7 +307,7 @@ This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) con We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. -We are keen for your feedback; please open an [issue](https://www.github.com/stainless-sdks/brainbase-python/issues) with questions, bugs, or suggestions. +We are keen for your feedback; please open an [issue](https://www.github.com/BrainbaseHQ/brainbase-python-sdk/issues) with questions, bugs, or suggestions. ### Determining the installed version diff --git a/api.md b/api.md index 77b07ee9..6f634335 100644 --- a/api.md +++ b/api.md @@ -2,7 +2,7 @@ Methods: -- client.workers.create(id, \*\*params) -> None +- client.workers.create(\*\*params) -> None - client.workers.retrieve(id) -> None - client.workers.list() -> None - client.workers.delete(id) -> None diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 00000000..59422a48 --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${PYPI_TOKEN}" ]; then + errors+=("The BRAINBASE_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.") +fi + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" diff --git a/pyproject.toml b/pyproject.toml index d8ace7b9..52a90e3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [project] -name = "brainbase" +name = "brainbase-labs" version = "0.0.1-alpha.0" description = "The official Python library for the brainbase API" dynamic = ["readme"] @@ -34,8 +34,8 @@ classifiers = [ ] [project.urls] -Homepage = "https://github.com/stainless-sdks/brainbase-python" -Repository = "https://github.com/stainless-sdks/brainbase-python" +Homepage = "https://github.com/BrainbaseHQ/brainbase-python-sdk" +Repository = "https://github.com/BrainbaseHQ/brainbase-python-sdk" @@ -122,7 +122,7 @@ path = "README.md" [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]] # replace relative links with absolute links pattern = '\[(.+?)\]\(((?!https?://)\S+?)\)' -replacement = '[\1](https://github.com/stainless-sdks/brainbase-python/tree/main/\g<2>)' +replacement = '[\1](https://github.com/BrainbaseHQ/brainbase-python-sdk/tree/main/\g<2>)' [tool.pytest.ini_options] testpaths = ["tests"] diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 00000000..3f255933 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,66 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "python", + "extra-files": [ + "src/brainbase/_version.py" + ] +} \ No newline at end of file diff --git a/requirements-dev.lock b/requirements-dev.lock index 8ab32139..2ccbd89c 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -12,7 +12,7 @@ annotated-types==0.6.0 # via pydantic anyio==4.4.0 - # via brainbase + # via brainbase-labs # via httpx argcomplete==3.1.2 # via nox @@ -25,7 +25,7 @@ dirty-equals==0.6.0 distlib==0.3.7 # via virtualenv distro==1.8.0 - # via brainbase + # via brainbase-labs exceptiongroup==1.2.2 # via anyio # via pytest @@ -36,7 +36,7 @@ h11==0.14.0 httpcore==1.0.2 # via httpx httpx==0.28.1 - # via brainbase + # via brainbase-labs # via respx idna==3.4 # via anyio @@ -63,7 +63,7 @@ platformdirs==3.11.0 pluggy==1.5.0 # via pytest pydantic==2.10.3 - # via brainbase + # via brainbase-labs pydantic-core==2.27.1 # via pydantic pygments==2.18.0 @@ -85,14 +85,14 @@ six==1.16.0 # via python-dateutil sniffio==1.3.0 # via anyio - # via brainbase + # via brainbase-labs time-machine==2.9.0 tomli==2.0.2 # via mypy # via pytest typing-extensions==4.12.2 # via anyio - # via brainbase + # via brainbase-labs # via mypy # via pydantic # via pydantic-core diff --git a/requirements.lock b/requirements.lock index c06830b2..ab585024 100644 --- a/requirements.lock +++ b/requirements.lock @@ -12,13 +12,13 @@ annotated-types==0.6.0 # via pydantic anyio==4.4.0 - # via brainbase + # via brainbase-labs # via httpx certifi==2023.7.22 # via httpcore # via httpx distro==1.8.0 - # via brainbase + # via brainbase-labs exceptiongroup==1.2.2 # via anyio h11==0.14.0 @@ -26,19 +26,19 @@ h11==0.14.0 httpcore==1.0.2 # via httpx httpx==0.28.1 - # via brainbase + # via brainbase-labs idna==3.4 # via anyio # via httpx pydantic==2.10.3 - # via brainbase + # via brainbase-labs pydantic-core==2.27.1 # via pydantic sniffio==1.3.0 # via anyio - # via brainbase + # via brainbase-labs typing-extensions==4.12.2 # via anyio - # via brainbase + # via brainbase-labs # via pydantic # via pydantic-core 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 f41cdb5a..29916c66 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__ = "0.0.1-alpha.0" +__version__ = "0.0.1-alpha.0" # x-release-please-version diff --git a/src/brainbase/resources/workers/deployments/deployments.py b/src/brainbase/resources/workers/deployments/deployments.py index 13a0ae86..93735470 100644 --- a/src/brainbase/resources/workers/deployments/deployments.py +++ b/src/brainbase/resources/workers/deployments/deployments.py @@ -27,7 +27,7 @@ def with_raw_response(self) -> DeploymentsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return DeploymentsResourceWithRawResponse(self) @@ -36,7 +36,7 @@ def with_streaming_response(self) -> DeploymentsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return DeploymentsResourceWithStreamingResponse(self) @@ -52,7 +52,7 @@ def with_raw_response(self) -> AsyncDeploymentsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return AsyncDeploymentsResourceWithRawResponse(self) @@ -61,7 +61,7 @@ def with_streaming_response(self) -> AsyncDeploymentsResourceWithStreamingRespon """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return AsyncDeploymentsResourceWithStreamingResponse(self) diff --git a/src/brainbase/resources/workers/deployments/voice.py b/src/brainbase/resources/workers/deployments/voice.py index b82a3386..57cc1313 100644 --- a/src/brainbase/resources/workers/deployments/voice.py +++ b/src/brainbase/resources/workers/deployments/voice.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> VoiceResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return VoiceResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> VoiceResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return VoiceResourceWithStreamingResponse(self) @@ -264,7 +264,7 @@ def with_raw_response(self) -> AsyncVoiceResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return AsyncVoiceResourceWithRawResponse(self) @@ -273,7 +273,7 @@ def with_streaming_response(self) -> AsyncVoiceResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return AsyncVoiceResourceWithStreamingResponse(self) diff --git a/src/brainbase/resources/workers/flows.py b/src/brainbase/resources/workers/flows.py index 2b27f22d..f91b1a3b 100644 --- a/src/brainbase/resources/workers/flows.py +++ b/src/brainbase/resources/workers/flows.py @@ -30,7 +30,7 @@ def with_raw_response(self) -> FlowsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return FlowsResourceWithRawResponse(self) @@ -39,7 +39,7 @@ def with_streaming_response(self) -> FlowsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return FlowsResourceWithStreamingResponse(self) @@ -252,7 +252,7 @@ def with_raw_response(self) -> AsyncFlowsResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return AsyncFlowsResourceWithRawResponse(self) @@ -261,7 +261,7 @@ def with_streaming_response(self) -> AsyncFlowsResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return AsyncFlowsResourceWithStreamingResponse(self) diff --git a/src/brainbase/resources/workers/workers.py b/src/brainbase/resources/workers/workers.py index ced9ec05..9d2eb83c 100644 --- a/src/brainbase/resources/workers/workers.py +++ b/src/brainbase/resources/workers/workers.py @@ -54,7 +54,7 @@ def with_raw_response(self) -> WorkersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return WorkersResourceWithRawResponse(self) @@ -63,16 +63,15 @@ def with_streaming_response(self) -> WorkersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return WorkersResourceWithStreamingResponse(self) def create( self, - id: str, *, + name: 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. @@ -82,7 +81,7 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: """ - Update a worker + Create a new worker Args: extra_headers: Send extra headers @@ -93,15 +92,13 @@ def create( 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}", + "/api/workers", body=maybe_transform( { - "description": description, "name": name, + "description": description, "status": status, }, worker_create_params.WorkerCreateParams, @@ -216,7 +213,7 @@ def with_raw_response(self) -> AsyncWorkersResourceWithRawResponse: This property can be used as a prefix for any HTTP method call to return the raw response object instead of the parsed content. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#accessing-raw-response-data-eg-headers + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#accessing-raw-response-data-eg-headers """ return AsyncWorkersResourceWithRawResponse(self) @@ -225,16 +222,15 @@ def with_streaming_response(self) -> AsyncWorkersResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. - For more information, see https://www.github.com/stainless-sdks/brainbase-python#with_streaming_response + For more information, see https://www.github.com/BrainbaseHQ/brainbase-python-sdk#with_streaming_response """ return AsyncWorkersResourceWithStreamingResponse(self) async def create( self, - id: str, *, + name: 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. @@ -244,7 +240,7 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> None: """ - Update a worker + Create a new worker Args: extra_headers: Send extra headers @@ -255,15 +251,13 @@ async def create( 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}", + "/api/workers", body=await async_maybe_transform( { - "description": description, "name": name, + "description": description, "status": status, }, worker_create_params.WorkerCreateParams, diff --git a/src/brainbase/types/worker_create_params.py b/src/brainbase/types/worker_create_params.py index f84e516c..757c0420 100644 --- a/src/brainbase/types/worker_create_params.py +++ b/src/brainbase/types/worker_create_params.py @@ -2,14 +2,14 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing_extensions import Required, TypedDict __all__ = ["WorkerCreateParams"] class WorkerCreateParams(TypedDict, total=False): - description: str + name: Required[str] - name: str + description: str status: str diff --git a/tests/api_resources/test_workers.py b/tests/api_resources/test_workers.py index a6c4d926..5f524f47 100644 --- a/tests/api_resources/test_workers.py +++ b/tests/api_resources/test_workers.py @@ -19,7 +19,7 @@ class TestWorkers: @parametrize def test_method_create(self, client: Brainbase) -> None: worker = client.workers.create( - id="id", + name="name", ) assert worker is None @@ -27,9 +27,8 @@ def test_method_create(self, client: Brainbase) -> None: @parametrize def test_method_create_with_all_params(self, client: Brainbase) -> None: worker = client.workers.create( - id="id", - description="description", name="name", + description="description", status="status", ) assert worker is None @@ -38,7 +37,7 @@ def test_method_create_with_all_params(self, client: Brainbase) -> None: @parametrize def test_raw_response_create(self, client: Brainbase) -> None: response = client.workers.with_raw_response.create( - id="id", + name="name", ) assert response.is_closed is True @@ -50,7 +49,7 @@ def test_raw_response_create(self, client: Brainbase) -> None: @parametrize def test_streaming_response_create(self, client: Brainbase) -> None: with client.workers.with_streaming_response.create( - id="id", + name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -60,14 +59,6 @@ def test_streaming_response_create(self, client: Brainbase) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip() - @parametrize - def test_path_params_create(self, client: Brainbase) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): - client.workers.with_raw_response.create( - id="", - ) - @pytest.mark.skip() @parametrize def test_method_retrieve(self, client: Brainbase) -> None: @@ -188,7 +179,7 @@ class TestAsyncWorkers: @parametrize async def test_method_create(self, async_client: AsyncBrainbase) -> None: worker = await async_client.workers.create( - id="id", + name="name", ) assert worker is None @@ -196,9 +187,8 @@ async def test_method_create(self, async_client: AsyncBrainbase) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncBrainbase) -> None: worker = await async_client.workers.create( - id="id", - description="description", name="name", + description="description", status="status", ) assert worker is None @@ -207,7 +197,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncBrainbase) @parametrize async def test_raw_response_create(self, async_client: AsyncBrainbase) -> None: response = await async_client.workers.with_raw_response.create( - id="id", + name="name", ) assert response.is_closed is True @@ -219,7 +209,7 @@ async def test_raw_response_create(self, async_client: AsyncBrainbase) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncBrainbase) -> None: async with async_client.workers.with_streaming_response.create( - id="id", + name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -229,14 +219,6 @@ async def test_streaming_response_create(self, async_client: AsyncBrainbase) -> assert cast(Any, response.is_closed) is True - @pytest.mark.skip() - @parametrize - async def test_path_params_create(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.create( - id="", - ) - @pytest.mark.skip() @parametrize async def test_method_retrieve(self, async_client: AsyncBrainbase) -> None: 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"} From 801bbaaddaddba829cf554d8b0ee0bc4c229ee40 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:05:17 +0000 Subject: [PATCH 3/5] feat(api): update via SDK Studio (#40) --- .stats.yml | 2 +- README.md | 27 +-- api.md | 1 + src/brainbase/_client.py | 52 +++--- src/brainbase/resources/workers/workers.py | 104 ++++++++++- src/brainbase/types/__init__.py | 1 + src/brainbase/types/worker_update_params.py | 15 ++ tests/api_resources/test_workers.py | 106 ++++++++++++ tests/conftest.py | 8 +- tests/test_client.py | 182 +++++++++++--------- 10 files changed, 371 insertions(+), 127 deletions(-) create mode 100644 src/brainbase/types/worker_update_params.py 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) From fb611f97127b4b491884acf8ccd636ebea0e858c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:07:50 +0000 Subject: [PATCH 4/5] feat(api): update via SDK Studio (#41) --- README.md | 29 +++---- src/brainbase/_client.py | 52 ++++++----- tests/conftest.py | 8 +- tests/test_client.py | 182 +++++++++++++++++---------------------- 4 files changed, 126 insertions(+), 145 deletions(-) diff --git a/README.md b/README.md index 9981e1b9..7a599b1c 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 [docs.brainbase.com](https://docs.brainbase.com). The full API of this library can be found in [api.md](api.md). +The REST API documentation can be found on [docs.usebrainbase.com](https://docs.usebrainbase.com). The full API of this library can be found in [api.md](api.md). ## Installation @@ -24,25 +24,32 @@ 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( - bearer_token="My Bearer Token", + 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( - bearer_token="My Bearer Token", + 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( - bearer_token="My Bearer Token", -) +client = Brainbase() try: client.workers.list() @@ -122,7 +127,6 @@ from brainbase import Brainbase client = Brainbase( # default is 2 max_retries=0, - bearer_token="My Bearer Token", ) # Or, configure per-request: @@ -141,13 +145,11 @@ 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: @@ -191,9 +193,7 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to ```py from brainbase import Brainbase -client = Brainbase( - bearer_token="My Bearer Token", -) +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"), ), - bearer_token="My Bearer Token", ) ``` @@ -291,9 +290,7 @@ By default the library closes underlying HTTP connections whenever the client is ```py from brainbase import Brainbase -with Brainbase( - bearer_token="My Bearer Token", -) as client: +with Brainbase() as client: # make requests here ... diff --git a/src/brainbase/_client.py b/src/brainbase/_client.py index 3c4f9565..9192a946 100644 --- a/src/brainbase/_client.py +++ b/src/brainbase/_client.py @@ -51,12 +51,12 @@ class Brainbase(SyncAPIClient): with_streaming_response: BrainbaseWithStreamedResponse # client options - bearer_token: str + api_key: str def __init__( self, *, - bearer_token: str | None = None, + api_key: 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 `bearer_token` argument from the `BEARER_TOKEN` environment variable if it is not provided. + This automatically infers the `api_key` argument from the `BRAINBASE_API_KEY` environment variable if it is not provided. """ - if bearer_token is None: - bearer_token = os.environ.get("BEARER_TOKEN") - if bearer_token is None: + if api_key is None: + api_key = os.environ.get("BRAINBASE_API_KEY") + if api_key is None: raise BrainbaseError( - "The bearer_token client option must be set either by passing bearer_token to the client or by setting the BEARER_TOKEN environment variable" + "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" ) - self.bearer_token = bearer_token + self.api_key = api_key if base_url is None: base_url = os.environ.get("BRAINBASE_BASE_URL") @@ -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]: @@ -125,7 +131,7 @@ def default_headers(self) -> dict[str, str | Omit]: def copy( self, *, - bearer_token: str | None = None, + api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.Client | None = None, @@ -159,7 +165,7 @@ def copy( http_client = http_client or self._client return self.__class__( - bearer_token=bearer_token or self.bearer_token, + api_key=api_key or self.api_key, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, @@ -213,12 +219,12 @@ class AsyncBrainbase(AsyncAPIClient): with_streaming_response: AsyncBrainbaseWithStreamedResponse # client options - bearer_token: str + api_key: str def __init__( self, *, - bearer_token: str | None = None, + api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: Union[float, Timeout, None, NotGiven] = NOT_GIVEN, max_retries: int = DEFAULT_MAX_RETRIES, @@ -240,15 +246,15 @@ def __init__( ) -> None: """Construct a new async brainbase client instance. - This automatically infers the `bearer_token` argument from the `BEARER_TOKEN` environment variable if it is not provided. + This automatically infers the `api_key` argument from the `BRAINBASE_API_KEY` environment variable if it is not provided. """ - if bearer_token is None: - bearer_token = os.environ.get("BEARER_TOKEN") - if bearer_token is None: + if api_key is None: + api_key = os.environ.get("BRAINBASE_API_KEY") + if api_key is None: raise BrainbaseError( - "The bearer_token client option must be set either by passing bearer_token to the client or by setting the BEARER_TOKEN environment variable" + "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" ) - self.bearer_token = bearer_token + self.api_key = api_key if base_url is None: base_url = os.environ.get("BRAINBASE_BASE_URL") @@ -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]: @@ -287,7 +299,7 @@ def default_headers(self) -> dict[str, str | Omit]: def copy( self, *, - bearer_token: str | None = None, + api_key: str | None = None, base_url: str | httpx.URL | None = None, timeout: float | Timeout | None | NotGiven = NOT_GIVEN, http_client: httpx.AsyncClient | None = None, @@ -321,7 +333,7 @@ def copy( http_client = http_client or self._client return self.__class__( - bearer_token=bearer_token or self.bearer_token, + api_key=api_key or self.api_key, base_url=base_url or self.base_url, timeout=self.timeout if isinstance(timeout, NotGiven) else timeout, http_client=http_client, diff --git a/tests/conftest.py b/tests/conftest.py index 9a8b7c7c..8e89d982 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") -bearer_token = "My Bearer Token" +api_key = "My API Key" @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, bearer_token=bearer_token, _strict_response_validation=strict) as client: + with Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: yield client @@ -47,7 +47,5 @@ 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, bearer_token=bearer_token, _strict_response_validation=strict - ) as client: + async with AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=strict) as client: yield client diff --git a/tests/test_client.py b/tests/test_client.py index fa4581c7..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, @@ -36,7 +36,7 @@ from .utils import update_env base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") -bearer_token = "My Bearer Token" +api_key = "My API Key" 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, bearer_token=bearer_token, _strict_response_validation=True) + client = Brainbase(base_url=base_url, api_key=api_key, _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(bearer_token="another My Bearer Token") - assert copied.bearer_token == "another My Bearer Token" - assert self.client.bearer_token == "My Bearer Token" + 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" def test_copy_default_options(self) -> None: # options that have a default are overridden correctly @@ -106,10 +106,7 @@ def test_copy_default_options(self) -> None: def test_copy_default_headers(self) -> None: client = Brainbase( - base_url=base_url, - bearer_token=bearer_token, - _strict_response_validation=True, - default_headers={"X-Foo": "bar"}, + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) assert client.default_headers["X-Foo"] == "bar" @@ -143,7 +140,7 @@ def test_copy_default_headers(self) -> None: def test_copy_default_query(self) -> None: client = Brainbase( - base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, default_query={"foo": "bar"} + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" @@ -268,7 +265,7 @@ def test_request_timeout(self) -> None: def test_client_timeout_option(self) -> None: client = Brainbase( - base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, timeout=httpx.Timeout(0) + base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -279,7 +276,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, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -289,7 +286,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, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -299,7 +296,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, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -311,17 +308,14 @@ async def test_invalid_http_client(self) -> None: async with httpx.AsyncClient() as http_client: Brainbase( base_url=base_url, - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client), ) def test_default_headers_option(self) -> None: client = Brainbase( - base_url=base_url, - bearer_token=bearer_token, - _strict_response_validation=True, - default_headers={"X-Foo": "bar"}, + base_url=base_url, api_key=api_key, _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" @@ -329,7 +323,7 @@ def test_default_headers_option(self) -> None: client2 = Brainbase( base_url=base_url, - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, default_headers={ "X-Foo": "stainless", @@ -340,12 +334,19 @@ 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, - bearer_token=bearer_token, - _strict_response_validation=True, - default_query={"query_param": "bar"}, + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) @@ -545,9 +546,7 @@ class Model(BaseModel): assert response.foo == 2 def test_base_url_setter(self) -> None: - client = Brainbase( - base_url="https://example.com/from_init", bearer_token=bearer_token, _strict_response_validation=True - ) + client = Brainbase(base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True) assert client.base_url == "https://example.com/from_init/" client.base_url = "https://example.com/from_setter" # type: ignore[assignment] @@ -556,20 +555,16 @@ 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(bearer_token=bearer_token, _strict_response_validation=True) + client = Brainbase(api_key=api_key, _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/", - bearer_token=bearer_token, - _strict_response_validation=True, - ), - Brainbase( - base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(), ), @@ -589,14 +584,10 @@ 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/", - bearer_token=bearer_token, - _strict_response_validation=True, - ), - Brainbase( - base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(), ), @@ -616,14 +607,10 @@ 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/", - bearer_token=bearer_token, - _strict_response_validation=True, - ), - Brainbase( - base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=httpx.Client(), ), @@ -641,7 +628,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, bearer_token=bearer_token, _strict_response_validation=True) + client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) assert not client.is_closed() copied = client.copy() @@ -652,7 +639,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, bearer_token=bearer_token, _strict_response_validation=True) + client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) with client as c2: assert c2 is client assert not c2.is_closed() @@ -673,12 +660,7 @@ 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, - bearer_token=bearer_token, - _strict_response_validation=True, - max_retries=cast(Any, None), - ) + Brainbase(base_url=base_url, api_key=api_key, _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: @@ -687,12 +669,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, bearer_token=bearer_token, _strict_response_validation=True) + strict_client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): strict_client.get("/foo", cast_to=Model) - client = Brainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=False) + client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=False) response = client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] @@ -720,7 +702,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, bearer_token=bearer_token, _strict_response_validation=True) + client = Brainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) @@ -830,7 +812,7 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: class TestAsyncBrainbase: - client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) @pytest.mark.respx(base_url=base_url) @pytest.mark.asyncio @@ -858,9 +840,9 @@ def test_copy(self) -> None: copied = self.client.copy() assert id(copied) != id(self.client) - 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" + 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" def test_copy_default_options(self) -> None: # options that have a default are overridden correctly @@ -880,10 +862,7 @@ def test_copy_default_options(self) -> None: def test_copy_default_headers(self) -> None: client = AsyncBrainbase( - base_url=base_url, - bearer_token=bearer_token, - _strict_response_validation=True, - default_headers={"X-Foo": "bar"}, + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_headers={"X-Foo": "bar"} ) assert client.default_headers["X-Foo"] == "bar" @@ -917,7 +896,7 @@ def test_copy_default_headers(self) -> None: def test_copy_default_query(self) -> None: client = AsyncBrainbase( - base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, default_query={"foo": "bar"} + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"foo": "bar"} ) assert _get_params(client)["foo"] == "bar" @@ -1042,7 +1021,7 @@ async def test_request_timeout(self) -> None: async def test_client_timeout_option(self) -> None: client = AsyncBrainbase( - base_url=base_url, bearer_token=bearer_token, _strict_response_validation=True, timeout=httpx.Timeout(0) + base_url=base_url, api_key=api_key, _strict_response_validation=True, timeout=httpx.Timeout(0) ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1053,7 +1032,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, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1063,7 +1042,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, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1073,7 +1052,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, bearer_token=bearer_token, _strict_response_validation=True, http_client=http_client + base_url=base_url, api_key=api_key, _strict_response_validation=True, http_client=http_client ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) @@ -1085,17 +1064,14 @@ def test_invalid_http_client(self) -> None: with httpx.Client() as http_client: AsyncBrainbase( base_url=base_url, - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=cast(Any, http_client), ) def test_default_headers_option(self) -> None: client = AsyncBrainbase( - base_url=base_url, - bearer_token=bearer_token, - _strict_response_validation=True, - default_headers={"X-Foo": "bar"}, + base_url=base_url, api_key=api_key, _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" @@ -1103,7 +1079,7 @@ def test_default_headers_option(self) -> None: client2 = AsyncBrainbase( base_url=base_url, - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, default_headers={ "X-Foo": "stainless", @@ -1114,12 +1090,19 @@ 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, - bearer_token=bearer_token, - _strict_response_validation=True, - default_query={"query_param": "bar"}, + base_url=base_url, api_key=api_key, _strict_response_validation=True, default_query={"query_param": "bar"} ) request = client._build_request(FinalRequestOptions(method="get", url="/foo")) url = httpx.URL(request.url) @@ -1320,7 +1303,7 @@ class Model(BaseModel): def test_base_url_setter(self) -> None: client = AsyncBrainbase( - base_url="https://example.com/from_init", bearer_token=bearer_token, _strict_response_validation=True + base_url="https://example.com/from_init", api_key=api_key, _strict_response_validation=True ) assert client.base_url == "https://example.com/from_init/" @@ -1330,20 +1313,18 @@ 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(bearer_token=bearer_token, _strict_response_validation=True) + client = AsyncBrainbase(api_key=api_key, _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/", - bearer_token=bearer_token, - _strict_response_validation=True, + base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), AsyncBrainbase( base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), @@ -1364,13 +1345,11 @@ def test_base_url_trailing_slash(self, client: AsyncBrainbase) -> None: "client", [ AsyncBrainbase( - base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, - _strict_response_validation=True, + base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), AsyncBrainbase( base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), @@ -1391,13 +1370,11 @@ def test_base_url_no_trailing_slash(self, client: AsyncBrainbase) -> None: "client", [ AsyncBrainbase( - base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, - _strict_response_validation=True, + base_url="http://localhost:5000/custom/path/", api_key=api_key, _strict_response_validation=True ), AsyncBrainbase( base_url="http://localhost:5000/custom/path/", - bearer_token=bearer_token, + api_key=api_key, _strict_response_validation=True, http_client=httpx.AsyncClient(), ), @@ -1415,7 +1392,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, bearer_token=bearer_token, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) assert not client.is_closed() copied = client.copy() @@ -1427,7 +1404,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, bearer_token=bearer_token, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) async with client as c2: assert c2 is client assert not c2.is_closed() @@ -1450,10 +1427,7 @@ 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, - bearer_token=bearer_token, - _strict_response_validation=True, - max_retries=cast(Any, None), + base_url=base_url, api_key=api_key, _strict_response_validation=True, max_retries=cast(Any, None) ) @pytest.mark.respx(base_url=base_url) @@ -1464,12 +1438,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, bearer_token=bearer_token, _strict_response_validation=True) + strict_client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) with pytest.raises(APIResponseValidationError): await strict_client.get("/foo", cast_to=Model) - client = AsyncBrainbase(base_url=base_url, bearer_token=bearer_token, _strict_response_validation=False) + client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=False) response = await client.get("/foo", cast_to=Model) assert isinstance(response, str) # type: ignore[unreachable] @@ -1498,7 +1472,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, bearer_token=bearer_token, _strict_response_validation=True) + client = AsyncBrainbase(base_url=base_url, api_key=api_key, _strict_response_validation=True) headers = httpx.Headers({"retry-after": retry_after}) options = FinalRequestOptions(method="get", url="/foo", max_retries=3) From 2b9759cfca44e5e9987fbc7f0a9a7b5e9d822222 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:08:08 +0000 Subject: [PATCH 5/5] release: 0.1.0-alpha.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 27 +++++++++++++++++++++++++++ pyproject.toml | 2 +- src/brainbase/_version.py | 2 +- 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c4762802..ba6c3483 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1-alpha.0" + ".": "0.1.0-alpha.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..ea6e2b07 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog + +## 0.1.0-alpha.1 (2025-02-04) + +Full Changelog: [v0.0.1-alpha.0...v0.1.0-alpha.1](https://github.com/BrainbaseHQ/brainbase-python-sdk/compare/v0.0.1-alpha.0...v0.1.0-alpha.1) + +### Features + +* **api:** update via SDK Studio ([#10](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/10)) ([4fb75c8](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/4fb75c8c78c172cb0a80be304334803956968247)) +* **api:** update via SDK Studio ([#12](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/12)) ([a363549](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/a3635498129383f20cae75014ad9720e18cc7ec6)) +* **api:** update via SDK Studio ([#18](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/18)) ([5f5451c](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/5f5451cebcda05a40deef4104207be19e5f8e8ac)) +* **api:** update via SDK Studio ([#23](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/23)) ([b2bbdf6](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/b2bbdf640fa7b0b9163f0a7a6b8ab964cb2c1fa5)) +* **api:** update via SDK Studio ([#33](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/33)) ([9254242](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/9254242f08a8f3f0da2a3b101fd07776022487d4)) +* **api:** update via SDK Studio ([#35](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/35)) ([91c7c39](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/91c7c396731fc46c41a031b2235e0e9562acea8f)) +* **api:** update via SDK Studio ([#38](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/38)) ([bc32c04](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/bc32c04421def2b0a84a5def7f5a4bb08546d704)) +* **api:** update via SDK Studio ([#40](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/40)) ([801bbaa](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/801bbaaddaddba829cf554d8b0ee0bc4c229ee40)) +* **api:** update via SDK Studio ([#41](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/41)) ([fb611f9](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/fb611f97127b4b491884acf8ccd636ebea0e858c)) +* **api:** update via SDK Studio ([#8](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/8)) ([312b657](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/312b657cf73569a314b3c64ed83521ca2bb576a5)) + + +### Chores + +* go live ([#1](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/1)) ([db8a29c](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/db8a29c23e871872bcfc26b15bc7e4b27b0b08b3)) +* remove custom code ([e685c86](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/e685c866f3f2b482e1d899a475a5d140ca134938)) +* sync repo ([cce7924](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/cce79248b7058f58c4fe7d98ea36ed534403c7a7)) +* update SDK settings ([#3](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/3)) ([c5e3c22](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/c5e3c223ba6a7df56e290877e55c31e81c1d4b52)) +* update SDK settings ([#5](https://github.com/BrainbaseHQ/brainbase-python-sdk/issues/5)) ([1e74403](https://github.com/BrainbaseHQ/brainbase-python-sdk/commit/1e744032bc5800bb1b4f97a703cfdd1a7a7dd922)) diff --git a/pyproject.toml b/pyproject.toml index 52a90e3c..d439fa3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "brainbase-labs" -version = "0.0.1-alpha.0" +version = "0.1.0-alpha.1" description = "The official Python library for the brainbase API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/brainbase/_version.py b/src/brainbase/_version.py index 29916c66..0550757d 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__ = "0.0.1-alpha.0" # x-release-please-version +__version__ = "0.1.0-alpha.1" # x-release-please-version