feat(python): add forward-compatible model serialization

Draft
TH
5h ago
+1053-52

Why

Python SDKs need undeclared fields to survive nested JSON request and response serialization, and model helpers must serialize future enum values without a downstream base-model patch.

What changed

  • Add python.preserveUnknownFields (default false) to retain undeclared fields in generated models and error bodies. Explicitly typed additional properties still validate; the option deliberately permits extras on closed schemas.
  • Add python.modelSerializationMethods (default false) for to_dict and to_json helpers, including field aliases and Pydantic filtering options. Reserve the helper names only when enabled.
  • Give unrecognized string and integer enums explicit JSON serializers without warnings, while retaining the original objects in Python-mode dumps. This fix also applies when the new options are disabled.
  • Preserve nested JSON nulls without changing top-level omission, required-value validation, or optional JSON query parameters.
  • Add four echo-test variants covering every combination of the two options and dictionary/model inputs, sync/async requests, recursion, arrays, maps, aliases, nulls, unions, composed schemas, empty models, error responses, helper-name collisions, and separate input/output models. All four variants run in CI.
  • Align the generator test job with the existing patched PHP setup used by PHP jobs so dependency security checks can run on a supported patch release.

Configuration schema: https://github.com/speakeasy-api/sdk-gen-config/pull/136

Testing

  • 121 echo/runtime cases pass in all four combinations of the two options, including warning-free enum serialization and Python-mode object identity.
  • The enabled suite also passes on Pydantic 2.11.2, the minimum supported version.
  • Generated SDKs pass Pyright, mypy, Pylint and Python compilation.
  • Focused Python generator snapshots, template type-check, template/configuration unit tests pass.
  • Review SDK regeneration passes integrity validation; its only runtime source change is the base-model enum serializers and formatting.
  • git diff --check passes.

Public-safety check

  • This change contains no credentials, customer documents, private repository URLs, private filesystem paths, or unredacted private logs.
  • Title, body, comments, and commit messages name no customers or customer-derived identifiers, private paths or trackers, or workflow provenance, and are understandable without private context.
  • Generated fixtures and review SDK changes are public-safe.
  • I reviewed git diff --check.