Skip to content

Commit

Permalink
[1.10.x] Properly encode model and dataclass default for schema (#4781)
Browse files Browse the repository at this point in the history
* Properly encode model and dataclass default for schema

* Wrap type annotation in quotes

* Fix compatibility

* Add changes file

* Remove unnecessary import

Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>

* Add a blank line back

* Reorder conditions

As per suggestion in #4781 (comment).

Co-authored-by: Hasan Ramezani <hasan.r67@gmail.com>
  • Loading branch information
2 people authored and samuelcolvin committed Nov 29, 2022
1 parent 1ac1199 commit 8b7c568
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
1 change: 1 addition & 0 deletions changes/4781-Bobronium.md
@@ -0,0 +1 @@
Fix `schema` and `schema_json` on models where a model instance is a one of default values.
12 changes: 9 additions & 3 deletions pydantic/schema.py
@@ -1,6 +1,7 @@
import re
import warnings
from collections import defaultdict
from dataclasses import is_dataclass
from datetime import date, datetime, time, timedelta
from decimal import Decimal
from enum import Enum
Expand Down Expand Up @@ -931,16 +932,21 @@ def multitypes_literal_field_for_schema(values: Tuple[Any, ...], field: ModelFie


def encode_default(dft: Any) -> Any:
if isinstance(dft, Enum):
from .main import BaseModel

if isinstance(dft, BaseModel) or is_dataclass(dft):
dft = cast('dict[str, Any]', pydantic_encoder(dft))

if isinstance(dft, dict):
return {encode_default(k): encode_default(v) for k, v in dft.items()}
elif isinstance(dft, Enum):
return dft.value
elif isinstance(dft, (int, float, str)):
return dft
elif isinstance(dft, (list, tuple)):
t = dft.__class__
seq_args = (encode_default(v) for v in dft)
return t(*seq_args) if is_namedtuple(t) else t(seq_args)
elif isinstance(dft, dict):
return {encode_default(k): encode_default(v) for k, v in dft.items()}
elif dft is None:
return None
else:
Expand Down
32 changes: 32 additions & 0 deletions tests/test_schema.py
Expand Up @@ -1512,6 +1512,38 @@ class UserModel(BaseModel):
}


def test_model_default():
"""Make sure inner model types are encoded properly"""

class Inner(BaseModel):
a: Dict[Path, str] = {Path(): ''}

class Outer(BaseModel):
inner: Inner = Inner()

assert Outer.schema() == {
'definitions': {
'Inner': {
'properties': {
'a': {
'additionalProperties': {'type': 'string'},
'default': {'.': ''},
'title': 'A',
'type': 'object',
}
},
'title': 'Inner',
'type': 'object',
}
},
'properties': {
'inner': {'allOf': [{'$ref': '#/definitions/Inner'}], 'default': {'a': {'.': ''}}, 'title': 'Inner'}
},
'title': 'Outer',
'type': 'object',
}


@pytest.mark.parametrize(
'kwargs,type_,expected_extra',
[
Expand Down

0 comments on commit 8b7c568

Please sign in to comment.