_MockModule and _MockObject now display meaningful names in type annotations and superclass names

This commit is contained in:
Max
2018-09-07 15:14:01 +03:00
parent 9553453424
commit 61f9005b73
2 changed files with 44 additions and 11 deletions

View File

@@ -31,13 +31,18 @@ logger = logging.getLogger(__name__)
class _MockObject(object):
"""Used by autodoc_mock_imports."""
__display_name__ = '_MockObject'
def __new__(cls, *args, **kwargs):
# type: (Any, Any) -> Any
if len(args) == 3 and isinstance(args[1], tuple) and args[1][-1].__class__ is cls:
# subclassing MockObject
return type(args[0], (_MockObject,), args[2], **kwargs) # type: ignore
else:
return super(_MockObject, cls).__new__(cls)
if len(args) == 3 and isinstance(args[1], tuple):
superclass = args[1][-1].__class__
if superclass is cls:
# subclassing MockObject
return _make_subclass(args[0], superclass.__display_name__,
superclass=superclass, attributes=args[2])
return super(_MockObject, cls).__new__(cls)
def __init__(self, *args, **kwargs):
# type: (Any, Any) -> None
@@ -61,11 +66,11 @@ class _MockObject(object):
def __getitem__(self, key):
# type: (str) -> _MockObject
return self
return _make_subclass(key, self.__display_name__, self.__class__)()
def __getattr__(self, key):
# type: (str) -> _MockObject
return self
return _make_subclass(key, self.__display_name__, self.__class__)()
def __call__(self, *args, **kw):
# type: (Any, Any) -> Any
@@ -74,6 +79,17 @@ class _MockObject(object):
return args[0]
return self
def __repr__(self):
return self.__display_name__
def _make_subclass(name, module, superclass=_MockObject, attributes=None):
# type: (str, str, Any, dict) -> _MockObject
attrs = {'__module__': module, '__display_name__': module + '.' + name}
attrs.update(attributes or {})
return type(name, (superclass,), attrs)
class _MockModule(ModuleType):
"""Used by autodoc_mock_imports."""
@@ -88,9 +104,10 @@ class _MockModule(ModuleType):
def __getattr__(self, name):
# type: (str) -> _MockObject
o = _MockObject()
o.__module__ = self.__name__
return o
return _make_subclass(name, self.__name__)()
def __repr__(self):
return self.__name__
class _MockImporter(object):

View File

@@ -9,7 +9,7 @@
:license: BSD, see LICENSE for details.
"""
from sphinx.ext.autodoc.importer import _MockObject
from sphinx.ext.autodoc.importer import _MockObject, _MockModule
def test_MockObject():
@@ -21,6 +21,7 @@ def test_MockObject():
class SubClass(mock.SomeClass):
"""docstring of SubClass"""
def method(self):
return "string"
@@ -29,3 +30,18 @@ def test_MockObject():
assert isinstance(obj, SubClass)
assert obj.method() == "string"
assert isinstance(obj.other_method(), SubClass)
def test_MockModule():
mock = _MockModule('mocked_module', None)
assert isinstance(mock.some_attr, _MockObject)
assert isinstance(mock.some_method, _MockObject)
assert isinstance(mock.attr1.attr2, _MockObject)
assert isinstance(mock.attr1.attr2.meth(), _MockObject)
assert repr(mock.some_attr) == 'mocked_module.some_attr'
assert repr(mock.some_method) == 'mocked_module.some_method'
assert repr(mock.attr1.attr2) == 'mocked_module.attr1.attr2'
assert repr(mock.attr1.attr2.meth) == 'mocked_module.attr1.attr2.meth'
assert repr(mock) == 'mocked_module'