Как переопределить метод MagicMock __str__? - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь автоматически сгенерировать документацию для Readthedocs. Я высмеиваю некоторые зависимости как , которые они предлагают в FAQ , но из аннотаций типов функций я получаю некоторые части документации, которые выглядят как

Тип возвращаемого значения:

Что, конечно, недопустимо. Поэтому я переписал макет так:

from unittest.mock import Mock

class ModuleMock(Mock):
    def __init__(self, path='', *args, **kwargs):
        super().__init__(*args, *kwargs)
        self.path = path

    def __getattr__(self, name):
        return ModuleMock(path=self.path + '.' + name)

    def __repr__(self):
        return self.path

Чтобы я мог сделать

>>> x = ModuleMock('x')
>>> x
x
>>> x.y.z
x.y.z

Но с этим я получаю исключение

  ...
  File "<frozen importlib._bootstrap>", line 906, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1280, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1246, in _get_spec
TypeError: 'ModuleMock' object is not iterable

Когда я вместо этого пытаюсь наследовать от MagicMock, я получаю RecursionError.

Что я должен сделать, чтобы правильно изолировать зависимости для генерации документации и сделать эту документацию удобочитаемой?

1 Ответ

0 голосов
/ 03 января 2019

Это потому, что MagicMock использует атрибуты _mock_methods и _mock_unsafe, а Mock - нет (кажется). Я использую Python 2.7

Правильная реализация:

from mock import MagicMock

class ModuleMock(MagicMock):
    def __init__(self, path='', *args, **kwargs):
        super(ModuleMock, self).__init__(*args, **kwargs)
        self.path = path

    def __repr__(self):
        return self.path

    def __getattr__(self, name):
        #print(name)
        if name in ('_mock_methods', '_mock_unsafe'):
            return super(ModuleMock, self).__getattr__(name)

        return ModuleMock(self.path + "." + name)


if __name__ == '__main__':
    x = ModuleMock('x')
    print(x)
    print(x.y.z)

Итак, если вы напечатаете имя атрибута внутри __getattr__, вы увидите, что MagicMock имеет несколько вызовов.

Результат:

_mock_methods
_mock_methods
x
y
_mock_methods
z
_mock_methods
_mock_methods
x.y.z
...