Аннотация типа MyPy для связанного метода? - PullRequest
1 голос
/ 24 сентября 2019

Я пишу несколько тестов для библиотеки, используя pytest.Я хочу попробовать несколько тестовых случаев для каждой функции, предоставляемой библиотекой, поэтому мне было удобно сгруппировать тесты для каждого метода в классе.Все функции, которые я хочу протестировать, имеют одинаковую сигнатуру и возвращают одинаковые результаты, поэтому я хотел бы использовать вспомогательный метод, определенный в суперклассе, чтобы сделать некоторые утверждения относительно результатов.Упрощенная версия будет работать так:

class MyTestCase:
    function_under_test: Optional[Callable[[str], Any]] = None

    def assert_something(self, input_str: str, expected_result: Any) -> None:
        if self.function_under_test is None:
            raise AssertionError(
                "To use this helper method, you must set the function_under_test"
                "class variable within your test class to the function to be called.")

        result = self.function_under_test.__func__(input_str)
        assert result == expected_result
        # various other assertions on result...


class FunctionATest(MyTestCase):
    function_under_test = mymodule.myfunction

    def test_whatever(self):
        self.assert_something("foo bar baz")

В assert_something. Необходимо вызвать __func__() для функции, поскольку назначение функции атрибуту класса делает ее связанным методом этого класса -в противном случае self будет передан в качестве первого аргумента функции внешней библиотеки, где это не имеет никакого смысла.

Этот код работает как задумано.Однако это приводит к ошибке MyPy:

"Callable[[str], Any]" has no attribute "__func__"

Исходя из моей аннотации, это правильно, что это не безопасная операция: произвольный Callable может не иметь атрибута __func__.Однако я не могу найти аннотацию типа, которая указала бы, что переменная function_under_test ссылается на метод и, следовательно, всегда будет иметь __func__.Я пропускаю один или есть другой способ настроить мои аннотации или доступы, чтобы заставить это работать с проверкой типов?

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

...