Типовые подсказки не оцениваются в декораторах

Данный

class A:
    pass

class B:
    pass

Если я определяю новый тип ACallback, который принимает экземпляр A

from typing import Callable

ACallback = Callable[[A], None]

И определите функцию, которая принимает экземпляр B

def b_callback(b: B):
    pass

Если я попытаюсь использовать b_callback там, где ожидается ACallback, я получу предупреждение о подсказке типа - как и ожидалось.

def test(callback: ACallback):
    pass


test(the_callback)  # <-- "Expected type '(A) -> None', got '(b: B) -> None` instead

Однако, если я создам декоратор, который принимает ACallback

def test2(callback: ACallback):
    def decorate(f):
        def new_f(*args, **kwargs):
            return f(*args, **kwargs)
        return new_f
    return decorate

И передать функцию, которая не соответствует

@test2(the_callback)  # <-- No type hint errors
def decorator_test():
    pass

Я не вижу никаких предупреждений о подсказках типа.

Вопрос. Отсутствие предупреждений о подсказках связано с...

  • Тип подсказки ошибки?
  • Ограничения подсказки типа Python?
  • Ограничения подсказки типа PyCharm?
  • Что-то другое?

person bphi    schedule 18.12.2018    source источник
comment
Что вы используете для анализа типов? Встроенная обработка PyCharm? mypy, похоже, отлично справляется с декораторами в моих тестах.   -  person user2357112 supports Monica    schedule 18.12.2018
comment
Это известная проблема.   -  person user2235698    schedule 25.12.2018


Ответы (1)


Кажется, это ошибка (или «отсутствие функции») в PyCharm. Я пробовал эту программу:

import typing

ACallback = typing.Callable[[int], None]

def test2(callback: ACallback):
    def decorate(f):
        def new_f(*args, **kwargs):
            return f(*args, **kwargs)
        return new_f
    return decorate


def foo(s: str):
    pass


test2(foo)


@test2(foo)
def bar():
    pass

с последней версией mypy, и результаты были

decorated.py:17: error: Argument 1 to "test2" has incompatible type "Callable[[str], Any]"; expected "Callable[[int], None]"
decorated.py:20: error: Argument 1 to "test2" has incompatible type "Callable[[str], Any]"; expected "Callable[[int], None]"

то есть оба использования привели к ошибке.


Если вы хотите использовать его с PyCharm, по крайней мере 2 разных плагина для интеграции PyCharm; один с именем mypy, а другой - Dropbox, то есть недоступно в репозитории JetBrains.

Я бы назвал DropBox одним из «официальных плагинов, одобренных mypy» в том смысле, что все ключи mypy/ Люди, подсказывающие Python, работают в Dropbox...

person Antti Haapala    schedule 18.12.2018
comment
Спасибо за ответ. Просто комментарий для будущих читателей о плагинах: mypy плагин не работает с последней версией PyCharm (183.4), плагин dropbox на самом деле не улучшает визуальные встроенные подсказки типов, просто обеспечивает более простой способ запуска mypy - person bphi; 18.12.2018