Pydantic: Can we have __post_init_post_parse__ for BaseModel please?

Created on 25 Jul 2019  路  5Comments  路  Source: samuelcolvin/pydantic

I am painfully missing a method on BaseModel which is called after parsing has finished.
Akin to __post_init_post_parse__ which is right now only available for data classes.

Are there any plans to implement such?

Feedback Wanted feature request

Most helpful comment

great. I think that should remain fine, although I've been wrong before :-).

I think we still need @validator('__after__') or @validator('__root__') or something, but I guess that's another issue for the future.

All 5 comments

What do you want to do there?

The simplest option now would be to override __init__:

class MyModel(BaseModel):
    foo: int
    bar: float

    def __init__(self, **data: Any):
        super().__init__(**data)
        print('do my stuff...')

A few problems with that approach:

  • It won't be called for from_orm or a few other ways of creating a model instance
  • It wouldn't allow you to raise exceptions which are wrapped in a standard ValidationError if there are problems with the data

A couple of options:

  • anther method on a model, something post_parse which is called after parse, allows parsing errors to be raised and adds them to a new __all__ or __base__ key in the error.
  • a special value to @validator like @validator('__after__') which means that validator is called last.

@samuelcolvin Thank you for your fast and in-depth reply.

You asked:

What do you want to do there?

Well, I am in need of the method in question to populate a dict member of my class with additional data:
https://github.com/jpscaletti/copier/blob/901051677fe88c9559d0db65bde2ad07384163b2/copier/config/objects.py#L70

This population should always happen, representing an inherent behavior of that said class.
Hence, it being most logically to put the assignment logic in the class itself. However, it is crucial for that assignment to happened after the validation has run.

The reason being that I abuse validators to do some data transformation upfront. Namely, resolving str to Paths.

I think your __init__ solution is fine. You could also add another field folder_name: str = None and populate it using a validator:

@validator('folder_name')
def populate_folder_name(cls, v, values):
    return values.get('folder_name')

@samuelcolvin If you say the init solution is the way to go, I am fine with that.
My main concern is not to abuse pydantic in a way of having unintended consequences.

I am closing this.

great. I think that should remain fine, although I've been wrong before :-).

I think we still need @validator('__after__') or @validator('__root__') or something, but I guess that's another issue for the future.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jasonkuhrt picture jasonkuhrt  路  21Comments

Yolley picture Yolley  路  18Comments

dand-oss picture dand-oss  路  19Comments

rrbarbosa picture rrbarbosa  路  35Comments

chopraaa picture chopraaa  路  18Comments