Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 511
LondonRob Avatar asked Sep 12 '25 04:09

LondonRob


2 Answers

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.

like image 161
Ogaday Avatar answered Sep 14 '25 19:09

Ogaday


If the field is required, then you just don't supply a default:

class DemoModel(BaseModel):
    ts: datetime

Pydantic will prevent you from instantiating an instance of DemoModel if you don't supply a ts argument in this case.

like image 29
Daniel Quinn Avatar answered Sep 14 '25 19:09

Daniel Quinn