#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