Changelog
5.34.2
(fix): Accept an async_token callable on the async root client when OAuth client credentials are
configured with a token override. Previously only a synchronous token callable could be
supplied in token mode, so resolving the token blocked the event loop on every request. The
async client now exposes async_token: Optional[Callable[[], Awaitable[str]]], adds a
constructor overload for it, and forwards it to AsyncClientWrapper.
5.34.1
(chore): Bump bundled @fern-api/generator-cli to 0.10.3. When the hosted auto-version analysis of the
full SDK diff fails, generator-cli now retries chunk-by-chunk instead of silently applying a
PATCH bump; any remaining unavailable or incomplete analysis adds a “Version bump not verified”
notice to the SDK PR body and disables automerge.
5.34.0
(feat): XML-encoded (TwiML) models now carry inline documentation on their user-facing APIs: the
__init__ of text-bearing models and every fluent child method (say.break_(...)) document
each parameter from the API definition’s property descriptions, plus **extra_attributes.
5.33.2
(fix): Also emit the SPDX license in [tool.poetry] alongside the PEP 639 [project] license. Poetry 1.x
(including the poetry version pinned in the generated publish workflow) ignores the [project]
table, so since 5.32.0 packages built with it were published to PyPI without any license metadata.
5.33.1
(fix): Annotate generated WebSocket __iter__ / __aiter__ methods with typing.Iterator[<Socket>Response] /
typing.AsyncIterator[<Socket>Response] so type checkers infer iterated messages as the response union
(matching recv()) instead of bytes | <Response>.
5.33.0
(feat): Generate the shared WebhooksHelper from the API-wide api.settings.webhook-signature
setting in generators.yml (IR sdkConfig.webhookSignatureVerification). The helper is
emitted even when the API definition models no webhooks; webhook-specific signature
overrides still produce their own named helpers.
5.32.1
(fix): Stop emitting deprecated License :: PyPI classifiers alongside the PEP 639 [project] license
expression; modern setuptools rejects the combination. Inline metadata.license: "MIT" /
"Apache-2.0" now also writes the standard license text to LICENSE and declares it via
license-files = ["LICENSE"].
5.32.0
(feat): License metadata is now emitted in the [project] table of the generated pyproject.toml
following PEP 639: metadata.license: "MIT" / "Apache-2.0" produce license = "<SPDX>",
and metadata.license: { custom: "./LICENSE" } produces license-files = ["LICENSE"].
When the custom license file is recognized (Apache-2.0, MIT, BSD, GPL, MPL, ISC — same
heuristics as the Java generator), license = "<SPDX>" and the matching PyPI classifier are
emitted alongside license-files.
5.31.2
(fix): Fix multipart requests where a list<file> property declares a content-type. The generated
client now applies core.with_content_type to each file in the list instead of passing the
whole list to a single call, which failed mypy and would have sent the list as one part.
5.31.1
(chore): Bump bundled @fern-api/generator-cli to 0.10.1. Auto-versioned MAJOR/MINOR bumps no longer
produce a version-only changelog.md block when the AI analysis returns an empty changelog
entry; the PR description, version bump reason, or commit message body is used instead.
5.31.0
(feat): Object types carrying IR encoding.xml metadata (e.g. Twilio TwiML verbs imported from an OpenAPI
xml object) now generate a to_xml() method (and __str__) that serializes the model as an XML
element: properties marked as attributes become XML attributes, the text property becomes the element
body, and remaining properties are emitted as ordered child elements, honoring wire names,
namespaces/prefixes, wrapped lists and attribute list separators. A core/xml_utilities.py helper is
emitted only when the API contains XML-encoded types.
5.30.2
(fix): Fix the generated OIDC publish workflow in ci.yml so the pypi GitHub Environment URL
points to the configured package-name (https://pypi.org/p/<package-name>) instead of
github.event.repository.name.
5.30.1
(fix): The generated README only documents pagination (SyncPager, iter_pages()) when paginated
clients are actually generated, so the README and list() return types stay in sync.
5.30.0
(feat): Add a license_header custom config option that emits the configured text as a comment
at the top of every generated Python file, above the auto-generated notice.
5.29.4
(fix): Fix the generated tests/utils/test_http_client.py failing when retry_status_codes: recommended
is configured. The retry-status expectations in the test are now derived from the configured mode
instead of always asserting the legacy set (which includes 500, 501 and 599).
5.29.3
(fix): Cache Pydantic field alias metadata per model class instead of rebuilding the field name to alias maps on
every validation. The mode="before" validator now skips copying the input mapping when no key needs to be
rewritten, and parse_obj_as reuses the cached metadata instead of rescanning fields on each call. This
roughly halves the parsing cost of streaming responses, where the validator runs once per nested model per
event. As a result the validator can now hand the caller’s own dict to Pydantic rather than a copy of it;
Pydantic does not mutate or retain that mapping, so parsed models are unaffected.
5.29.2
(fix): Respect custom OAuth token headers and prefixes for client credentials authentication.
5.29.1
(fix): Fixed generated WireMock stubs for OAuth client credentials APIs whose token endpoint is
itself marked as authenticated: the token (and refresh) endpoint stub no longer requires
an Authorization header, since the token request is made to obtain the token and cannot
carry one yet.
5.29.0
(feat): Add stream_abstraction. With it enabled, streaming endpoints return a Stream[T]
(AsyncStream[T] for async clients) rather than a plain iterator, mirroring the TypeScript SDK’s
core.Stream. Iterating the stream still yields the parsed payloads, while with_metadata()
yields them wrapped in a StreamEvent that also exposes the server-sent event id, event and
retry fields — for event in client.completions.stream(...).with_metadata() — so reading an
event id no longer requires dropping down to with_raw_response. The request is still only
issued once the stream is iterated, the stream owns the underlying response and releases it when
exhausted, closed or exited as a (asynchronous) context manager, and the raw client’s data is
the same stream. AsyncStream is awaitable, so await client.completions.stream(...) and
async for chunk in client.completions.stream(...) both work. Defaults to false, so signatures
and snippets are unchanged until you opt in.
5.28.0
(feat): Add respect_optional_request_body. With it enabled, an endpoint whose request body the API does
not require defaults that body to the OMIT sentinel — batch_refund(request: Sequence[RefundRequest] = OMIT)
rather than request: Optional[Sequence[RefundRequest]] — so “not passed” stays distinct from an
explicit None, and a body left out means the request carries no content and no Content-Type.
Examples that supply no body render as client.batch_refund(). When the body inlines into keyword
arguments instead, leaving all of them out sends no body rather than an empty {}. Defaults to
false, so signatures and snippets are unchanged until you opt in.