перегрузка mypy и контекстный менеджер

#python #mypy

Вопрос:

Я пытаюсь реализовать абстрактный и конкретный класс для открывателя файлов.

Однако с mypy (v0.910 на Python 3.8) я, похоже, не могу заставить печатать работать. Ниже приведен мой текущий код и сообщения об ошибках от mypy.

Я также попробовал несколько других «комбинаций», например @contextmanager , в абстрактном классе, но, похоже, просто не могу найти правильную алхимию.

 from abc import ABC, abstractmethod
from contextlib import contextmanager
from typing import ContextManager, Iterator, Literal, Union, overload


class Reader:
    """A file reader."""
    def __init__(self, path: str) -> None:
        self.path = path


class Writer:
    """A file writer."""
    def __init__(self, path: str) -> None:
        self.path = path


class FileOpenerAbstract(ABC):

    @overload
    @abstractmethod
    def open(self,
             path: str,
             mode: Literal['r']
    ) -> ContextManager[Reader]:
        ...

    @overload
    @abstractmethod
    def open(self,
             path: str,
             mode: Literal['x', 'w', 'a']
    ) -> ContextManager[Writer]:
        ...

    @abstractmethod
    def open(
        self,
        path: str,
        mode: Literal['r', 'x', 'w', 'a'] = 'r'
    ) -> Union[ContextManager[Reader], ContextManager[Writer]]:
        """Open an archive"""


class FileOpener(FileOpenerAbstract):

    @overload
    @contextmanager
    def open(self,
             path: str,
             mode: Literal['r']
    ) -> Iterator[Reader]:
        ...

    @overload
    @contextmanager
    def open(self,
             path: str,
             mode: Literal['x', 'w', 'a']
    ) -> Iterator[Writer]:
        ...

    @contextmanager
    def open(
        self,
        path: str,
        mode: Literal['r', 'x', 'w', 'a'] = 'r',
    ) -> Union[Iterator[Reader], Iterator[Writer]]:
        if mode == 'r':
            yield Reader(path)
        else:
            yield Writer(path)

 
 $ mypy mypy_test.py
mypy_test.py:47: error: Signature of "open" incompatible with supertype "FileOpenerAbstract"
mypy_test.py:63: error: Overloaded function implementation cannot produce return type of signature 1
mypy_test.py:63: error: Overloaded function implementation cannot produce return type of signature 2
mypy_test.py:64: error: Signature of "open" incompatible with supertype "FileOpenerAbstract"
Found 4 errors in 1 file (checked 1 source file)
 

есть какие-нибудь указания о том, как заставить это работать?

(обратите внимание, что автозаполнение с помощью пиланса VS Code, похоже, работает с этим кодом, поэтому я не уверен, является ли это ограничением mypy? Но опять же у пайлинта также есть проблемы с его интерпретацией)

Комментарии:

1. совпадают ли ваши типы возврата?

2. В текущей версии mypy есть ошибка, которая может повлиять на вас github.com/python/mypy/issues/11373