Search code examples
pythonpydantic

How should I specify default values on Pydantic fields with "Validate Always" to satisfy type checkers?


My type checker moans at me when I use snippets like this one from the Pydantic docs:

from datetime import datetime

from pydantic import BaseModel, validator


class DemoModel(BaseModel):
    ts: datetime = None  # Expression of type "None" cannot be 
                         # assigned to declared type "datetime"

    @validator('ts', pre=True, always=True)
    def set_ts_now(cls, v):
        return v or datetime.now()

My workarounds so far have been:

ts: datetime = datetime(1970, 1, 1)  # yuck
ts: datetime = None  # type: ignore
ts: Optional[datetime] = None  # Not really true. `ts` is not optional.

Is there a preferred way out of this conundrum?

Or is there a type checker I could use which doesn't mind this?


Solution

  • New answer

    Use a Field with a default_factory for your dynamic default value:

    from datetime import datetime
    
    from pydantic import BaseModel, Field
    
    
    class DemoModel(BaseModel):
        ts: datetime = Field(default_factory=datetime.now)
    

    Your type hints are correct, the linter is happy and DemoModel().ts is not None.

    From the Field docs:

    default_factory: a zero-argument callable that will be called when a default value is needed for this field. Among other purposes, this can be used to set dynamic default values.