Pydantic: How to change Config for all subclasses?

Created on 4 Feb 2021  路  4Comments  路  Source: samuelcolvin/pydantic

Checks

  • [x] I added a descriptive title to this issue
  • [x] I have searched (google, github) for similar issues and couldn't find anything
  • [x] I have read and followed the docs and couldn't find an answer
  • [x] After submitting this, I commit to one of:

    • Look through open issues and helped at least one other person

    • Hit the "watch" button on this repo to receive notifications and I commit to help at least 2 people that ask questions in the future

    • Implement a Pull Request for a confirmed bug

Question

I would like to change Config for all subclasses of my parent class. Is it possible? And what is the correct way?

I can change Config in a class like this:

import pydantic

class MyBaseModel(pydantic.BaseModel):
    class Config:
        validate_assignment = True

But this Config is changed only for MyBaseModel, but not it's sublasses.


import pytest
def test_validate_assignment():
    class ValidateAssignmentModel(MyBaseModel):
        this_is_a_string: str

    model = ValidateAssignmentModel(this_is_a_string="hello")
    with pytest.raises(ValidationError):
        model.this_is_a_string = 1

# > Failed: DID NOT RAISE <class 'pydantic.error_wrappers.ValidationError'>

question

Most helpful comment

Hi @HynekBlahaDev
In your example, the issue does not come from the inheritance of Config, which is indeed inherited in ValidateAssignmentModel.

It comes from the fact 1 is parsed into string at the assignment cf. the note here: https://pydantic-docs.helpmanual.io/usage/models/

class ValidateAssignmentModel(MyBaseModel):
    this_is_a_string: str

model = ValidateAssignmentModel(this_is_a_string="hello")
model.this_is_a_string = 1
# does not raise any error because the int `1` is parsed in the string `"1"`
print(model.this_is_a_string)
# > "1"

This is a classic confusion with pydantic ! I have done it too ;)

All 4 comments

Hi @HynekBlahaDev
IMO the best solution is to do

from pydantic import BaseConfig

BaseConfig.validate_assignment = True

in your entrypoint.
All Config classes inherit from BaseConfig :)

Hi @HynekBlahaDev
In your example, the issue does not come from the inheritance of Config, which is indeed inherited in ValidateAssignmentModel.

It comes from the fact 1 is parsed into string at the assignment cf. the note here: https://pydantic-docs.helpmanual.io/usage/models/

class ValidateAssignmentModel(MyBaseModel):
    this_is_a_string: str

model = ValidateAssignmentModel(this_is_a_string="hello")
model.this_is_a_string = 1
# does not raise any error because the int `1` is parsed in the string `"1"`
print(model.this_is_a_string)
# > "1"

This is a classic confusion with pydantic ! I have done it too ;)

Thanks @rhuille
Indeed I read too fast. Your solution works but the type coercion is done as expected
If you don't want that, see https://pydantic-docs.helpmanual.io/usage/types/#strict-types

Hi @rhuille
You are correct! It behaves the same way even when I change the Config directly on the subclass.

def test_validate_assignment():
    class ValidateAssignmentModel(BigQueryModel):
        this_is_a_string: str

        class Config:
            validate_assignment = True

    model = ValidateAssignmentModel(this_is_a_string="hello")
    with pytest.raises(ValidationError):
        model.this_is_a_string = 1

# > Failed: DID NOT RAISE <class 'pydantic.error_wrappers.ValidationError'>

I misinterpreted what validate_assignment does. So what is it used for? 馃

validate_assignment
whether to perform validation on assignment to attributes (default: False)
Was this page helpful?
0 / 5 - 0 ratings