Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/sdk-types-defer-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type: minor
packages: [ sdk-types ]
changelog: |-
Importing `turnkey_sdk_types` is much faster and uses much less memory: each generated model now builds its validator and serializer the first time it's used, instead of all of them at import (Pydantic `defer_build`). On Pydantic 2.14, import takes about 0.2s instead of 2-3s, and memory after import drops from about 276MB to about 50MB.

This is only enabled on Pydantic 2.5 and later. Behavior is unchanged, with a few things to know:
- The first use of each model takes slightly longer, usually a few milliseconds. Activity response models take about 20ms.
- A process that uses most of the activity response types builds a separate copy of the activity schema for each, so its peak memory can be higher than before (about 520MB with every model built, compared with about 280MB).
- On Pydantic 2.10 and earlier, `Model.model_fields[...].annotation` can show an unresolved `ForwardRef` until the model is first used. Field names, aliases, and defaults are unaffected. Call `Model.model_rebuild()` first if you inspect annotations right after import.
- A model that can't be built would now fail on first use instead of at import. Every current model builds.
7 changes: 6 additions & 1 deletion codegen/types/generate_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,15 @@ def main():
output += "from __future__ import annotations\n"
output += "from typing import Any, Dict, List, Optional\n"
output += "from enum import Enum\n"
output += "from pydantic import VERSION as _PYDANTIC_VERSION\n"
output += "from pydantic import BaseModel, Field, ConfigDict\n\n"
output += (
"# Build models on first use, not at import. Needs Pydantic 2.5+.\n"
'_DEFER_BUILD = tuple(int(p) for p in _PYDANTIC_VERSION.split(".")[:2]) >= (2, 5)\n\n'
)
output += "\n# Base class with shared configuration\n"
output += "class TurnkeyBaseModel(BaseModel):\n"
output += " model_config = ConfigDict(populate_by_name=True)\n\n"
output += " model_config = ConfigDict(populate_by_name=True, defer_build=_DEFER_BUILD)\n\n"

# --- Base Types ---
output += "# --- Base Types from Swagger Definitions ---\n\n"
Expand Down
6 changes: 5 additions & 1 deletion packages/sdk-types/src/turnkey_sdk_types/generated/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
from __future__ import annotations
from typing import Any, Dict, List, Optional
from enum import Enum
from pydantic import VERSION as _PYDANTIC_VERSION
from pydantic import BaseModel, Field, ConfigDict

# Build models on first use, not at import. Needs Pydantic 2.5+.
_DEFER_BUILD = tuple(int(p) for p in _PYDANTIC_VERSION.split(".")[:2]) >= (2, 5)


# Base class with shared configuration
class TurnkeyBaseModel(BaseModel):
model_config = ConfigDict(populate_by_name=True)
model_config = ConfigDict(populate_by_name=True, defer_build=_DEFER_BUILD)


# --- Base Types from Swagger Definitions ---
Expand Down
Loading