pydantic / pydantic

Data validation using Python type hints
https://docs.pydantic.dev
MIT License
20.21k stars 1.82k forks source link

`default` should be keyword only in `Field` otherwise type checkers don't recognize it #9902

Closed DetachHead closed 1 month ago

DetachHead commented 1 month ago

Initial Checks

Description

when specifying the default value to Field as a positional argument, neither mypy or pyright recognizes it and incorrectly treats the field as mandatory.

i believe this is because of how typing.dataclass_transform works. since dataclasses.field takes default as a keyword only argument, pydantic.fields.Field shouldn't allow it to be specified positionally.

Example Code

from pydantic import Field
from pydantic.dataclasses import dataclass

@dataclass
class Foo:
    a: int | None = Field(None)
    b: int | None = Field(default=None)

foo = Foo() # mypy & pyright error: Argument missing for parameter "a"

Python, Pydantic & OS Version

pydantic version: 2.8.2
        pydantic-core version: 2.20.1
          pydantic-core build: profile=release pgo=true
                 install path: C:\Users\user\project\.venv\Lib\site-packages\pydantic
               python version: 3.12.0 (tags/v3.12.0:0fb18b0, Oct  2 2023, 13:03:39) [MSC v.1935 64 bit (AMD64)]
                     platform: Windows-11-10.0.22621-SP0
             related packages: typing_extensions-4.12.2
                       commit: unknown
Viicos commented 1 month ago

This was discussed here: https://github.com/pydantic/pydantic/discussions/7379#discussioncomment-6951557.

Unfortunately making default a kw-only argument is a breaking change so I don't think this can be changed easily.

sydney-runkle commented 1 month ago

Thanks @Viicos for the discussion here.

Going to close this as a duplicate of https://github.com/pydantic/pydantic/issues/3617, which, as @Viicos mentioned, explains why this is too breaking of a change to implement. If you're looking for cleaner type checking, you can use the default=... syntax.