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

each_item is applied recursively #1255

Closed
gsakkis opened this issue Feb 25, 2020 · 2 comments · Fixed by #1991
Closed

each_item is applied recursively #1255

gsakkis opened this issue Feb 25, 2020 · 2 comments · Fixed by #1991
Labels
Change Suggested alteration to pydantic, not a new feature nor a bug

Comments

@gsakkis
Copy link
Contributor

gsakkis commented Feb 25, 2020

Setting each_item=True to a validator of a nested collection is apparently called recursively for each singleton of the collection, instead of the items of the collection:

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

pydantic version: 1.4
pydantic compiled: True
python version: 3.7.1 (default, Dec 14 2018, 19:46:24)  [GCC 7.3.0]
platform: Linux-4.4.0-173-generic-i686-with-debian-stretch-sid
optional deps. installed: ['typing-extensions']
from pydantic import validator
from pydantic.dataclasses import dataclass
from typing import Sequence

@dataclass
class DemoModel:
    square_numbers: Sequence[int] = ()
    square_number_lists: Sequence[Sequence[int]] = ()

    @validator('square_numbers', each_item=True)
    def check_squares(cls, v):
        assert v ** 0.5 % 1 == 0, f'{v} is not a square number'
        return v

    @validator('square_number_lists', each_item=True)
    def check_square_lists(cls, v):
        assert isinstance(v, Sequence), type(v)
        return v

print(DemoModel(square_numbers=[1, 4, 9]))
print(DemoModel(square_number_lists=[[1, 4, 9], [16, 25]]))
DemoModel(square_numbers=[1, 4, 9], square_number_lists=())
Traceback (most recent call last):
  File "foo.py", line 22, in <module>
    print(DemoModel(square_number_lists=[[1, 4, 9], [16, 25]]))
  File "<string>", line 4, in __init__
  File "pydantic/dataclasses.py", line 83, in pydantic.dataclasses._process_class._pydantic_post_init
    # Raise because not adding these methods would break the "frozen-ness"
pydantic.error_wrappers.ValidationError: 5 validation errors for DemoModel
square_number_lists -> 0 -> 0
  <class 'int'> (type=assertion_error)
square_number_lists -> 0 -> 1
  <class 'int'> (type=assertion_error)
square_number_lists -> 0 -> 2
  <class 'int'> (type=assertion_error)
square_number_lists -> 1 -> 0
  <class 'int'> (type=assertion_error)
square_number_lists -> 1 -> 1
  <class 'int'> (type=assertion_error)
@gsakkis gsakkis added the bug V1 Bug related to Pydantic V1.X label Feb 25, 2020
@samuelcolvin samuelcolvin added Change Suggested alteration to pydantic, not a new feature nor a bug and removed bug V1 Bug related to Pydantic V1.X labels Feb 28, 2020
@samuelcolvin
Copy link
Member

humm, I guess I think this would be very hard to change and might be wanted, you'd be best to skip each_item=True and do the validation on the whole object.

If that doesn't work for you, what would you propose?

@gsakkis
Copy link
Contributor Author

gsakkis commented Feb 28, 2020

At the very least the documentation should mention the current behavior, it's surely not expected. If backwards compatibility can be broken here, my suggestion would be to make each_item flat and add a new parameter, say flatten, with the current recursive behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Change Suggested alteration to pydantic, not a new feature nor a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants