Skip to content

Now TypeInfo.get_method also returns Decorator nodes #11150

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

Merged
merged 11 commits into from
Dec 3, 2021
Merged

Now TypeInfo.get_method also returns Decorator nodes #11150

merged 11 commits into from
Dec 3, 2021

Conversation

sobolevn
Copy link
Member

Closes #10409

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! Left a few comments and a question.

@sobolevn
Copy link
Member Author

This commit just addresses the code review: 28d950d

Now, I am going to change how .get_method() is defined. Let's see what will happen!

@github-actions

This comment has been minimized.

@sobolevn
Copy link
Member Author

I am running self-check with the only change: def get_method(self) -> Union[FuncBase, Decorator, None]

» python runtests.py self
run self: ['/Users/sobolev/Desktop/mypy/.venv/bin/python', '-m', 'mypy', '--config-file', 'mypy_self_check.ini', '-p', 'mypy']
mypy/subtypes.py:618: error: Item "Decorator" of "Union[FuncBase, Decorator]" has no
attribute "is_property"  [union-attr]
            if method.is_property:
               ^
mypy/subtypes.py:623: error: Argument 1 to "find_node_type" has incompatible type
"Union[FuncBase, Decorator]"; expected "Union[Var, FuncBase]"  [arg-type]
            return find_node_type(method, itype, subtype)
                                  ^
mypy/subtypes.py:644: error: Argument 1 to "find_node_type" has incompatible type
"Union[FuncBase, Decorator]"; expected "Union[Var, FuncBase]"  [arg-type]
    ...         getattr_type = get_proper_type(find_node_type(method, itype, subtyp...
                                                              ^
mypy/subtypes.py:667: error: Item "Decorator" of "Union[FuncBase, Decorator]" has no
attribute "is_property"  [union-attr]
            if method.is_property:
               ^
mypy/checkmember.py:199: error: Item "Decorator" of "Union[FuncBase, Decorator]" has
no attribute "is_property"  [union-attr]
            if method.is_property:
               ^
mypy/checkmember.py:205: error: Argument 1 to "function_type" has incompatible type
"Union[FuncBase, Decorator]"; expected "FuncBase"  [arg-type]
            signature = function_type(method, mx.builtin_type('builtins.function...
                                      ^
mypy/checkmember.py:216: error: Item "Decorator" of "Union[FuncBase, Decorator]" has
no attribute "is_class"  [union-attr]
    ...     signature = check_self_arg(signature, dispatched_type, method.is_class,
                                                                   ^
mypy/checkmember.py:218: error: Item "Decorator" of "Union[FuncBase, Decorator]" has
no attribute "is_class"  [union-attr]
    ...gnature = bind_self(signature, mx.self_type, is_classmethod=method.is_class)
                                                                   ^
mypy/checkmember.py:392: error: Argument 1 to "function_type" has incompatible type
"Union[FuncBase, Decorator]"; expected "FuncBase"  [arg-type]
                        function = function_type(method, mx.builtin_type('builti...
                                                 ^
mypy/checkmember.py:409: error: Argument 1 to "function_type" has incompatible type
"Union[FuncBase, Decorator]"; expected "FuncBase"  [arg-type]
                    setattr_func = function_type(setattr_meth, mx.builtin_type('...
                                                 ^
mypy/checkmember.py:479: error: Argument 1 to "function_type" has incompatible type
"Union[FuncBase, Decorator]"; expected "FuncBase"  [arg-type]
        function = function_type(dunder_get, builtin_type('builtins.function'))
                                 ^
mypy/checker.py:3125: error: Argument 1 to "function_type" has incompatible type
"Union[FuncBase, Decorator]"; expected "FuncBase"  [arg-type]
            function = function_type(dunder_set, self.named_type('builtins.funct...
                                     ^
mypy/checker.py:6042: error: Never apply isinstance() to unexpanded types; use
mypy.types.get_proper_type() first  [misc]
                if isinstance(method.type, Overloaded):
                   ^
mypy/checker.py:6042: note: If you pass on the original type after the check, always use its unexpanded version
Found 13 errors in 3 files (checked 164 source files)

FAILED: self

Looks doable! 👍

@sobolevn
Copy link
Member Author

This is now pretty big:

  1. I've changed all parts where .get_method() was used to work with decorators, including
  • Protocol checks with find_member
  • is_untyped_decorator function in checker
  • checkmember
  1. I've changed how type was inferenced from decorators, so for example decorating x.__getattr__ actually changes what type is inferred for x.attr
  2. I've added new tests for each individual change, improved some existing ones

else:
result = getattr_type

# Call the attribute hook before returning.
Copy link
Member Author

Choose a reason for hiding this comment

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

Now plugin hooks are also triggered for non callable types as well.

@sobolevn sobolevn changed the title Now decorated __getattr__ works Now TypeInfo.get_method also returns Decorator nodes Sep 22, 2021
@sobolevn
Copy link
Member Author

sobolevn commented Sep 22, 2021

Ok, looks like mypyc also need to be fixed. It is failing right now https://github.com/python/mypy/runs/3673913236

@JukkaL any tips on that? I haven't used mypyc 😞

@sobolevn
Copy link
Member Author

mypyc didn't like this code:

if isinstance(node, (FuncBase, Decorator)):
    return node

But, it accepted this code:

if isinstance(node, FuncBase):
    return node
elif isinstance(node, Decorator):
    return node

Seems like a bug in mypyc to me.

@JukkaL
Copy link
Collaborator

JukkaL commented Sep 24, 2021

I think I found a reproducer for the mypyc issue: mypyc/mypyc#892

@sobolevn
Copy link
Member Author

@JukkaL awesome! Thanks! Is there anything else left to do here?

@sobolevn
Copy link
Member Author

sobolevn commented Oct 2, 2021

Rebased on master 🚆

@github-actions

This comment has been minimized.

@sobolevn
Copy link
Member Author

@JukkaL any chance to get this merged? 🙂

@sobolevn
Copy link
Member Author

sobolevn commented Nov 6, 2021

@JukkaL rebased once again 🙂

I will also friendly ping @hauntsaninja as well.

@github-actions

This comment has been minimized.

@97littleleaf11 97littleleaf11 self-requested a review November 12, 2021 17:42
Copy link
Collaborator

@97littleleaf11 97littleleaf11 left a comment

Choose a reason for hiding this comment

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

Using MemberContext in analyze_descriptor_access is a good refactoring!

Copy link
Collaborator

@JukkaL JukkaL left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, this looks solid! I like how this fixes many related issues.


function = function_type(dunder_set, self.named_type('builtins.function'))
bound_method = bind_self(function, attribute_type)
if isinstance(dunder_set, Decorator):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Code quite similar to this if/else gets repeated several times. I wonder if it would be possible to abstract it into a helper function, for example? If this sounds like a feasible idea, it could be a nice follow-up PR.

@JukkaL JukkaL merged commit 4e34fec into python:master Dec 3, 2021
@sobolevn
Copy link
Member Author

sobolevn commented Dec 3, 2021

@JukkaL thank you! I will think about a helper function 🙂

97littleleaf11 pushed a commit that referenced this pull request Dec 5, 2021
* Follow up to #11150, refactors `if`s into a util function
tushar-deepsource pushed a commit to DeepSourceCorp/mypy that referenced this pull request Jan 20, 2022
Support decorators properly in additional contexts.

Closes python#10409
tushar-deepsource pushed a commit to DeepSourceCorp/mypy that referenced this pull request Jan 20, 2022
* Follow up to python#11150, refactors `if`s into a util function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

mypy doesn't understand @abc.abstractmethod on __getattr__
3 participants