Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal for users to easily define their own mypy compatible pydantic decorators #1833

Open
thejaminator opened this issue Apr 21, 2022 · 1 comment
Assignees
Labels
mypy Issues related to the mypy plugin

Comments

@thejaminator
Copy link
Contributor

thejaminator commented Apr 21, 2022

Users can't easily define their own pydantic conversion decorators with their desired defaults or values.
It wouldn't be mypy compatible.

First, partial functions don't work in mypy

The second alternative is to manually define it out

def input_all_fields(
    model: Type[PydanticModel],
    fields: Optional[List[str]] = None,
    name: Optional[str] = None,
    is_interface: bool = False,
    description: Optional[str] = None,
    directives: Optional[Sequence[StrawberrySchemaDirective]] = (),
    use_pydantic_alias: bool = True,
) -> Callable[..., Type[StrawberryTypeFromPydantic[PydanticModel]]]:
    # Custom decorator to create an input with all fields
    return strawberry.experimental.pydantic.type(
        model=model,
        fields=fields,
        name=name,
        is_input=True,
        is_interface=is_interface,
        description=description,
        directives=directives,
        all_fields=True,
        use_pydantic_alias=use_pydantic_alias,
    )

Now this doesn't work too, because of python/mypy#3135. Mypy doesn't work with class decorators out of the box.
They will need to write their own plugin to hook onto the decorator name.

Proposal A

In our mypy plugin, we check if it is a pydantic conversion parameter through a whitelist in _is_strawberry_pydantic_decorator.
We can allow more functions to be added through this whitelist.
We can have a specifc keyword that the class decorator will hook on. e.g. strawberry_pydantic

return any(
            fullname.endswith(decorator)
            for decorator in {
                 .....
                "strawberry_pydantic"
            }
        )

This way the user can define

def input_all_fields_strawberry_pydantic(
    model: Type[PydanticModel],
    fields: Optional[List[str]] = None,
    name: Optional[str] = None,
    is_interface: bool = False,
    description: Optional[str] = None,
    directives: Optional[Sequence[StrawberrySchemaDirective]] = (),
    use_pydantic_alias: bool = True,
) -> Callable[..., Type[StrawberryTypeFromPydantic[PydanticModel]]]:
    # Custom decorator to create an input with all fields
    return strawberry.experimental.pydantic.type(
        model=model,
        fields=fields,
        name=name,
        is_input=True,
        is_interface=is_interface,
        description=description,
        directives=directives,
        all_fields=True,
        use_pydantic_alias=use_pydantic_alias,
    )

and our mypy plugin will hook onto it.

This workaround is quite hacky.

Proposal B

We can add a setting for our mypy plugin which allows users to specify the decorator names.
We'll hook onto those

# mypy.ini
[strawberry-mypy]
pydantic_decorator_names = input_all_fields, some_other_decorator_name

Looking for other suggestions. @patrick91

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@thejaminator thejaminator added the mypy Issues related to the mypy plugin label Apr 21, 2022
@thejaminator thejaminator self-assigned this Apr 21, 2022
@motherofcoconuts
Copy link

Hey @thejaminator Any progress on this? I know we spoke back in April and this problem is still a pain for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mypy Issues related to the mypy plugin
Projects
None yet
Development

No branches or pull requests

2 participants