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

Explicit decorated __new__, __class_getitem__ and __init_subclass__ #15353

Merged
merged 10 commits into from
Jul 5, 2023

Conversation

erikkemperman
Copy link
Contributor

Fixes #15080

As I mentioned in the bug report, there are cases where mypy currently treats "special" methods differently if they are decorated explicitly.

In particular, the __new__ method is a static method whether or not it has an explicit @staticmethod decorator, and the __init_subclass__ and __class_getitem__ methods are class methods whether or not they have an explicit @classmethod decorator, as per the python docs.

This PR makes sure that mypy will treat code with explicit decorators the same as code without them. I appreciate that this isn't something that many people do (or otherwise this would have probably come up earlier) but I feel that mypy shouldn't fail if they choose to do so anyway, and with a slightly confusing message at that.

I've added a bunch of tests, but perhaps I took it a bit too far. I created a new check-special-class--and-static-methods.test file with variants of all of the unit tests that contain one of these special methods, adding the explicit decorators. Not all of these tests were failing before the patch I am proposing here. If you would rather have just those tests then I will gladly reduce them!

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

mypy/typeops.py Outdated
@@ -710,7 +710,9 @@ def callable_type(
fdef: FuncItem, fallback: Instance, ret_type: Type | None = None
) -> CallableType:
# TODO: somewhat unfortunate duplication with prepare_method_signature in semanal
if fdef.info and not fdef.is_static and fdef.arg_names:
if fdef.name == "__new__":
Copy link
Collaborator

@hauntsaninja hauntsaninja Jul 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, mutating fdef here seems a little suspicious to me. Why do we need this? (My weak mental model for when it's safe to mutate these kind of things is to try and keep it to semantic analysis, like you do in prepare method signature)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good catch, thanks! I'm actually not entirely sure why I added this -- perhaps this was before I made sure the semantic analyzer set the is_static property. At any rate, I've verified that is_static is set correctly for methods named __new__ by the time we get in typeops, meaning that it is not necessary to modify the attribute here. I've removed it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Github is having some problems, so your commit hasn't shown up. The workaround I found is to make an empty commit, push it, then reset to delete the commit, then force push

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually had some issues with my local git client suddenly deciding to use the wrong SSH key -- fixed that now, but I see that the commit still isn't visible. Will make an empty commit and push again, thanks for the tip!

@erikkemperman
Copy link
Contributor Author

erikkemperman commented Jul 5, 2023

Ah, hang on -- I now notice that I was sloppy when I removed all of those duplicated unit tests, and left some changes in the fixtures (adding classmethod and staticmethod as needed). I don't believe this is actually harmful, but it also isn't necessary anymore to have those there... I will remove them and push again. Apologies for this oversight (and having to start yet another test build).

@github-actions
Copy link
Contributor

github-actions bot commented Jul 5, 2023

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I spot checked several of the existing uses of is_static and I think they work as expected.

@hauntsaninja hauntsaninja merged commit c13f1d4 into python:master Jul 5, 2023
@erikkemperman
Copy link
Contributor Author

@hauntsaninja Thanks a lot for review and merge!

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

Successfully merging this pull request may close these issues.

Quirk with @staticmethod decorator on __new__
2 participants