Pydantic Tagged Union Pattern¶
Demonstrates discriminated unions for type-safe configuration using Pydantic’s discriminator field
When you need to handle multiple connection types or configuration variants, use Pydantic tagged unions with a discriminator field. This pattern enables type-safe deserialization where the type field determines which specific subclass to instantiate, providing compile-time type checking and runtime validation for polymorphic configurations.
pydantic_tagged_union_pattern.py
1# -*- coding: utf-8 -*-
2
3"""
4In Python, we can use Pydantic to define a tagged union
5(also known as a discriminated union) using the `discriminator` field.
6This allows us to create a union type that can be used to represent
7different subtypes of a base type, where each subtype has its own specific fields.
8"""
9
10import typing as T
11from pydantic import BaseModel, Field
12
13
14class BaseConnection(BaseModel):
15 type: str = Field()
16
17
18class SqlalchemyConnection(BaseConnection):
19 type: T.Literal["sqlalchemy"] = Field(default="sqlalchemy")
20 create_engine_kwargs: dict[str, T.Any] = Field(default_factory=dict)
21
22
23class AwsConnection(BaseConnection):
24 type: T.Literal["aws"] = Field(default="aws")
25 boto_session_kwargs: dict[str, T.Any] = Field(default_factory=dict)
26
27
28class Config(BaseModel):
29 connection: T.Union[SqlalchemyConnection, AwsConnection] = Field(
30 discriminator="type"
31 )
32
33
34if __name__ == "__main__":
35 dct_sql = {"connection": {"type": "sqlalchemy", "create_engine_kwargs": {}}}
36 dct_aws = {"connection": {"type": "aws", "boto_session_kwargs": {}}}
37
38 config = Config(**dct_sql)
39 # config = Config(**dct_aws)
40
41 print(config)