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
Fix mypy plugin for 1.1.0 #5077
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍🏻
Looks like this PR is against the (Looks good to me as well.) |
That would be great. The plugin wouldn't work properly for the next mypy release (1.1.0) without this change. |
pydantic/mypy.py
Outdated
assert info_metaclass | ||
if getattr(info_metaclass.type, 'dataclass_transform_spec', None): | ||
info_metaclass.type.dataclass_transform_spec = None # type: ignore[attr-defined] | ||
return None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this return
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍
Thanks @cdce8p for this.
It seems there are two Prs in mypy:
- Fix crash with
dataclass_transform
cache python/mypy#14734 (Created by @cdce8p) - [dataclass_transform] detect transform spec changes in incremental mode python/mypy#14695
Seems we need this fix in main
and 1.10.x
whether your PR is merged or the other one
Yeah, although both would address a different issue to this one.
Exactly 👍🏻 |
Forgot to mention, I think we need a test for this change as well. |
That's a bit more complicated 😅 Of course the obvious issue here is that the mypy change isn't released yet. So just in theory, there is a (very) slim chance the attribute could change which would require additional work here. However, with the If you really want to have a test first, it might be better to wait for the actual mypy release and see it break first. Or we move forward with the PR and I come back later to update the mypy version used for the tests. |
@cdce8p @hramezani I think if the current mypy plugin tests fail if run using mypy 1.1.0, but pass with this change, then we might not need a new test. If the current tests don't fail then I can help put one together quickly to get this across the line. (Should be straightforward to just copy/paste the example at the top of this into a new file in the |
@cdce8p Does this mean that if using mypy without the plugin, anyone using |
Not just with from pydantic import BaseModel, Field
class Event(BaseModel):
id: int | None = Field(None, alias="event")
required_var: str | None = Field(...)
optional_var: str | None
Event()
Tbh I don't know if other type checker depend on it, mainly pyright. I would image they also have custom logic for pydantic just because of the default value issue. However IMO, the better alternative would be to adopt the "default" syntax for custom Fields. I.e. any argument is required unless it is assigned
Ran the mypy tests. |
Want to bring this to your attention. ☝️
I think it's reasonable to tell people they have to use |
Just to clarify, some example class Event(BaseModel):
# ok
a: int | None = Field(default=None)
b: int | None = None
c: int
d: int = Field(...) # required -> only works without 'default' keyword
# error
e: int | None = Field(None) # false-positive: not recognized as optional
f: int | None # false-positive: not recognized as optional
g: int = ... # false-negative: not recognized as required; but different mypy error [assignment]
# Add empty constructor to show errors
Event() |
It might still makes sense to add this PR and not fall back to Never the less, syntax that more aligns with the stdlib |
Oh yeah I didn’t mean to indicate we shouldn’t merge this PR |
Just pushed a small addition which adds a I don't plan on adding anything else, so it would be ready to merge from my POV. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, just catching up on this.
In principle this looks good (although I don't pretend to understand all the nuances).
I'll discuss with @dmontagu today and hopefully merge
A few (perhaps related) questions:
- should this be back-ported to the
1.10
pydantic branch? - do the changes to required logic in v2 affect this at all?
Thanks so much @cdce8p for digging into this and all your work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, just catching up on this.
In principle this looks good (although I don't pretend to understand all the nuances).
I'll discuss with @dmontagu today and hopefully merge
A few (perhaps related) questions:
- should this be back-ported to the
1.10
pydantic branch? - do the changes to required logic in v2 affect this at all?
Thanks so much @cdce8p for digging into this and all your work.
Yes
No. The changes will improve the type checking experience for anyone
|
on your points:
|
Not in the context of
True, however that doesn't work if the model is part of a library that is used somewhere else. Especially if the maintainer of said library doesn't want to change it only to better support static typing.
Didn't know that. Only saw it in the Lines 49 to 50 in ae481b9
pydantic/pydantic/dataclasses.py Lines 175 to 176 in ae481b9
-- Tbh those suggestions would be nice but the pydantic mypy plugin resolves all of these issues, once mypy knows to ignore the |
@cdce8p we can add a recommendation to the docs to do those things "the right way", but we don't want to break V1 code unless we have to. |
* Fix mypy plugin for 1.1.0 * Code review * Add version key to plugin data
Is this working with import pydantic
@pydantic.dataclasses.dataclass
class A:
a: str
A("") # error: Too many positional arguments for "A" [misc] |
Pydantic dataclasses are keyword only: https://docs.pydantic.dev/usage/dataclasses/ pydantic/pydantic/dataclasses.py Lines 175 to 176 in 6267ae3
https://peps.python.org/pep-0681/#decorator-function-and-class-metaclass-parameters |
@cdce8p I don't think they are keyword only as that example works correctly at runtime and with the pydantic mypy plugin with v1.0.1. It's only with this change that they are now reporting errors. |
Are you sure that it's this change? As it doesn't change anything regarding |
I did mean that, that mypy caused this defect originally. But also that, this PR doesn't seem to be a complete fix, as the functionality of dataclassess has regressed. |
pydantic dataclasses are not kwarg only, however we decorate them with pydantic/pydantic/dataclasses.py Line 96 in 314abca
and other overloads. Not sure why we did that, but I guess it could be changed? |
Mypy It could make sense to include #5120 as well, although that was already broken. https://mypy-lang.blogspot.com/2023/03/mypy-111-released.html |
@cdce8p Do you mind if I merge the stuff from #5120 directly into this branch, along with some changes to tests to get everything behaving nicely? If so, I'll take care of it and I think we can have this ready to merge first thing tomorrow. (If I don't hear from you in the next few hours I might just start pushing..) |
Not at all! Please let me know if I can help. |
(And to be clear, I meant the cherry-pick branch for 1.10.X, not this branch.) My current plan is to make it so that you can get strict/lenient behavior on mypy 1.1.1 by using the plugin, but without the plugin, when using mypy 1.1.1 it becomes "strict" in accordance with mypy's handling of @cdce8p would that work for you? I will add some commits onto the cherry-pick branch, once I've done I'll notify you and it would be great if you could confirm if the changes work for you on Home Assistant. |
That sounds like exactly what this PR / the cherry-pick one does, so yes. Basically the PR only restores the plugin behavior for mypy
Sounds good -- |
Yeah I realized that I didn't need to do anything because I wasn't going to make the tests actually pass on 1.1.1. So I just merged your changes in there. |
* Fix mypy plugin for 1.1.0 (#5077) * Fix mypy plugin for 1.1.0 * Code review * Add version key to plugin data (cherry picked from commit 6267ae3) * Change file name * Add the changes from #5120 * Update changes file * Remove additional unneeded dataclass import (from #5120) --------- Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>
Mypy 1.1.1 throws errors with pydantic models that specify default values with positional arguments. The next pydantic version will probably fix it by updating the mypy-pydantic plugin, but converting the default value to a keyword argument is no big deal either. So let's fix it today. For more info pydantic/pydantic#5077
Mypy 1.1.1 throws errors with pydantic models that specify default values with positional arguments. The next pydantic version will probably fix it by updating the mypy-pydantic plugin, but converting the default value to a keyword argument is no big deal either. So let's fix it today. For more info pydantic/pydantic#5077
Hi, first of all thank you for you patch, but I'm still having this issue with I was getting a lot of these errors, so I added to my code exactly your same class: class Event(BaseModel):
id: int | None = Field(None, alias="id") and when I run
update: there was no 1.1.0 release, only 1.1.1 so the problem seems to be still there. Thanks |
@andreagrandi See #5192 — I'll make sure that we address this once we get back to looking at the mypy plugin again (hopefully not too far out). |
@dmontagu thank you for the quick reply and my bad I didn't check among existing issues 🙇🏻 I will stay tuned, thanks again! |
We need to use the pydantic mypy plugin to work around the breaking changes in mypy 1.1 that required pydantic/pydantic#5077
getting dozens of mypy errors with upgraded pydantic (1.10.6) and mypy (1.1.1); ... ``` tests/test_transform.py:57: error: Missing named argument "doaj_id" for "ScholarBiblio" [call-arg] tests/test_transform.py:57: error: Missing named argument "dblp_id" for "ScholarBiblio" [call-arg] tests/test_transform.py:57: error: Missing named argument "oai_id" for "ScholarBiblio" [call-arg] ``` related: pydantic/pydantic#5077 For the moment, try to follow dependency upgrades to not let the gap become too larget; albeit these issues are time-consuming to sort out.
The next mypy release will add better support for
dataclass_transform
.Since
ModelMetaclass
is decorated with it, it means that mypy would use that instead of the custom plugin. The plugin is quite good at parsingBaseModel
, so the result would be worse. Especially with regards to the of default arguments aspydantic.field.Field
uses a slightly different syntax.With this PR, the plugin will basically pretend
ModelMetaclass
isn't decorated and thus continue to use the plugin for it.I've also added a new (undocumented) option
debug_dataclass_transform
to be able to toggle that behavior and test new future versions of mypy without modifying the plugin again.If accepted, it would be great if this PR could be backported to
1.10.X
and a new version released. The next mypy release which would otherwise break this behavior is currently scheduled for the end of February.--
Without this PR mypy
1.1.0
would emit