Skip to content

Commit

Permalink
Add Pydantic Json field support to settings management (#6250)
Browse files Browse the repository at this point in the history
  • Loading branch information
hramezani committed Jun 26, 2023
1 parent 51b4751 commit 19e2eb9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
1 change: 1 addition & 0 deletions changes/6250-hramezani.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add Pydantic `Json` field support to settings management.
6 changes: 5 additions & 1 deletion pydantic/env_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
from .config import BaseConfig, Extra
from .fields import ModelField
from .main import BaseModel
from .types import JsonWrapper
from .typing import StrPath, display_as_type, get_origin, is_union
from .utils import deep_update, path_type, sequence_like
from .utils import deep_update, lenient_issubclass, path_type, sequence_like

env_file_sentinel = str(object())

Expand Down Expand Up @@ -231,6 +232,9 @@ def field_is_complex(self, field: ModelField) -> Tuple[bool, bool]:
"""
Find out if a field is complex, and if so whether JSON errors should be ignored
"""
if lenient_issubclass(field.annotation, JsonWrapper):
return False, False

if field.is_complex():
allow_parse_failure = False
elif is_union(get_origin(field.type_)) and field.sub_fields and any(f.is_complex() for f in field.sub_fields):
Expand Down
34 changes: 33 additions & 1 deletion tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import pytest

from pydantic import BaseModel, BaseSettings, Field, HttpUrl, NoneStr, SecretStr, ValidationError, dataclasses
from pydantic import BaseModel, BaseSettings, Field, HttpUrl, Json, NoneStr, SecretStr, ValidationError, dataclasses
from pydantic.env_settings import (
EnvSettingsSource,
InitSettingsSource,
Expand Down Expand Up @@ -1278,3 +1278,35 @@ def parse_env_var(cls, field_name: str, raw_val: str):

s = Settings()
assert s.top == {1: 'apple', 2: 'banana'}


def test_env_json_field(env):
class Settings(BaseSettings):
x: Json

env.set('x', '{"foo": "bar"}')

s = Settings()
assert s.x == {'foo': 'bar'}

env.set('x', 'test')
with pytest.raises(ValidationError) as exc_info:
Settings()
assert exc_info.value.errors() == [{'loc': ('x',), 'msg': 'Invalid JSON', 'type': 'value_error.json'}]


def test_env_json_field_dict(env):
class Settings(BaseSettings):
x: Json[Dict[str, int]]

env.set('x', '{"foo": 1}')

s = Settings()
assert s.x == {'foo': 1}

env.set('x', '{"foo": "bar"}')
with pytest.raises(ValidationError) as exc_info:
Settings()
assert exc_info.value.errors() == [
{'loc': ('x', 'foo'), 'msg': 'value is not a valid integer', 'type': 'type_error.integer'}
]

0 comments on commit 19e2eb9

Please sign in to comment.