Changelog
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.
5.27.1
(fix): Accept a plain string for the root client’s token parameter when OAuth client credentials
are configured with a token override. The constructor overload, implementation signature, and
docstring previously typed token as typing.Callable[[], str] only, even though the client
wrapper accepts typing.Union[str, typing.Callable[[], str]] at runtime and the generated
example passes a string literal, so type checkers rejected the documented usage.
5.27.0
(feat): Add an opt-in prefer_explicit_auth configuration option. When enabled (and the API composes
OAuth client-credentials with basic auth via auth: any), auth credentials passed
explicitly to the client constructor take precedence over environment-variable
defaults when selecting the auth scheme — e.g. explicitly provided basic auth
credentials win over OAuth client ID/secret environment variables. Disabled by
default, so existing generated output and runtime behavior are unchanged.
5.26.1
(fix): Fixed WireMock stubs for wire tests of APIs with auth: any combining Basic and
OAuth/Bearer schemes: stubs now accept either Authorization form instead of
requiring the exact Basic header the client may not send.
5.26.0
(feat): Add an encode_path_params config option (default false). When enabled, path parameter
values are percent-encoded when substituted into the request path, so a value containing /
or .. can no longer change which endpoint the request resolves to. The default false
preserves the existing (unencoded) behavior; TypeScript, Go, Java, and C# already encode path
params.
5.25.0
(feat): Add opt-in allow_user_agent_app_info config (camelCase alias allowUserAgentAppInfo).
When enabled, the generated client accepts an optional app_info
({"name": ..., "version"?: ..., "comment"?: ...}) constructor argument whose product
token is appended to the User-Agent header
({sdk}/{version} ... {product}/{product-version} ({comment})), following RFC 9110.
Disabled by default, so existing generated output is unchanged. It composes with
include_platform_headers, the user-agent template config, and the default
{package}/{version} value, and survives the runtime_version path. Caller-supplied
values are sanitized (name/version token-encoded, comment delimiters and control
characters escaped), and it is still overridable by an explicit User-Agent header and
suppressed by omit_fern_headers.