-
-
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
Allow @final
on TypedDict
#13557
Allow @final
on TypedDict
#13557
Conversation
This comment has been minimized.
This comment has been minimized.
@@ -1469,8 +1469,8 @@ def analyze_typeddict_classdef(self, defn: ClassDef) -> bool: | |||
for decorator in defn.decorators: | |||
decorator.accept(self) | |||
if isinstance(decorator, RefExpr): | |||
if decorator.fullname in FINAL_DECORATOR_NAMES: | |||
self.fail("@final cannot be used with TypedDict", decorator) | |||
if decorator.fullname in FINAL_DECORATOR_NAMES and info is not 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.
What if the info is None? Does that happen if there's a circular reference? It would be good to get a test covering that code path.
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.
It could be FakeInfo
for some reason.
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 if the info is None? Does that happen if there's a circular reference?
When there's a forward declaration in the TypedDict
body, analyze_typeddict_classdef
gets called multiple times. info
is initially None
in that case, but eventually it's a TypeInfo
.
It would be good to get a test covering that code path.
Done.
It could be
FakeInfo
for some reason.
When would that happen?
Also the CI failures look like there are some duplicate error messages. |
Allow a `TypedDict` to be decorated with `@final`. Like a regular class, mypy will emit an error if a final `TypedDict` is subclassed. Relates-to: python#7981
3c0a1ed
to
623a332
Compare
That's what I get for only running the |
This comment has been minimized.
This comment has been minimized.
Huh. This seems to be causing a mypyc segfault, judging by The mypyc tests ( |
The segfaults may be unrelated, we're seeing them on a bunch of PRs. Not sure what's causing them :( |
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 looks good to me!
Although it's a little surprising to me that we don't have the correct MRO (in which case we could just fallback to the existing final logic in checker.py). Not familiar enough with mypy's TypedDict impl to know if that's intentional.
According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉 |
Allow a
TypedDict
to be decorated with@final
. Like a regular class, mypy will emit an error if a finalTypedDict
is subclassed.Relates-to: #7981
Description
Allow
@final
to be applied to aTypedDict
, and have mypy emit an error if class is derived from a finalTypedDict
. This goes some way towards closing #7981 and closing a feature gap with pyright, though not the whole way, as #7981 also asks for additional type narrowing for a finalTypedDict
.Test Plan
testCannotUseFinalDecoratorWithTypedDict
was removed, andtestCannotSubclassFinalTypedDict
added.