Печатание в классе dict mixin с Mypy - PullRequest
2 голосов
/ 12 апреля 2019

Я пытаюсь написать небольшой класс mixin, чтобы несколько соединить типы Set и MutableMapping: я хочу, чтобы у типов отображения была возможность получать некоторые объекты (байты), хэшировать их и хранить их, чтобы они были доступны для этогохэш.

Вот рабочая версия смешивания этого класса со стандартным dict:

from hashlib import blake2b

class HashingMixin:
    def add(self, content):
        digest = blake2b(content).hexdigest()
        self[digest] = content

class HashingDict(dict, HashingMixin):
    pass

Однако я не могу понять, как добавить аннотации типов.

Из https://github.com/python/mypy/issues/1996 кажется, что миксин должен подкласс abc.ABC и abc.abstractmethod - определить все методы, которые он ожидает вызвать, так что вот мой выстрел:

import abc
from hashlib import blake2b
from typing import Dict

class HashingMixin(abc.ABC):
    def add(self, content: bytes) -> None:
        digest = blake2b(content).hexdigest()
        self[digest] = content

    @abc.abstractmethod
    def __getitem__(self, key: str) -> bytes:
        raise NotImplementedError

    @abc.abstractmethod
    def __setitem__(self, key: str, content: bytes) -> None:
        raise NotImplementedError


class HashingDict(Dict[str, bytes], HashingMixin):
    pass

Тогда Mypy жалуется наHashingDict определение:

error: Definition of "__getitem__" in base class "dict" is incompatible with definition in base class "HashingMixin"
error: Definition of "__setitem__" in base class "dict" is incompatible with definition in base class "HashingMixin"
error: Definition of "__setitem__" in base class "MutableMapping" is incompatible with definition in base class "HashingMixin"
error: Definition of "__getitem__" in base class "Mapping" is incompatible with definition in base class "HashingMixin"

Выявление типов с помощью:

reveal_type(HashingMixin.__getitem__)
reveal_type(HashingDict.__getitem__)

выход:

error: Revealed type is 'def (coup.content.HashingMixin, builtins.str) -> builtins.bytes'
error: Revealed type is 'def (builtins.dict[_KT`1, _VT`2], _KT`1) -> _VT`2'

Я не знаю, что не так: (

1 Ответ

1 голос
/ 12 апреля 2019

Это похоже на ошибку в mypy - см. this TODO в коде, который mypy использует для анализа MRO классов с использованием множественного наследования.Короче говоря, mypy неправильно завершает игнорирование того, что вы параметризовали Dict с конкретными значениями, и вместо этого анализирует код, как если бы вы использовали Dict.

Я считаю, что https://github.com/python/mypy/issues/5973вероятно, самая важная проблема в системе отслеживания проблем: основная причина та же.

Пока эта ошибка не устранена, вы можете подавить ошибки, которые mypy генерирует в этой строке, добавив # type: ignore к любой строкеошибки.Так что в вашем случае вы могли бы сделать следующее:

import abc
from hashlib import blake2b
from typing import Dict

class HashingMixin(abc.ABC):
    def add(self, content: bytes) -> None:
        digest = blake2b(content).hexdigest()
        self[digest] = content

    @abc.abstractmethod
    def __getitem__(self, key: str) -> bytes:
        raise NotImplementedError

    @abc.abstractmethod
    def __setitem__(self, key: str, content: bytes) -> None:
        raise NotImplementedError


class HashingDict(Dict[str, bytes], HashingMixin):  # type: ignore
    pass

Если вы решите воспользоваться этим подходом, я также рекомендую оставить дополнительный комментарий, документирующий, почему вы подавляете эти ошибки и запускаете mypy с * 1015.* flag.

Первый предназначен для будущих читателей вашего кода;последний выдаст сообщение mypy о предупреждении всякий раз, когда обнаружит # type: ignore, который фактически не подавляет никаких ошибок и поэтому может быть безопасно удален.

(И, конечно, вы всегда можете попытаться внести исправлениесами!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...