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

Misbehavior of expand_type in pydantic mypy plugin #16087

Open
dmontagu opened this issue Sep 11, 2023 · 0 comments
Open

Misbehavior of expand_type in pydantic mypy plugin #16087

dmontagu opened this issue Sep 11, 2023 · 0 comments
Labels
topic-plugins The plugin API and ideas for new plugins

Comments

@dmontagu
Copy link

dmontagu commented Sep 11, 2023

In writing the pydantic mypy plugin, I have leaned heavily on the code from the dataclasses plugin. Recently, a couple issues have been reported with misbehavior that I was able to track down to being caused by a call to expand_type changing the type from Union[str, None] to just str.

In particular, the following code snippet is misbehaving while using the pydantic mypy plugin (reported in pydantic/pydantic#7399):

import pydantic

class Model(pydantic.BaseModel):
    model_config = {'frozen': True}
    my_var: str | None = pydantic.Field(default=None)

class SubModel(Model):
    pass

reveal_type(SubModel.my_var)
#> note: Revealed type is "builtins.str"

(The revealed type should have been "Union[builtins.str, None]".)

If I change

class Model(pydantic.BaseModel):
    model_config = {'frozen': True}
    ...

to

import dataclasses
@dataclasses.dataclass(frozen=True)
class Model:
    ...

I do get the expected reveal_type result of "Union[builtins.str, None]".

After a bit of digging, I was able to trace this down to the code that freezes fields, and in particular, if I comment out this block, the issue goes away. Digging further, I found the issue was that, in this line, I would sometimes end up getting str as the "expanded type" for Union[str, None].

Of course, I also noticed the verbatim warning comment, which was taken from the dataclasses plugin here. It seems that the caveats:

however this plugin is called very late...

only apply to the dataclasses plugin, as I do not get the same (correct) behavior in the pydantic plugin. I was able to find a hacky work-around for this specific failure (included in this PR), where, if I passed in a Union and got out a non-Union from expand_type I defer analysis, and this did resolve one of the reported issues, but it feels to me like there are probably many other cases that that won't handle correctly, and I'm not sure what exactly I can/should do to handle this more correctly.

Any suggestions about how to ensure that the pydantic plugin behaves the same as the dataclasses plugin with regard to expand_type would be appreciated! (Or other suggestions about how to improve the plugin logic, of course.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-plugins The plugin API and ideas for new plugins
Projects
None yet
Development

No branches or pull requests

2 participants