davidhalter / jedi

Awesome autocompletion, static analysis and refactoring library for python
http://jedi.readthedocs.io
Other
5.81k stars 508 forks source link

Autocompletion breaks after a decorator #2024

Open vhaldemar opened 2 months ago

vhaldemar commented 2 months ago

Hey! I saw this topic was already brought here a few times, so I excuse for doing this again, but I coulnd't find any workarounds and don't know what to do.

I am working on some sort of SDK with a sync client version and async one and I am really don't want to copypaste all of the methods signatures all over my codebase.

So I have next decorator:

def run_sync(coro: Callable[Concatenate[Any, P], Awaitable[T]]) -> Callable[Concatenate[Any, P], T]:        
    @wraps(coro)    
    def wrapped(self: Any, *args: P.args, **kwargs: P.kwargs) -> T:    
        ...

    return wrapped

and I use this decorator next way:

class AsyncOne:
    async def method(self, arg):
        """docstring""
        ...

class SyncOne(AsyncOne):
    method = run_sync(AsyncOne.method)

I am using jedi=0.19.1, python=3.8 and typing_extensions for a ParamSpec and Concatenate.

I tried to use .pyi to get some hint to Jedi, and it works from a signature perspective, but it is still losing a doctstring. Thanks in advance!

davidhalter commented 2 months ago

Do signatures work without .pyi? I would personally be surprised if they do, because I do not feel like we support ParamSpec.

I feel like the docstring should work with @wraps without the annotation of coro: Callable[...]. But otherwise this is kind of annoyinng to get working, because we would need to ignore the annotations of run_sync and simply do type inference on the inner part.

vhaldemar commented 1 month ago

Do signatures work without .pyi? I would personally be surprised if they do, because I do not feel like we support ParamSpec.

Nope

I feel like the docstring should work with @wraps without the annotation of coro: Callable[...]

Nope, but for some reason half of the params works

I would personally be surprised if they do, because I do not feel like we support ParamSpec.

I checked output Scipt.infer on a line with a call of a decorated method, and it gives just Callable.

Anyway, my research concluded that there is no good way to handle this problem (at least right now), and even if I will manage to fix it for jedi, there are still will be left PyCharm with probably different autocomplition engine, soooo I decided to copypaste all of the methods signatures into my sync client plus write a test which will check signatures are not different in sync & async clients. Maybe in some future I will bring codegeneration for this task.

Thanks for your response!