Skip to content

release: 4.1.0#83

Closed
stainless-app[bot] wants to merge 120 commits intomainfrom
release-please--branches--main--changes--next
Closed

release: 4.1.0#83
stainless-app[bot] wants to merge 120 commits intomainfrom
release-please--branches--main--changes--next

Conversation

@stainless-app
Copy link
Contributor

@stainless-app stainless-app bot commented Mar 7, 2026

Automated Release PR

4.1.0 (2026-03-07)

Full Changelog: v4.0.0...v4.1.0

Features

  • api: update via SDK Studio (#61) (9c0c551)
  • clean up environment call outs (696f18b)
  • client: add custom JSON encoder for extended type support (87eaded)
  • client: add follow_redirects request option (6eb41c9)
  • client: add support for aiohttp (6f6ddd9)
  • client: add support for binary request streaming (41c399b)
  • client: allow passing NotGiven for body (#67) (3ad7f25)
  • client: send X-Stainless-Read-Timeout header (#63) (a594c75)
  • client: support file upload requests (fde965a)
  • improve future compat with pydantic v3 (bccbddf)
  • types: replace List[str] with SequenceNotStr in params (0578887)

Bug Fixes

  • asyncify on non-asyncio runtimes (#66) (ca310cd)
  • avoid newer type syntax (db10820)
  • ci: correct conditional (66eb0ef)
  • ci: ensure pip is always available (#78) (d3d295a)
  • ci: release-doctor — report correct token name (65cdccf)
  • ci: remove publishing patch (#79) (493f504)
  • client: close streams without requiring full consumption (e783145)
  • client: correctly parse binary response | stream (3924997)
  • client: don't send Content-Type header on GET requests (6bcbc4e)
  • client: mark some request bodies as optional (3ad7f25)
  • compat with Python 3.14 (f7d6103)
  • compat: update signatures of model_dump and model_dump_json for Pydantic v1 (898ca7b)
  • ensure streams are always closed (f89af68)
  • package: support direct resource imports (ad2d130)
  • parsing: correctly handle nested discriminated unions (cd511d2)
  • parsing: ignore empty metadata (bdd8ead)
  • parsing: parse extra field types (470d8a8)
  • perf: optimize some hot paths (7cc4937)
  • perf: skip traversing types for NotGiven values (38509ba)
  • pydantic v1: more robust ModelField.annotation check (3dc3480)
  • tests: fix: tests which call HTTP endpoints directly with the example parameters (539215f)
  • types: allow pyright to infer TypedDict types within SequenceNotStr (84b4806)
  • types: handle more discriminated union shapes (#77) (8b6dcf0)
  • use async_to_httpx_files in patch method (6bfd0c0)

Chores

  • add Python 3.14 classifier and testing (c172e9c)
  • broadly detect json family of content-type headers (febefbc)
  • bump httpx-aiohttp version to 0.1.9 (7aeb4c8)
  • ci: add timeout thresholds for CI jobs (d5cbcd0)
  • ci: change upload type (d7e4405)
  • ci: enable for pull requests (1ea6fbc)
  • ci: fix installation instructions (6291f4a)
  • ci: only run for pushes and fork pull requests (5d00f3e)
  • ci: only use depot for staging repos (19ee773)
  • ci: skip uploading artifacts on stainless-internal branches (d12f89a)
  • ci: upgrade actions/github-script (bdad5ed)
  • ci: upload sdks to package manager (598ec7e)
  • client: minor internal fixes (1e29d3b)
  • deps: mypy 1.18.1 has a regression, pin to 1.17 (fd940b6)
  • do not install brew dependencies in ./scripts/bootstrap by default (67c48f0)
  • docs: grammar improvements (540e711)
  • docs: remove reference to rye shell (ec32daa)
  • docs: update client docstring (#71) (b41543a)
  • docs: use environment variables for authentication in code snippets (ff7f0ef)
  • fix typos (#80) (c1576cc)
  • format all api.md files (034e708)
  • internal/tests: avoid race condition with implicit client cleanup (d3a5435)
  • internal: add --fix argument to lint script (0b1e68e)
  • internal: add missing files argument to base client (5547d1b)
  • internal: add request options to SSE classes (931a27e)
  • internal: add Sequence related utils (5f815ef)
  • internal: avoid errors for isinstance checks on proxies (5dc0949)
  • internal: base client updates (0ac179a)
  • internal: bump dependencies (5c298f6)
  • internal: bump pinned h11 dep (6cafe07)
  • internal: bump pyright version (81c2baf)
  • internal: bump rye to 0.44.0 (#76) (21a20b3)
  • internal: change ci workflow machines (656643d)
  • internal: codegen related update (0b4efb7)
  • internal: codegen related update (2f8fbc4)
  • internal: codegen related update (d6d5a1d)
  • internal: codegen related update (a145cee)
  • internal: codegen related update (#75) (db19786)
  • internal: detect missing future annotations with ruff (23b94ed)
  • internal: expand CI branch coverage (7fd1145)
  • internal: fix devcontainers setup (#68) (97b7254)
  • internal: fix lint error on Python 3.14 (1d9c80a)
  • internal: fix list file params (1b5e333)
  • internal: fix ruff target version (1437b86)
  • internal: fix type traversing dictionary params (#64) (1322c80)
  • internal: grammar fix (it's -> its) (8b1cdb7)
  • internal: import reformatting (8a3f6f0)
  • internal: make test_proxy_environment_variables more resilient (f79d30c)
  • internal: make test_proxy_environment_variables more resilient to env (08e33e4)
  • internal: minor type handling changes (#65) (7e69125)
  • internal: move mypy configurations to pyproject.toml file (f87b268)
  • internal: properly set pydantic_private (#69) (bc25b84)
  • internal: reduce CI branch coverage (2492996)
  • internal: refactor retries to not use recursion (055e329)
  • internal: remove extra empty newlines (#74) (3d90dff)
  • internal: remove mock server code (cb06a16)
  • internal: remove trailing character (#81) (4cfa80b)
  • internal: remove unused http client options forwarding (#72) (69a44e3)
  • internal: slight transform perf improvement (#82) (5498eaf)
  • internal: update actions/checkout version (54d6bd9)
  • internal: update comment in script (103820e)
  • internal: update conftest.py (83531b4)
  • internal: update models test (421a2b5)
  • internal: update pydantic dependency (5dd09a4)
  • internal: update pyright exclude list (f306088)
  • internal: update pyright settings (2d267e1)
  • package: drop Python 3.8 support (95ca18d)
  • package: mark python 3.13 as supported (06ad64f)
  • project: add settings file for vscode (6754b39)
  • readme: fix version rendering on pypi (b1e9e51)
  • readme: update badges (f3f214f)
  • speedup initial import (3b3f4e6)
  • tests: add tests for httpx client instantiation & proxies (5e172cd)
  • tests: run tests in parallel (497b381)
  • tests: simplify get_platform test (ef07d85)
  • tests: skip some failing tests on the latest python versions (39d037c)
  • types: change optional parameter type from NotGiven to Omit (14cb9a9)
  • update @stainless-api/prism-cli to v5.15.0 (d766a01)
  • update github action (d0f9d9e)
  • update lockfile (77726a0)
  • update mock server docs (1241c00)

Documentation

  • client: fix httpx.Timeout documentation reference (3341b85)
  • update URLs from stainlessapi.com to stainless.com (#70) (08062c4)

This pull request is managed by Stainless's GitHub App.

The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.

For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.

🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions

fix(client): mark some request bodies as optional
Comment on lines 441 to 442
headers = httpx.Headers(headers_dict)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idempotency header now skipped when key is falsy

The old guard was options.method.lower() != "get" and idempotency_header not in headers, which ensured the header was always sent for non-GET requests (generating a key on the fly if none was provided). The new guard is options.idempotency_key and idempotency_header not in headers, which will silently skip the header if idempotency_key happens to be an empty string "" rather than None.

In practice this is safe because idempotency_key is populated earlier in request() via self._idempotency_key(), which generates a UUID and is never an empty string. However, a caller that explicitly sets options.idempotency_key = "" to suppress the header would get different behaviour between the old and new code (old: header sent with an auto-generated value; new: header not sent). This is a subtle semantic difference worth documenting.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/brainbase/_base_client.py
Line: 441-442

Comment:
**Idempotency header now skipped when key is falsy**

The old guard was `options.method.lower() != "get" and idempotency_header not in headers`, which ensured the header was always sent for non-GET requests (generating a key on the fly if none was provided). The new guard is `options.idempotency_key and idempotency_header not in headers`, which will silently skip the header if `idempotency_key` happens to be an empty string `""` rather than `None`.

In practice this is safe because `idempotency_key` is populated earlier in `request()` via `self._idempotency_key()`, which generates a UUID and is never an empty string. However, a caller that explicitly sets `options.idempotency_key = ""` to suppress the header would get different behaviour between the old and new code (old: header sent with an auto-generated value; new: header not sent). This is a subtle semantic difference worth documenting.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 4 to 8

from .voice_deployment import VoiceDeployment as VoiceDeployment
from .voice_create_params import VoiceCreateParams as VoiceCreateParams
from .voice_list_response import VoiceListResponse as VoiceListResponse
from .voice_update_params import VoiceUpdateParams as VoiceUpdateParams
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking removal of VoiceCreateResponse, VoiceRetrieveResponse, VoiceUpdateResponse, and VoiceListResponseItem

All four names that were previously part of the public exports of this sub-package have been removed. Users who imported any of them directly will receive an ImportError after upgrading:

from brainbase.types.workers.deployments import VoiceCreateResponse   # ImportError in 4.1.0
from brainbase.types.workers.deployments import VoiceRetrieveResponse  # ImportError in 4.1.0
from brainbase.types.workers.deployments import VoiceUpdateResponse    # ImportError in 4.1.0
from brainbase.types.workers.deployments import VoiceListResponseItem  # ImportError in 4.1.0

The new equivalent is VoiceDeployment. The CHANGELOG does not explicitly call out these individual name removals, so the migration path may not be obvious to users. Consider adding re-export aliases (e.g. VoiceCreateResponse = VoiceDeployment) with a deprecation warning, or at minimum documenting the renames in the CHANGELOG migration notes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/brainbase/types/workers/deployments/__init__.py
Line: 4-8

Comment:
**Breaking removal of `VoiceCreateResponse`, `VoiceRetrieveResponse`, `VoiceUpdateResponse`, and `VoiceListResponseItem`**

All four names that were previously part of the public exports of this sub-package have been removed. Users who imported any of them directly will receive an `ImportError` after upgrading:

```python
from brainbase.types.workers.deployments import VoiceCreateResponse   # ImportError in 4.1.0
from brainbase.types.workers.deployments import VoiceRetrieveResponse  # ImportError in 4.1.0
from brainbase.types.workers.deployments import VoiceUpdateResponse    # ImportError in 4.1.0
from brainbase.types.workers.deployments import VoiceListResponseItem  # ImportError in 4.1.0
```

The new equivalent is `VoiceDeployment`. The CHANGELOG does not explicitly call out these individual name removals, so the migration path may not be obvious to users. Consider adding re-export aliases (e.g. `VoiceCreateResponse = VoiceDeployment`) with a deprecation warning, or at minimum documenting the renames in the CHANGELOG migration notes.

How can I resolve this? If you propose a fix, please make it concise.

@stainless-app
Copy link
Contributor Author

stainless-app bot commented Mar 7, 2026

🧪 Testing

To try out this version of the SDK:

pip install 'https://pkg.stainless.com/s/brainbase-python/d12f89a1c25c3d7c7fb8075e339d0b5eb9b08ac4/brainbase_labs-4.0.0-py3-none-any.whl'

Expires at: Mon, 06 Apr 2026 19:04:52 GMT
Updated at: Sat, 07 Mar 2026 19:04:52 GMT

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from dd993ea to 83c7404 Compare March 7, 2026 19:21
@Nauxie Nauxie closed this Mar 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant