The following code shows a pylance (pyright) error for AModel()
of Argument missing for parameter "field_b"
:
from pydantic import BaseModel, Field
from typing import Optional, Any
class AModel(BaseModel):
field_a: str = Field()
field_b: Optional[bool] = Field(None)
instance_1 = AModel(field_a="", field_b=None) # No error
instance_2 = AModel(field_a="") # Error
# ^^^^^^^^^^^^^^^^^^
kwargs: dict[str, Any] = {"field_a": "", "field_bad": True}
instance_3 = AModel(**kwargs) # No error but no type checking
Is it possible to instantiate this model without providing field_b=None
and whilst retaining type checking?
You need to either specify default=
explicitly or drop the Field()
call altogether:
class AModel(BaseModel):
field_a: str = Field()
field_b: Optional[bool] = Field(default=None)
### or
field_b: Optional[bool] = None
As it is written, Pydantic's Field
allows default
to be passed positionally:
Field(
default: Any = PydanticUndefined,
*,
# ...
) -> Any
However, default
is a field specifier parameter, and the typing specification requires such parameters to be keyword-only for them to be detectable by type checkers (emphasis mine):
Libraries that support dataclass-like semantics and support field specifier classes typically use common parameter names to construct these field specifiers. This specification formalizes the names and meanings of the parameters that must be understood for static type checkers. These standardized parameters must be keyword-only.
See also this GitHub discussion, where a maintainer of Pyright posted the same answer.