-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Add signature for attr.evolve #14526
Conversation
e47698c
to
042aa94
Compare
042aa94
to
cd832cc
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
mypy/plugins/default.py
Outdated
) -> Callable[[FunctionSigContext], FunctionLike] | None: | ||
from mypy.plugins import attrs | ||
|
||
if fullname in ("attr.evolve", "attr.assoc"): |
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.
There’s also attrs.evolve()
- maybe that’s just an alias and will work, but it should be tested. Perhaps these should be moved to a constant with the others at the start of the attrs plug-in module also?
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.
Yep, yep. All still WIP.
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.
Ready now!
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
mypy-primer identified an error in home-assistant: new = self.areas[area_id] = attr.evolve(old, **new_values) Typing |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
test-data/unit/fine-grained.test
Outdated
2: <b>, <b[wildcard]>, __main__ | ||
3: <b>, <b[wildcard]>, __main__, a |
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.
So.... the addition of dict
in fixtures/list.pyi now causes __annotations__
to exist:
Lines 636 to 639 in bac9e77
elif name == "__annotations__": | |
sym = self.lookup_qualified("__builtins__.dict", Context(), suppress_errors=True) | |
if not sym: | |
continue |
which then makes __annotations__
one of the names in the diff (reasonably...):
Lines 781 to 795 in a08388c
if item.count(".") <= package_nesting_level + 1 and item.split(".")[-1] not in ( | |
"__builtins__", | |
"__file__", | |
"__name__", | |
"__package__", | |
"__doc__", | |
): | |
# Activate catch-all wildcard trigger for top-level module changes (used for | |
# "from m import *"). This also gets triggered by changes to module-private | |
# entries, but as these unneeded dependencies only result in extra processing, | |
# it's a minor problem. | |
# | |
# TODO: Some __* names cause mistriggers. Fix the underlying issue instead of | |
# special casing them here. | |
diff.add(id + WILDCARD_TAG) |
I've created #14547 to discuss this more.
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.
This comment has been minimized.
This comment has been minimized.
7188141
to
cf756d1
Compare
ab8d33b
to
babf91f
Compare
This comment has been minimized.
This comment has been minimized.
@AlexWaygood can label with attrs? :) |
This comment has been minimized.
This comment has been minimized.
🤔 Curious why the mypy_primer diff here is gone: |
@JelleZijlstra would love to get some eyes on this (I was waiting for #14575 to merge to reduce the diff) |
This comment has been minimized.
This comment has been minimized.
According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉 |
I can take a look in the next few days. This function is basically equivalent to |
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.
Looks good, just one minor point.
@@ -1775,7 +1775,7 @@ def copy_modified( | |||
self: CT, | |||
arg_types: Bogus[Sequence[Type]] = _dummy, | |||
arg_kinds: Bogus[list[ArgKind]] = _dummy, | |||
arg_names: Bogus[list[str | None]] = _dummy, | |||
arg_names: Bogus[Sequence[str | None]] = _dummy, |
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.
What is the reason for this change? I'd prefer to avoid touching the mypy core in this PR.
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.
Because of list's invariance — otherwise, this fails since it passes list[str]
:
arg_names=["inst"] + attrs_init_type.arg_names[1:],
CallableType.__init__
accepts arg_names: Sequence[str | None]
but I guess CallableType.copy_modified
was not updated in tandem.
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.
Broke out into #14840 — can merge then update this branch.
# <hack> | ||
assert isinstance(ctx.api, TypeChecker) | ||
inst_type = ctx.api.expr_checker.accept(inst_arg) | ||
# </hack> |
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.
@JelleZijlstra now that we got this merged 😅 what would be the right place to discuss whether this should be promoted to be formal plugin API?
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.
Open an issue, I suppose.
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.
👉 #14845
hey, I have tried to run this in my project, doen't work well when evolving generic classes
|
@LukasKrocek this was just mentioned in the review for #14849 — addressed in c005895, but here it would actually be simpler |
Generics should be addressed in #15016. |
Validate `dataclassses.replace` actual arguments to match the fields: - Unlike `__init__`, the arguments are always named. - All arguments are optional except for `InitVar`s without a default value. The tricks: - We're looking up type of the first positional argument ("obj") through private API. See #10216, #14845. - We're preparing the signature of "replace" (for that specific dataclass) during the dataclass transformation and storing it in a "private" class attribute `__mypy-replace` (obviously not part of PEP-557 but contains a hyphen so should not conflict with any future valid identifier). Stashing the signature into the symbol table allows it to be passed across phases and cached across invocations. The stashed signature lacks the first argument, which we prepend at function signature hook time, since it depends on the type that `replace` is called on. Based on #14526 but actually simpler. Partially addresses #5152. # Remaining tasks - [x] handle generic dataclasses - [x] avoid data class transforms - [x] fine-grained mode tests --------- Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Validate
attr.evolve
calls to specify correct arguments and types.The implementation makes it so that at every point where
attr.evolve
is called, the signature is modified to expect the attrs class' initializer's arguments (but so that they're all kw-only and optional).Notes:
class dict: pass
to some fixtures files since our attrs type stubs now have **kwargs and that triggers abuiltin.dict
lookup in dozens of attrs tests.ctx.api.expr_checker.accept(inst_arg)
which is a hack since it's not part of the plugin API. This is a compromise for due to Adjusting the signature of a function on the basis of caller types in plugin #10216.Fixes #14525.