Skip to content

Update Python version, update API specs, fix non-nullable defaults in generated models - #18

Merged
cretz merged 1 commit into
mainfrom
cretz/update-specs-strict-nullable
Sep 15, 2026
Merged

cretz merged 1 commit into
mainfrom
cretz/update-specs-strict-nullable

Conversation

@cretz

@cretz cretz commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

🚀 What

Backwards incompatible changes:

  • 💥 Minimum Python is now 3.11; 3.10 is EOL next month
  • 💥 Optional fields that the spec does not declare nullable no longer accept an explicit None and now raise ValidationError. Leaving a field unset is unchanged and still omits it from the request
  • 💥 Generated enums are now StrEnum, so members compare equal to their string value and format as the bare value rather than ClassName.MEMBER
  • 💥 The spec refresh renames and removes some generated models and client methods where the underlying API changed, including endpoints that moved to team-scoped paths

💻 How

  • preprocess now rewrites discriminator mapping values during the V1-suffix strip. They were left stale, which was harmless only because every previous discriminated union tagged on a const field. The new enum-tagged unions fall back to the mapping, so codegen silently dropped the discriminator (and crashed outright on 0.55)
  • Pass --strict-nullable so presence and nullability are modeled independently
  • postprocess wraps literal defaults on model-typed fields in a validating call. Codegen emits the schema default verbatim (Limit | None = 500), relying on validate_default=True to coerce at runtime, which pydantic deliberately treats as a static type error
  • clientgen narrows the error-body handler to ValidationError via contextlib.suppress, replacing a blind except Exception: pass. Required by ruff 0.16, which expanded its default rule set from 59 to 413 rules
  • Dropped ty: ignore directives that the newer ty no longer needs

🔬 Testing

  • uv run poe lint, typecheck, and test all clean
  • Repeat generate-api runs are byte-stable, and CI regenerates and fails on any diff
  • Verified request tri-state on a PATCH body: unset omits the field, explicit None sends null, a value sends the value
  • Verified pydantic deep-copies the rewritten model-instance defaults per instance, so the dict-shaped ones are not shared mutable state

@cretz
cretz requested review from rdingwall and a lite review from Copilot September 15, 2026 19:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Regenerate affected exports and correct non-nullable model annotations before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Refreshes API specifications and generated SDK clients, raises the minimum Python version to 3.11, and strengthens nullability/default handling.

Changes:

  • Regenerates management, inference, and model-config APIs.
  • Updates code generation, discriminator handling, and validation.
  • Updates dependencies, CI, and tests.
  • Corrects generated export ordering and non-nullable model annotations.
File summaries
File Summary
tests/test_e2e.py Updates E2E cleanup and handling.
tests/client/test_inference.py Adds strict nullability coverage.
scripts/e2e_test_bootstrap/__main__.py Adjusts import formatting.
scripts/apigen/specs/config.schema.json Refreshes model-config schemas.
scripts/apigen/preprocess.py Rewrites discriminator mappings.
scripts/apigen/postprocess.py Validates generated defaults.
scripts/apigen/clientgen.py Narrows error-body handling.
scripts/apigen/__main__.py Enables strict-nullable generation.
pyproject.toml Raises Python and tooling requirements.
baseten/client/modelconfig/_models.py Regenerates model-config models; nullable annotations require correction.
baseten/client/modelconfig/__init__.py Generated exports need regeneration for stable ordering.
baseten/client/managementapi/_client.py Regenerates the management client.
baseten/client/managementapi/__init__.py Generated exports need regeneration for stable ordering.
baseten/client/inferenceapi/_models.py Regenerates inference models.
baseten/client/inferenceapi/_client.py Regenerates the inference client.
baseten/client/inferenceapi/__init__.py Generated exports need regeneration for stable ordering.
baseten/client/_management.py Updates management context-manager typing.
baseten/client/_inference.py Updates inference context-manager typing.
.github/workflows/ci.yml Updates CI Python and generation checks.
Review details

Suppressed comments (1)

baseten/client/modelconfig/_models.py:645

  • The schema for BDNConfig.mounts is an array without a null branch, but this generated annotation widens it to list[BDNVolumeMount] | None, so BDNConfig(mounts=None) is accepted even though the spec rejects it. This leaves the strict-nullable contract broken for the newly added config fields (the same issue applies to access and hotload); preserve omission without widening the input type and add a regression test.
    mounts: Annotated[
        list[BDNVolumeMount] | None,
        Field(
            description="Existing BDN volumes to mount when the model starts.",
            title="Mounts",
        ),
    ] = None
  • Files reviewed: 19/22 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread baseten/client/inferenceapi/__init__.py
Comment thread baseten/client/managementapi/__init__.py
Comment thread baseten/client/modelconfig/__init__.py
@cretz
cretz merged commit d3d9c8c into main Sep 15, 2026
6 of 10 checks passed
@cretz
cretz deleted the cretz/update-specs-strict-nullable branch September 15, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Do not allow None for defaulted-but-null-not-allowed fields

3 participants