Migration guide#
Migrating from Spectree v2 to v3#
Spectree v3 introduces a model-adapter layer. Pydantic remains the default backend, while msgspec and plain dataclasses are now supported through the same validation and OpenAPI generation contract.
Installation now requires a model extra#
Pydantic is no longer an unconditional dependency. Existing Pydantic users
should install the pydantic extra:
pip install "spectree[pydantic]"
To use msgspec instead:
pip install "spectree[msgspec]"
SpecTree continues to select Pydantic when no adapter is passed. A bare
pip install spectree is therefore intended for applications that supply their
own model adapter; it is not sufficient to construct the default SpecTree.
Select the model adapter explicitly#
Existing Pydantic applications can continue to rely on the default:
from spectree import SpecTree
spec = SpecTree("flask")
Applications using msgspec must pass its adapter:
from spectree import SpecTree, get_msgspec_model_adapter
spec = SpecTree("falcon", model_adapter=get_msgspec_model_adapter())
Custom adapters must implement the
ModelAdapter
protocol.
File models come from the active adapter#
The old top-level spectree.BaseFile type has been replaced by the active
adapter’s basefile contract. This lets each model backend expose the file type
it can validate:
from pydantic import BaseModel
from spectree import get_pydantic_model_adapter
model_adapter = get_pydantic_model_adapter()
class UploadForm(BaseModel):
file: model_adapter.basefile
Pass the same adapter to SpecTree when selecting it explicitly.
Hooks receive the active adapter#
The before and after hook signatures have a new final argument:
def before(request, response, validation_error, instance, model_adapter):
...
def after(request, response, validation_error, instance, model_adapter):
...
Update custom hooks that accepted exactly four arguments. The new argument provides adapter-specific validation errors, serialization, and schema behavior.
Spectree metadata models are no longer Pydantic models#
Spectree’s configuration and OpenAPI metadata classes now use adapter-backed
dataclasses rather than inheriting from pydantic.BaseModel. This affects code
that directly manipulates classes such as Configuration,
SecuritySchemeData, SecurityScheme, Server, Tag, or ExternalDocs.
Use
.to_dict()instead of Pydantic’s.model_dump().Plain construction still works for already-typed values.
When validating mappings, call
.model_validate()with the active adapter:
from spectree import get_pydantic_model_adapter
from spectree.models import SecuritySchemeData
model_adapter = get_pydantic_model_adapter()
scheme = SecuritySchemeData.model_validate(
{"type": "apiKey", "name": "X-API-Key", "in": "header"},
model_adapter=model_adapter,
)
Model names may change#
The default naming strategy now handles wrapped model types such as
Annotated[Item, ...] and list[Item]. This can change generated component
keys for applications that depended on the previous names.
Use naming_strategy and nested_naming_strategy on SpecTree when component
names are part of a published OpenAPI contract:
spec = SpecTree(
"flask",
naming_strategy=lambda model: model.__name__.lower(),
nested_naming_strategy=lambda _parent, child: child,
)
Validation errors are adapter-specific#
Validation exceptions and their serialized details now come from the active
model adapter. Code in custom hooks or plugins should use
model_adapter.validation_error and model_adapter.validation_errors(error)
instead of assuming a Pydantic ValidationError.
Starlette model responses have a new name#
The Pydantic-specific PydanticResponse factory has been replaced by
SpecTreeStarletteResponse, which serializes models through the active adapter.
Update Starlette handlers that return model instances:
# Spectree v2
from spectree.plugins.starlette_plugin import PydanticResponse
return PydanticResponse(model)
# Spectree v3, this works for both `pydantic` and `msgspec`
from spectree.plugins.starlette_plugin import SpecTreeStarletteResponse
return SpecTreeStarletteResponse(model)
Create SpecTreeStarletteResponse inside a route wrapped by spec.validate so
it can use that SpecTree instance’s model adapter automatically.
Upgrade checklist#
Install
spectree[pydantic]orspectree[msgspec].If using
msgspecor a custom adapter, pass it toSpecTree.Update hook functions to accept
model_adapter.Replace direct
spectree.BaseFileuse withmodel_adapter.basefile.Replace Pydantic-only operations on Spectree metadata classes.
If using Starlette, replace
PydanticResponsecalls withSpecTreeStarletteResponse.Compare the generated OpenAPI document, especially component names and serialized response schemas, before deploying.
Migrating from Spectree v1 to v2#
Spectree v2’s main breaking change is its complete migration to Pydantic v2.
Pydantic v1 models, including models imported through the pydantic.v1
compatibility namespace, are no longer supported.
Upgrade Python and Pydantic#
Spectree v2 requires Python 3.10 or newer and Pydantic 2.11 or newer:
pip install --upgrade "spectree>=2,<3"
If an application cannot migrate from Pydantic v1 yet, it should remain on Spectree 1.5:
pip install "spectree>=1.5,<2"
Follow the Pydantic migration guide for the complete set of Pydantic API and behavior changes.
Update Pydantic model APIs#
Move every model passed to Spectree to Pydantic v2’s BaseModel and update
deprecated Pydantic v1 APIs. Common replacements include:
Pydantic v1 |
Pydantic v2 |
|---|---|
|
|
|
|
|
|
|
|
Model configuration also uses model_config rather than an inner Config
class. For example:
from pydantic import BaseModel, ConfigDict
class Example(BaseModel):
model_config = ConfigDict(
json_schema_extra={"examples": [{"name": "example"}]}
)
name: str
Upgrade checklist#
Use Python 3.10 or newer.
Upgrade every request and response model to Pydantic v2; do not use
pydantic.v1compatibility models with Spectree v2.Replace deprecated model methods and
class Configdeclarations.Regenerate and compare the OpenAPI document.
Test request validation and response serialization before deploying.