Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pydantic 1.6 does not validate nested models when using a default_factory #1710

Closed
jlowin opened this issue Jul 11, 2020 · 7 comments · Fixed by #1712
Closed

Pydantic 1.6 does not validate nested models when using a default_factory #1710

jlowin opened this issue Jul 11, 2020 · 7 comments · Fixed by #1712
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@jlowin
Copy link

jlowin commented Jul 11, 2020

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.6
            pydantic compiled: True
                 install path: /usr/local/Caskroom/miniconda/base/envs/server/lib/python3.8/site-packages/pydantic
               python version: 3.8.3 (default, Jul  2 2020, 11:26:31)  [Clang 10.0.0 ]
                     platform: macOS-10.15.5-x86_64-i386-64bit
     optional deps. installed: ['typing-extensions']

I'm aware that validation does not apply to default values, but it appears that it is no longer applied to user-provided values that have a default factory value, either. If this is expected, I'm not sure if I saw it in the documentation or changelog.

from pydantic import BaseModel, Field
from typing import List

class Child(BaseModel):
    x: int

class Parent(BaseModel):
    children: List[Child] = Field(default_factory=list)


p = Parent(children=[{'x':1}, {'y':2}])

In Pydantic 1.5.1, an error is raised because the second child fails to validate (it is missing required value 'x')

In Pydantic 1.6, the Parent object is instantiated successfully and contains two dicts:

print(p)
# children=[{'x': 1}, {'y': 2}]

To avoid this and recover the expected behavior, validate_all must be set on the Parent class. However, since I'm providing the child value, I'm surprised that I had to ask for it to be validated.

@jlowin jlowin added the bug V1 Bug related to Pydantic V1.X label Jul 11, 2020
@jlowin jlowin changed the title Pydantic 1.6 does not resolve nested models when using a default_factory Pydantic 1.6 does not validate nested models when using a default_factory Jul 11, 2020
@samuelcolvin
Copy link
Member

This is definitely a bug, probably caused by the changes in #1691, specifically removing alwasy=True from list and set child fields.

That it turn was required to solve a problem that came up in #1627.

I see that this is urgent, but I'm flat out with work, will try to fix when I can. @PrettyWood do you have any bright ideas how to solve this without a different regeression?

@jlowin
Copy link
Author

jlowin commented Jul 11, 2020

Perhaps this is a consequence of the issue described in #1566 (and docs update #1592)? Does applying nested models implicitly set each_item=True with a default validator?

@jlowin
Copy link
Author

jlowin commented Jul 11, 2020

Ah sorry I see we just crossed messages. Ok, bittersweet glad to hear it :) I'll review the issues you linked and see what we can do in the meantime. Thank you!

@PrettyWood
Copy link
Member

PrettyWood commented Jul 11, 2020

Hmmm I see I'm sorry for that. This is definitely not expected! I'll have a look as soon as I can (probably on monday in the train).

PrettyWood added a commit to PrettyWood/pydantic that referenced this issue Jul 12, 2020
PR pydantic#1504 introduced a regression by bypassing `populate_validators()`,
which would skip the validation of children in nested models
with `default_factory`

closes pydantic#1710
@PrettyWood
Copy link
Member

Edit: the bug was way easier than I thought as it was only due to #1504. If any other has the same issue, do not hesitate to try out the fix to make sure there is no further regression.

samuelcolvin added a commit that referenced this issue Jul 15, 2020
…#1712)

* fix: validate nested models with `default_factory`

PR #1504 introduced a regression by bypassing `populate_validators()`,
which would skip the validation of children in nested models
with `default_factory`

closes #1710

* test: add example of nested models parsing with `default_factory`

closes #1717

* add testcase from #1722

* bodge for benchmarks

Co-authored-by: Samuel Colvin <s@muelcolvin.com>
@vladarefiev
Copy link

Hey everybody. I just picked up the same example from 1st comment, but without list:

from pydantic import BaseModel, Field
from typing import List

class Child(BaseModel):
    x: int

class Parent(BaseModel):
    child: Child


p = Parent(child={'y':2})
p.child
<class '__main__.Child'>

p.child.x
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: type object 'Child' has no attribute 'x'

p.child.y
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: type object 'Child' has no attribute 'y'

Is it expected behaviour or is it a bug?

@samuelcolvin
Copy link
Member

This bug relates to pydantic 1.6, please upgrade to the newest version of pydantic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V1 Bug related to Pydantic V1.X
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants