Tinkoff / invest-python

Tinkoff Invest Python gRPC client
https://tinkoff.github.io/invest-python/
Apache License 2.0
301 stars 87 forks source link

[Bug] mypy infers return type of InstrumentsService methods as Any #199

Closed ikokostya closed 1 year ago

ikokostya commented 1 year ago

Что случилось?

mypy выводит тип методов всех сервисов клиента Client как Any:

import os

from tinkoff.invest import Client                                                               

token = os.environ["INVEST_TOKEN"]                                                              

with Client(token) as client:                                                                   
     reveal_type(client.instruments)                                                        
     reveal_type(client.instruments.get_assets)
$ mypy test.py 
test.py:8: note: Revealed type is "tinkoff.invest.services.InstrumentsService"
test.py:9: note: Revealed type is "Any"
Success: no issues found in 1 source file
$ mypy --version
mypy 1.0.1 (compiled: yes)

Таким образом, обращение к любым атрибутам возвращаемых объектов никак не проверяется.


Проблема заключается в том, что методы декорированы функцией handle_request_error

https://github.com/Tinkoff/invest-python/blob/75e33fecf4ae4683e91806051e5f09cae3ce34da/tinkoff/invest/services.py#L755-L756

у которой нет аннотации возвращаемого типа

https://github.com/Tinkoff/invest-python/blob/75e33fecf4ae4683e91806051e5f09cae3ce34da/tinkoff/invest/_errors.py#L13

поэтому mypy выводит ее тип как Any (вывод возвращаемого типа на основе тела функции в mypy пока не реализован).

Для исправления проблемы можно явно указать возвращаемый тип для декоратора:

TFunc = TypeVar("TFunc", bound=Callable[..., Any])

- def handle_request_error(name: str):
+ def handle_request_error(name: str) -> Callable[[TFunc], TFunc]:
$ mypy test.py 
test.py:8: note: Revealed type is "tinkoff.invest.services.InstrumentsService"
test.py:9: note: Revealed type is "def () -> tinkoff.invest.schemas.AssetsResponse"
Success: no issues found in 1 source file

Также стоит заметить, что в pyright используется автоматический вывод типа для возвращаемого значения функции, поэтому в редакторах, которые его используют (например, VSCode) ошибки нет.

Воспроизведение

import os

from tinkoff.invest import Client                                                               

token = os.environ["INVEST_TOKEN"]                                                              

with Client(token) as client:                                                                   
     reveal_type(client.instruments) # Revealed type is "tinkoff.invest.services.InstrumentsService"                                                             
     reveal_type(client.instruments.get_assets) # Revealed type is "Any"

Tinkoff Invest Version

0.2.0-beta48

Python Version

3.8

OS

Linux

Логи

No response