Skip to content

Commit

Permalink
Upgrade to pydantic 2.
Browse files Browse the repository at this point in the history
* Update dependencies
* Run `bump-pydantic` to migrate some code: https://docs.pydantic.dev/latest/migration/
* Adapt the toml parsing per pydantic/pydantic#2335
  • Loading branch information
caarmen committed Feb 3, 2024
1 parent 1ffbc4f commit 982648a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 21 deletions.
3 changes: 2 additions & 1 deletion requirements/prod.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
astral==3.2
pillow==10.2.0
pydantic==1.10.14
pydantic==2.6.0
pydantic-settings==2.1.0
python-dotenv==1.0.1
requests==2.31.0
52 changes: 32 additions & 20 deletions wspp/settings.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
import tomllib
from pathlib import Path
from typing import Any

from pydantic import BaseModel, BaseSettings, DirectoryPath, PositiveInt, confloat
from pydantic.env_settings import EnvSettingsSource
from pydantic.utils import deep_update
from pydantic import BaseModel, DirectoryPath, Field, PositiveInt
from pydantic.fields import FieldInfo
from pydantic_settings import (
BaseSettings,
EnvSettingsSource,
PydanticBaseSettingsSource,
)
from typing_extensions import Annotated

from wspp import slack, weatherstack


class WsppSettings(BaseModel):
latitude: confloat(ge=-90.0, le=90.0)
longitude: confloat(ge=-180.0, le=180.0)
latitude: Annotated[float, Field(ge=-90.0, le=90.0)]
longitude: Annotated[float, Field(ge=-180.0, le=180.0)]
profile_photos_dir: DirectoryPath = Path(__file__).parent.parent / "profile_photos"
polling_interval_s: PositiveInt = 7200


# https://github.com/pydantic/pydantic/issues/2335
class TOMLConfigSettingsSource(PydanticBaseSettingsSource):
def get_field_value(
self, field: FieldInfo, field_name: str
) -> tuple[Any, str, bool]:
return super().get_field_value(field, field_name)

def __call__(self) -> dict[str, Any]:
return tomllib.loads(Path("config.toml").read_text())


class Settings(BaseSettings):
wspp: WsppSettings
weatherstack: weatherstack.WeatherstackSettings
slack: list[slack.SlackSettings]

@classmethod
def read(cls):
# Pydantic doesn't have built-in support for toml files, so we
# have to load the toml file (and override with any env vars)
# ourselves.
# https://github.com/pydantic/pydantic/issues/2335
toml_settings = Settings(**tomllib.loads(Path("config.toml").read_text()))
env_data = EnvSettingsSource(
env_file=None,
env_file_encoding=None,
env_nested_delimiter="__",
)(toml_settings)
return Settings.parse_obj(obj=deep_update(toml_settings.dict(), env_data))


settings = Settings.read()
def settings_customise_sources(
cls, *_args, **_kwargs
) -> tuple[PydanticBaseSettingsSource, ...]:
return (
EnvSettingsSource(Settings, env_nested_delimiter="__"),
TOMLConfigSettingsSource(Settings),
)


settings = Settings()

0 comments on commit 982648a

Please sign in to comment.