Skip to content

Commit 4d82c97

Browse files
dmontaguhramezani
andauthored
Change the behavior of field_is_complex to be more similar to pydantic v1 (#31)
Co-authored-by: Hasan Ramezani <[email protected]>
1 parent 6d9c1a2 commit 4d82c97

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

pydantic_settings/sources.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import os
55
import warnings
66
from abc import ABC, abstractmethod
7+
from collections import deque
78
from dataclasses import is_dataclass
89
from pathlib import Path
9-
from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Tuple, Type, Union
10+
from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Sequence, Tuple, Type, Union
1011

1112
from pydantic import BaseModel
1213
from pydantic._internal._typing_extra import origin_is_union
@@ -53,10 +54,16 @@ def get_field_value(self, field: FieldInfo, field_name: str) -> Tuple[Any, str,
5354
pass
5455

5556
def field_is_complex(self, field: FieldInfo) -> bool:
56-
def _annotation_is_complex(annotation: type[Any] | None) -> bool:
57-
return lenient_issubclass(annotation, (BaseModel, list, set, frozenset, dict)) or is_dataclass(annotation)
57+
"""
58+
Checks whether a field is complex, in which case it will attempt to be parsed as JSON.
59+
60+
Args:
61+
field (FieldInfo): The field.
5862
59-
return _annotation_is_complex(field.annotation) or _annotation_is_complex(get_origin(field.annotation))
63+
Returns:
64+
bool: Whether the field is complex.
65+
"""
66+
return _annotation_is_complex(field.annotation)
6067

6168
def prepare_field_value(self, field_name: str, field: FieldInfo, value: Any, value_is_complex: bool) -> Any:
6269
"""
@@ -433,3 +440,22 @@ def find_case_path(dir_path: Path, file_name: str, case_sensitive: bool) -> Opti
433440
elif not case_sensitive and f.name.lower() == file_name.lower():
434441
return f
435442
return None
443+
444+
445+
def _annotation_is_complex(annotation: type[Any] | None) -> bool:
446+
origin = get_origin(annotation)
447+
return (
448+
_annotation_is_complex_inner(annotation)
449+
or _annotation_is_complex_inner(origin)
450+
or hasattr(origin, '__pydantic_core_schema__')
451+
or hasattr(origin, '__get_pydantic_core_schema__')
452+
)
453+
454+
455+
def _annotation_is_complex_inner(annotation: type[Any] | None) -> bool:
456+
if lenient_issubclass(annotation, str):
457+
return False
458+
459+
return lenient_issubclass(annotation, (BaseModel, Mapping, Sequence, tuple, set, frozenset, deque)) or is_dataclass(
460+
annotation
461+
)

tests/test_settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,10 @@ class B(BaseSettings):
622622
class Settings(BaseSettings):
623623
content: Union[A, B, datetime]
624624

625+
env.set('content', '{"a": "test"}')
626+
s = Settings()
627+
assert s.content == A(a='test')
628+
625629
env.set('content', '2020-07-05T00:00:00Z')
626630
s = Settings()
627631
assert s.content == datetime(2020, 7, 5, 0, 0, tzinfo=timezone.utc)

0 commit comments

Comments
 (0)