Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to redefine MagicMock __str__ method?

I'm trying to autogenerate documentation for Readthedocs. I mock some dependencies as they suggest in FAQ, but from type annotations of functions I get some parts of documentation to look like

Return type: <MagicMock id=‘140517266915680’>

Which is of course unacceptable. So I rewritten mock like this:

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

So I could do

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

But with this I get exception

  ...
  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

When I instead try to inherit from MagicMock, I get RecursionError.

What should I do to properly isolate dependencies for documentation generation, and make that documentation readable?

like image 220
Bunyk Avatar asked Sep 14 '25 13:09

Bunyk


1 Answers

It because MagicMock uses _mock_methods and _mock_unsafe attributes, but Mock doesn't (seems). I use Python 2.7

Correct implementation:

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)

So if you print attribute name inside __getattr__, you can see MagicMock has several calls.

Result:

_mock_methods
_mock_methods
x
y
_mock_methods
z
_mock_methods
_mock_methods
x.y.z
like image 54
Valijon Avatar answered Sep 16 '25 06:09

Valijon