Skip to content

release: 4.1.0#62

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

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

Conversation

@stainless-app
Copy link
Contributor

@stainless-app stainless-app bot commented Feb 4, 2025

Automated Release PR

4.1.0 (2026-02-25)

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: 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


Note

High Risk
Touches core HTTP client request/response handling (serialization, retries, streaming, headers, new transport), which can change runtime behavior across all API calls. Also raises the minimum supported Python version and updates dependency/tooling pins, potentially impacting downstream environments.

Overview
Bumps the SDK to 4.1.0 and updates the generated API/docs, including changing workers.deployments.voice methods to return VoiceDeployment and refreshing changelog/manifest metadata.

Extends the client with an optional aiohttp-backed async HTTP client (DefaultAioHttpClient + aiohttp extra), raw/binary request body support via a new content parameter, and a custom JSON serializer (openapi_dumps) to handle additional types (e.g., datetime, pydantic.BaseModel). Streaming/SSE handling is hardened to ensure responses are closed even if not fully consumed.

Reworks request plumbing: adds follow_redirects per-request option, sends X-Stainless-Read-Timeout, avoids sending Content-Type on GETs, improves pagination to support JSON-body pagination, refactors retry logic to a loop with stable idempotency keys, and broadens JSON content-type detection.

Modernizes project/infra: drops Python 3.8 (now >=3.9), updates typing/tooling configs (moves mypy settings into pyproject.toml, updates ruff/pyright, runs pytest in parallel), refreshes lockfiles, and updates CI/devcontainer setup (Rye 0.44.0, new build job + artifact upload, job timeouts, branch filters, and optional Homebrew installs).

Written by Cursor Bugbot for commit 7039a1a. This will update automatically on new commits. Configure here.

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 6c2b6c5 to a594c75 Compare February 6, 2025 03:11
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 85e4dfe to 1322c80 Compare February 7, 2025 03:11
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 2bb4c49 to 7e69125 Compare February 7, 2025 03:14
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 7cdfb0a to ca310cd Compare February 14, 2025 03:14
fix(client): mark some request bodies as optional
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 3bdb00f to 3ad7f25 Compare February 21, 2025 04:03
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 1be6ce9 to 97b7254 Compare February 22, 2025 03:24
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 35a4088 to bc25b84 Compare February 26, 2025 03:11
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from ef0d130 to 08062c4 Compare February 28, 2025 03:03
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 9257acd to b41543a Compare February 28, 2025 03:05
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from df1d708 to 69a44e3 Compare March 4, 2025 03:29
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from cf36bae to bba1424 Compare March 11, 2025 11:58
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from e0b03f0 to 3d90dff Compare March 14, 2025 08:46
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 84a0625 to db19786 Compare March 15, 2025 07:00
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next branch from 359644d to 21a20b3 Compare March 15, 2025 07:03
line-length = 120
output-format = "grouped"
target-version = "py37"
target-version = "py38"
Copy link

Choose a reason for hiding this comment

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

Ruff target-version inconsistent with minimum Python version

Low Severity

The ruff target-version was changed from "py37" to "py38", but the project's requires-python was updated to ">= 3.9" and pyright's pythonVersion is set to "3.9". The ruff target should be "py39" to match. This inconsistency means ruff applies formatting/linting rules for Python 3.8 compatibility even though the project no longer supports it — for example, the FA102 rule may unnecessarily flag missing from __future__ import annotations in files that only need 3.9+ support.

Additional Locations (2)

Fix in Cursor Fix in Web

request = self._build_request(options, retries_taken=retries_taken)
self._prepare_request(request)
retries_taken = 0
for retries_taken in range(max_retries + 1):
Copy link

Choose a reason for hiding this comment

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

Iterative retry loop breaks math.inf unlimited retries

Medium Severity

The refactored retry logic uses range(max_retries + 1) which crashes with TypeError when max_retries is math.inf, since range() requires integer arguments. The old recursive approach handled this correctly because it only compared remaining_retries > 0. The error message in __init__ still explicitly recommends math.inf for unlimited retries, making this a documented-but-broken feature.

Additional Locations (2)

Fix in Cursor Fix in Web

return o.isoformat()
if isinstance(o, pydantic.BaseModel):
return model_dump(o, exclude_unset=True, mode="json", by_alias=True)
return super().default(o)
Copy link

Choose a reason for hiding this comment

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

Custom JSON encoder handles datetime but not date

Low Severity

The new _CustomEncoder handles datetime serialization via isinstance(o, datetime) but does not handle date objects. Since datetime is a subclass of date (not the other way around), pure date values will fall through to super().default(o) and raise a TypeError. Given the stated goal of "extended type support," omitting date while including datetime appears to be an oversight. If any date objects survive the transform pipeline and reach openapi_dumps, serialization will fail.

Fix in Cursor Fix in Web

# mypy can't narrow the type
return extras["cls"] # type: ignore[no-any-return]

return None
Copy link

Choose a reason for hiding this comment

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

Missing "definitions" schema handling in extra fields type resolution

Low Severity

_get_extra_fields_type doesn't handle the "definitions" schema wrapper type, unlike _extract_field_schema_pv2 which was updated in the same PR to unwrap it. For models with forward references or self-referential types (whose core schema is wrapped in "definitions"), the function returns None instead of the actual extras type, causing extra fields to skip type-aware construction.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

kwargs["files"] = files
else:
headers.pop("Content-Type", None)
kwargs.pop("data", None)
Copy link

Choose a reason for hiding this comment

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

JSON body silently dropped when files present

Low Severity

When a request includes both json_data (body) and files but the Content-Type header is not multipart/form-data, the new body-handling logic silently drops json_data. The elif not files guard on line 558 skips setting content from json_data when files are present, and no other path forwards the JSON data to httpx. The old code passed both json and files to httpx (which would error on the conflict), making the issue explicit rather than a silent data loss.

Fix in Cursor Fix in Web

@Nauxie
Copy link
Member

Nauxie commented Mar 6, 2026

Closing stale PR

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