-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Fix decorators on class __init__ methods #5798
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -657,6 +657,7 @@ class Decorator(SymbolNode, Statement): | |
# TODO: This is mostly used for the type; consider replacing with a 'type' attribute | ||
var = None # type: Var # Represents the decorated function obj | ||
is_overload = False | ||
callable_decorator = None # type: Optional[CallableDecorator] | ||
|
||
def __init__(self, func: FuncDef, decorators: List[Expression], | ||
var: 'Var') -> None: | ||
|
@@ -704,6 +705,28 @@ def deserialize(cls, data: JsonDict) -> 'Decorator': | |
return dec | ||
|
||
|
||
class CallableDecorator(FuncItem): | ||
"""A wrapper around a Decorator that allows it to be treated as a callable function""" | ||
def __init__(self, decorator: Decorator) -> None: | ||
super().__init__(decorator.func.arguments, decorator.func.body, | ||
cast('mypy.types.CallableType', decorator.type)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is better but I think this can be made even simpler. I don't see why this class is necessary, moreover instead of one class that I don't like ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The main reason I do it this way is that |
||
self.is_final = decorator.is_final | ||
self.is_class = decorator.func.is_class | ||
self.is_property = decorator.func.is_property | ||
self.is_static = decorator.func.is_static | ||
self.is_overload = decorator.func.is_overload | ||
self.is_generator = decorator.func.is_generator | ||
self.is_async_generator = decorator.func.is_async_generator | ||
self.is_awaitable_coroutine = decorator.func.is_awaitable_coroutine | ||
self.expanded = decorator.func.expanded | ||
self.info = decorator.info | ||
self._name = decorator.func.name() | ||
self._fullname = decorator.func._fullname | ||
|
||
def name(self) -> str: | ||
return self._name | ||
|
||
|
||
VAR_FLAGS = [ | ||
'is_self', 'is_initialized_in_class', 'is_staticmethod', | ||
'is_classmethod', 'is_property', 'is_settable_property', 'is_suppressed_import', | ||
|
@@ -2308,11 +2331,7 @@ def has_readable_member(self, name: str) -> bool: | |
def get_method(self, name: str) -> Optional[FuncBase]: | ||
for cls in self.mro: | ||
if name in cls.names: | ||
node = cls.names[name].node | ||
if isinstance(node, FuncBase): | ||
return node | ||
else: | ||
return None | ||
return get_callable(cls.names[name].node) | ||
return None | ||
|
||
def calculate_metaclass_type(self) -> 'Optional[mypy.types.Instance]': | ||
|
@@ -2935,3 +2954,13 @@ def is_class_var(expr: NameExpr) -> bool: | |
if isinstance(expr.node, Var): | ||
return expr.node.is_classvar | ||
return False | ||
|
||
|
||
def get_callable(node: Optional[Node]) -> Optional[FuncBase]: | ||
"""Check if the passed node represents a callable function or funcion-like object""" | ||
if isinstance(node, FuncBase): | ||
return node | ||
elif isinstance(node, Decorator): | ||
return node.callable_decorator | ||
else: | ||
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.
I am not sure why you need this change, but please take into account that there are three places in
checker.py
that check Liskov: one here (for "horizontal" overriding in multiple inheritance), one for variables, and one for methods etc. (There is some code duplication, I know our code is not perfect.) So please double check if you need to update other two places.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.
On closer inspection, I think you are correct that this change is unnecessary, so removing it.