Add Combine StrEnum With Pydantic For Union Type as a Python TIL

This commit is contained in:
jbranchaud
2026-08-10 17:08:27 -05:00
parent 38b822fb5c
commit 2bb402ad40
2 changed files with 56 additions and 1 deletions
+2 -1
View File
@@ -10,7 +10,7 @@ working across different projects via [VisualMode](https://www.visualmode.dev/).
For a steady stream of TILs, [sign up for my newsletter](https://visualmode.kit.com/newsletter).
_1857 TILs and counting..._
_1858 TILs and counting..._
See some of the other learning resources I work on:
@@ -1087,6 +1087,7 @@ If you've learned something here, support my efforts writing daily TILs by
- [Break Debugger On First Line Of Program](python/break-debugger-on-first-line-of-program.md)
- [Check If Package Is Installed With Pip](python/check-if-package-is-installed-with-pip.md)
- [Check Precondition Before Click Arg Parsing](python/check-precondition-before-click-arg-parsing.md)
- [Combine StrEnum With Pydantic For Union Type](python/combine-strenum-with-pydantic-for-union-type.md)
- [Commit Writes From Executed SQLite Statements](python/commit-writes-from-executed-sqlite-statements.md)
- [Configure Other Attributes Of Dataclass Field](python/configure-other-attributes-of-dataclass-field.md)
- [Control Passing Of Time In Tests](python/control-passing-of-time-in-tests.md)
@@ -0,0 +1,54 @@
# Combine StrEnum With Pydantic For Union Type
I want a [Pydantic](https://pydantic.dev/docs/validation/latest/get-started/)
model that I can use to verify the shape and values of user-provided config
file. Let's say, for now, the only config value supported by the file is
`storage_format` and it can be one of three values (`json`, `sqlite`,
`inmemory`).
I can start with a
[`StrEnum`](https://docs.python.org/3/library/enum.html#enum.StrEnum) class to
represent the set of valid values for the storage format field.
```python
from enum import StrEnum
from typing import Literal
class StorageFormat(StrEnum):
SQLITE = "sqlite"
JSON = "json"
INMEMORY = "inmemory"
@classmethod
def default(cls) -> Literal[StorageFormat.SQLITE]:
return cls.SQLITE
```
Notice I've also provided a class method called `default` for serving up a
fallback default value.
Here is the corresponding Pydantic `CliConfig` model which uses the
`StorageFormat` string enum class as the type signature for its `storage_format`
field.
```python
from pydantic import BaseModel
class CliConfig(BaseModel):
storage_format: StorageFormat = StorageFormat.default()
```
For `storage_format` to be valid in the context of `CliConfig`, it must be one
of the values defined by that `StrEnum`. I get auto-complete, I get type
checking, and I can validate a config file I've just read into memory (in this
case, using
[`model_validate_json`](https://pydantic.dev/docs/validation/dev/api/pydantic/base_model/#pydantic.BaseModel.model_validate_json)).
```python
def _read_config(self) -> CliConfig:
if self.exists():
raw_json = self.config_file.read_text()
return CliConfig.model_validate_json(raw_json)
return CliConfig()
```