Skip to content

When checking Pydantic derived models mypy ignores default values of parent fields #14850

Closed

Description

@stur86

Bug Report

When using Pydantic models, if one creates a parent model with fields with default values, then a child model inheriting from it, and instantiates the child model, mypy erroneously complains for the lack of named arguments corresponding to the parent model's fields.

To Reproduce

Simplest code:

from pydantic import BaseModel, Field

class ParentModel(BaseModel):
    a: str = Field("A")


class ChildModel(ParentModel):
    b: str = Field("B")


if __name__ == "__main__":
    c: ChildModel = ChildModel(b="X")

Expected Behavior

If the field has a default value, it's not necessary to pass it, and it should not be considered an error to not do so.

Actual Behavior

The named argument is mentioned as missing even though it has a default value:

mypy_pydantic_bug.py:12: error: Missing named argument "a" for "ChildModel"  [call-arg]
Found 1 error in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 1.1.1
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.10.4

Activity

  1. chassing commented on Mar 7, 2023

    @chassing

    And it doesn't honor allow_population_by_field_name config anymore.

    allow_population_by_field_name:
    whether an aliased field may be populated by its name as given by the model attribute, as well as the alias (default: False)

  2. erictraut commented on Mar 7, 2023

    @erictraut

    If you use a keyword argument (default=) for the field, it works.

    class ParentModel(BaseModel):
        a: str = Field(default="A")
    
    class ChildModel(ParentModel):
        b: str = Field(default="B")

    Pydantic uses dataclass_transform (defined in PEP 681), which mypy now supports. The dataclass_transform mechanism requires you to specify field arguments by keyword because this is how the stdlib dataclass works.

  3. added a commit that references this issue on Mar 7, 2023
  4. cdce8p commented on Mar 8, 2023

    @cdce8p
    Collaborator

    If you want to restore the previous behavior, pydantic 1.10.6 was released a few hours ago.
    Add the pydantic.mypy plugin to your mypy config and it should work.

    https://docs.pydantic.dev/mypy_plugin/

  5. added a commit that references this issue on Mar 9, 2023
  6. wesleywright commented on Mar 10, 2023

    @wesleywright
    Collaborator

    To elaborate a bit on the comments above: unfortunately some Pydantic features aren't fully covered by the PEP 681 specification, among them the defaults and allow_population_by_field_name. Either you'll need to use the custom plugin that Pydantic provides or you'll have to avoid using these features of Pydantic.

  7. erictraut commented on Aug 14, 2023

    @erictraut

    Summary: If you stick with the standard features of dataclass_transform, mypy is able to type check the code without any plugins. If you use more bespoke features of pydantic, then you need to install the pydantic plugin for mypy.

    Is there anything actionable remaining in this bug report?

  8. irdkwmnsb commented on Nov 15, 2023

    @irdkwmnsb

    I've spent too much time looking for an answer of my issue after upgrading to pydantic v2.
    Since this is the first google result for the query of "pydantic mypy Missing named argument", I feel obligated to add this:

    Possible resolvement:

    If you are using Optional[type] for any of your fields, make sure you add Field(default=None), as per documentation
    Also see pydantic/6713

  9. gouravsinghbais commented on Jan 11, 2024

    @gouravsinghbais

    If you use a keyword argument (default=) for the field, it works.

    class ParentModel(BaseModel):
        a: str = Field(default="A")
    
    class ChildModel(ParentModel):
        b: str = Field(default="B")

    Pydantic uses dataclass_transform (defined in PEP 681), which mypy now supports. The dataclass_transform mechanism requires you to specify field arguments by keyword because this is how the stdlib dataclass works.

    This one works pretty well for my case, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions