8000 Decorated bound instance method cannot be inferred correctly. · Issue #3954 · microsoft/pyright · GitHub
[go: up one dir, main page]

Skip to content

Decorated bound instance method cannot be inferred correctly. #3954

@huntzhan

Description

@huntzhan

Note: if you are reporting a wrong signature of a function or a class in the standard library, then the typeshed tracker is better suited for this report: https://github.com/python/typeshed/issues.

Describe the bug
A clear and concise description of what the bug is.

from typing import Callable, TypeVar
from typing_extensions import Concatenate, ParamSpec

_S = TypeVar('_S')
_P = ParamSpec('_P')
_R = TypeVar('_R')


def proxy_method(method: Callable[[_S], Callable[_P, _R]]) -> Callable[Concatenate[_S, _P], _R]:

    def new_method(_self: _S, *args: _P.args, **kwargs: _P.kwargs):
        other_method = method(_self)
        return other_method(*args, **kwargs)

    return new_method


class Foo:

    def do_something(self, x: int):
        return 42 + x


class Bar:

    def __init__(self):
        self.foo = Foo()

    @proxy_method
    def do_something(self):
        return self.foo.do_something

    def do_other(self, x: int):
        return x + 1


def debug():
    Bar.do_something
    Bar.do_other
    bar = Bar()
    print(bar.do_other(1))
    print(bar.do_something(1))

proxy_method decorates an instance method (Bar.do_something). The instance method to be decorated should return a callable (self.foo.do_something). proxy_method should return a new instance method (function) simply acting as a proxy method to the the callable. Hence, calling bar.do_something(1) is equivalent to calling bar.foo.do_something(1).

But pyright cannot infer the bound instance method correctly:

image

(bar.do_something should be inferred as bound, and should not raise a type error)

And I also notice pyright treats the "naive" instance method (function) and the decorated one differently:

image

(Bar.do_something is decorated)

image

(Bar.do_other is not decorated)

To Reproduce
Steps to reproduce the behavior.

aforementioned.

Expected behavior
A clear and concise description of what you expected to happen.

bar.do_something should be inferred as bound, and should not raise a type error, just like bar.do_other:

image

Screenshots or Code
If applicable, add screenshots or the text of the code (surrounded by triple back ticks) to help explain your problem.

def foo(self) -> str:
    return 3

inlined.

If your code relies on symbols that are imported from a third-party library, include the associated import statements and specify which versions of those libraries you have installed.

VS Code extension or command-line
Are you running pyright as a VS Code extension or a command-line tool? Which version? You can find the version of the VS Code extension by clicking on the Pyright icon in the extensions panel.

I'm running pyright v1.1.271 as a VS Code extension.

Additional context
Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    as designedNot a bug, working as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0