-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Make self-cls-assignment
consider tuple assign. & ignore typing.cast()
#5254
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
Conversation
Pull Request Test Coverage Report for Build 1417458494
💛 - Coveralls |
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 ! I only have a small question regarding the test case.
def function(self): | ||
"""This function uses typing.cast to reassign self""" | ||
|
||
self = cast(TestTypingCast, self) |
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.
Why would we cast to TestTypingCast
here ? Wouldn't it be used in a more complex context ?
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.
I just used self
's class again because a similar example caused me to make this change. We can change it to something else, perhaps even a more generic Type
if you want!
@cdce8p Said that he thought the this message was actually correct for |
I would suggest not to special case It's much better to return the result directly, as now done in the astroid PR. def func(self) -> SomeType:
return cast(SomeType, self) |
I agree that you're probably doing something wrong when this is necessary. In our case However, I can create a contrived example where we would need to use the cast for class BaseClass:
def __init__(self):
self.advanced = False
def advanced_attribute(self) -> str:
if self.advanced:
# Will need to cast here to make this work for mypy
attr_type = self.get_attribute_type()
if attr_type == str:
return "string"
elif attr_type == int:
return "number"
else:
return ""
class SimpleClass(BaseClass):
pass
class AdvancedClass(BaseClass):
def __init__(self, attribute):
super().__init__()
self.advanced = True
self.attribute = attribute
def get_attribute_type(self):
return type(self.attribute)
print(AdvancedClass("string").advanced_attribute())
print(AdvancedClass(1).advanced_attribute()) So, based on the fact that a class's attribute has a certain value (which is only true for certain child classes) we know it has a certain method and we need to do something with that method that disallows immediately returning the cast. |
You don't need to use from typing import Any, Generic, Literal, Protocol, TypeVar
T = TypeVar("T")
class HasAdvancedAttribute(Protocol[T]):
advanced: Literal[True] = True
attribute: T
def get_attribute_type(self) -> type[T]:
...
class BaseClass:
def __init__(self) -> None:
self.advanced = False
def advanced_attribute(self: HasAdvancedAttribute[Any]) -> str:
if self.advanced:
attr_type = self.get_attribute_type()
if attr_type == str:
return "string"
if attr_type == int:
return "number"
return ""
class SimpleClass(BaseClass):
pass
class AdvancedClass(BaseClass, Generic[T]):
def __init__(self, attribute: T) -> None:
super().__init__()
self.advanced: Literal[True] = True
self.attribute: T = attribute
def get_attribute_type(self) -> type[T]:
return type(self.attribute)
print(AdvancedClass("string").advanced_attribute())
print(AdvancedClass(1).advanced_attribute()) |
Your example would indeed remove the need for |
Technically yet, but I wonder how common it really is that we need to special case it. Keep in mind, we start with In the end, I still believe the warning provides valuable feedback. A dev should really know what he/she is doing to assign the return of |
Fair enough! I'll remove the special casing and leave the handling of tuple assignments in as it is a nice enhancement of the checker. |
@DanielNoord I wondering, can you open a new PR for it? This discussion here has been quite extensive so it might be worth preserving it. |
Will do! |
doc/whatsnew/<current release.rst>
.Type of Changes
Description
Found while working on pylint-dev/astroid#1217
I don't think
typing.cast()
should raise this warning. While I was at it I thought I might as well fix this checker for tuple assignments as well.I would like for this to go in
2.12
so we can get pylint-dev/astroid#1217 inastroid
2.8.5
and thereby in2.12.1
.