mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Migrate to py3 style type annotation: sphinx.ext.autodoc.mock
This commit is contained in:
parent
d057c5e6d7
commit
e67f5db296
@ -15,14 +15,11 @@ import warnings
|
|||||||
from importlib.abc import Loader, MetaPathFinder
|
from importlib.abc import Loader, MetaPathFinder
|
||||||
from importlib.machinery import ModuleSpec
|
from importlib.machinery import ModuleSpec
|
||||||
from types import FunctionType, MethodType, ModuleType
|
from types import FunctionType, MethodType, ModuleType
|
||||||
|
from typing import Any, Generator, Iterator, List, Sequence, Tuple, Union
|
||||||
|
|
||||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
|
||||||
if False:
|
|
||||||
# For type annotation
|
|
||||||
from typing import Any, Generator, Iterator, List, Sequence, Tuple, Union # NOQA
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -31,8 +28,7 @@ class _MockObject:
|
|||||||
|
|
||||||
__display_name__ = '_MockObject'
|
__display_name__ = '_MockObject'
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs) -> Any:
|
||||||
# type: (Any, Any) -> Any
|
|
||||||
if len(args) == 3 and isinstance(args[1], tuple):
|
if len(args) == 3 and isinstance(args[1], tuple):
|
||||||
superclass = args[1][-1].__class__
|
superclass = args[1][-1].__class__
|
||||||
if superclass is cls:
|
if superclass is cls:
|
||||||
@ -42,48 +38,39 @@ class _MockObject:
|
|||||||
|
|
||||||
return super().__new__(cls)
|
return super().__new__(cls)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
# type: (Any, Any) -> None
|
|
||||||
self.__qualname__ = ''
|
self.__qualname__ = ''
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self) -> int:
|
||||||
# type: () -> int
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key: str) -> bool:
|
||||||
# type: (str) -> bool
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self) -> Iterator:
|
||||||
# type: () -> Iterator
|
|
||||||
return iter([])
|
return iter([])
|
||||||
|
|
||||||
def __mro_entries__(self, bases):
|
def __mro_entries__(self, bases: Tuple) -> Tuple:
|
||||||
# type: (Tuple) -> Tuple
|
|
||||||
return (self.__class__,)
|
return (self.__class__,)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key: str) -> "_MockObject":
|
||||||
# type: (str) -> _MockObject
|
|
||||||
return _make_subclass(key, self.__display_name__, self.__class__)()
|
return _make_subclass(key, self.__display_name__, self.__class__)()
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key: str) -> "_MockObject":
|
||||||
# type: (str) -> _MockObject
|
|
||||||
return _make_subclass(key, self.__display_name__, self.__class__)()
|
return _make_subclass(key, self.__display_name__, self.__class__)()
|
||||||
|
|
||||||
def __call__(self, *args, **kw):
|
def __call__(self, *args, **kw) -> Any:
|
||||||
# type: (Any, Any) -> Any
|
|
||||||
if args and type(args[0]) in [FunctionType, MethodType]:
|
if args and type(args[0]) in [FunctionType, MethodType]:
|
||||||
# Appears to be a decorator, pass through unchanged
|
# Appears to be a decorator, pass through unchanged
|
||||||
return args[0]
|
return args[0]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
# type: () -> str
|
|
||||||
return self.__display_name__
|
return self.__display_name__
|
||||||
|
|
||||||
|
|
||||||
def _make_subclass(name, module, superclass=_MockObject, attributes=None):
|
def _make_subclass(name: str, module: str, superclass: Any = _MockObject,
|
||||||
# type: (str, str, Any, dict) -> Any
|
attributes: Any = None) -> Any:
|
||||||
attrs = {'__module__': module, '__display_name__': module + '.' + name}
|
attrs = {'__module__': module, '__display_name__': module + '.' + name}
|
||||||
attrs.update(attributes or {})
|
attrs.update(attributes or {})
|
||||||
|
|
||||||
@ -94,8 +81,7 @@ class _MockModule(ModuleType):
|
|||||||
"""Used by autodoc_mock_imports."""
|
"""Used by autodoc_mock_imports."""
|
||||||
__file__ = os.devnull
|
__file__ = os.devnull
|
||||||
|
|
||||||
def __init__(self, name, loader=None):
|
def __init__(self, name: str, loader: "_MockImporter" = None) -> None:
|
||||||
# type: (str, _MockImporter) -> None
|
|
||||||
super().__init__(name)
|
super().__init__(name)
|
||||||
self.__all__ = [] # type: List[str]
|
self.__all__ = [] # type: List[str]
|
||||||
self.__path__ = [] # type: List[str]
|
self.__path__ = [] # type: List[str]
|
||||||
@ -104,18 +90,15 @@ class _MockModule(ModuleType):
|
|||||||
warnings.warn('The loader argument for _MockModule is deprecated.',
|
warnings.warn('The loader argument for _MockModule is deprecated.',
|
||||||
RemovedInSphinx30Warning)
|
RemovedInSphinx30Warning)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name: str) -> _MockObject:
|
||||||
# type: (str) -> _MockObject
|
|
||||||
return _make_subclass(name, self.__name__)()
|
return _make_subclass(name, self.__name__)()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
# type: () -> str
|
|
||||||
return self.__name__
|
return self.__name__
|
||||||
|
|
||||||
|
|
||||||
class _MockImporter(MetaPathFinder):
|
class _MockImporter(MetaPathFinder):
|
||||||
def __init__(self, names):
|
def __init__(self, names: List[str]) -> None:
|
||||||
# type: (List[str]) -> None
|
|
||||||
self.names = names
|
self.names = names
|
||||||
self.mocked_modules = [] # type: List[str]
|
self.mocked_modules = [] # type: List[str]
|
||||||
# enable hook by adding itself to meta_path
|
# enable hook by adding itself to meta_path
|
||||||
@ -124,8 +107,7 @@ class _MockImporter(MetaPathFinder):
|
|||||||
warnings.warn('_MockImporter is now deprecated.',
|
warnings.warn('_MockImporter is now deprecated.',
|
||||||
RemovedInSphinx30Warning)
|
RemovedInSphinx30Warning)
|
||||||
|
|
||||||
def disable(self):
|
def disable(self) -> None:
|
||||||
# type: () -> None
|
|
||||||
# remove `self` from `sys.meta_path` to disable import hook
|
# remove `self` from `sys.meta_path` to disable import hook
|
||||||
sys.meta_path = [i for i in sys.meta_path if i is not self]
|
sys.meta_path = [i for i in sys.meta_path if i is not self]
|
||||||
# remove mocked modules from sys.modules to avoid side effects after
|
# remove mocked modules from sys.modules to avoid side effects after
|
||||||
@ -134,16 +116,14 @@ class _MockImporter(MetaPathFinder):
|
|||||||
if m in sys.modules:
|
if m in sys.modules:
|
||||||
del sys.modules[m]
|
del sys.modules[m]
|
||||||
|
|
||||||
def find_module(self, name, path=None):
|
def find_module(self, name: str, path: Sequence[Union[bytes, str]] = None) -> Any:
|
||||||
# type: (str, Sequence[Union[bytes, str]]) -> Any
|
|
||||||
# check if name is (or is a descendant of) one of our base_packages
|
# check if name is (or is a descendant of) one of our base_packages
|
||||||
for n in self.names:
|
for n in self.names:
|
||||||
if n == name or name.startswith(n + '.'):
|
if n == name or name.startswith(n + '.'):
|
||||||
return self
|
return self
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def load_module(self, name):
|
def load_module(self, name: str) -> ModuleType:
|
||||||
# type: (str) -> ModuleType
|
|
||||||
if name in sys.modules:
|
if name in sys.modules:
|
||||||
# module has already been imported, return it
|
# module has already been imported, return it
|
||||||
return sys.modules[name]
|
return sys.modules[name]
|
||||||
@ -157,34 +137,30 @@ class _MockImporter(MetaPathFinder):
|
|||||||
|
|
||||||
class MockLoader(Loader):
|
class MockLoader(Loader):
|
||||||
"""A loader for mocking."""
|
"""A loader for mocking."""
|
||||||
def __init__(self, finder):
|
def __init__(self, finder: "MockFinder") -> None:
|
||||||
# type: (MockFinder) -> None
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.finder = finder
|
self.finder = finder
|
||||||
|
|
||||||
def create_module(self, spec):
|
def create_module(self, spec: ModuleSpec) -> ModuleType:
|
||||||
# type: (ModuleSpec) -> ModuleType
|
|
||||||
logger.debug('[autodoc] adding a mock module as %s!', spec.name)
|
logger.debug('[autodoc] adding a mock module as %s!', spec.name)
|
||||||
self.finder.mocked_modules.append(spec.name)
|
self.finder.mocked_modules.append(spec.name)
|
||||||
return _MockModule(spec.name)
|
return _MockModule(spec.name)
|
||||||
|
|
||||||
def exec_module(self, module):
|
def exec_module(self, module: ModuleType) -> None:
|
||||||
# type: (ModuleType) -> None
|
|
||||||
pass # nothing to do
|
pass # nothing to do
|
||||||
|
|
||||||
|
|
||||||
class MockFinder(MetaPathFinder):
|
class MockFinder(MetaPathFinder):
|
||||||
"""A finder for mocking."""
|
"""A finder for mocking."""
|
||||||
|
|
||||||
def __init__(self, modnames):
|
def __init__(self, modnames: List[str]) -> None:
|
||||||
# type: (List[str]) -> None
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.modnames = modnames
|
self.modnames = modnames
|
||||||
self.loader = MockLoader(self)
|
self.loader = MockLoader(self)
|
||||||
self.mocked_modules = [] # type: List[str]
|
self.mocked_modules = [] # type: List[str]
|
||||||
|
|
||||||
def find_spec(self, fullname, path, target=None):
|
def find_spec(self, fullname: str, path: Sequence[Union[bytes, str]],
|
||||||
# type: (str, Sequence[Union[bytes, str]], ModuleType) -> ModuleSpec
|
target: ModuleType = None) -> ModuleSpec:
|
||||||
for modname in self.modnames:
|
for modname in self.modnames:
|
||||||
# check if fullname is (or is a descendant of) one of our targets
|
# check if fullname is (or is a descendant of) one of our targets
|
||||||
if modname == fullname or fullname.startswith(modname + '.'):
|
if modname == fullname or fullname.startswith(modname + '.'):
|
||||||
@ -192,16 +168,14 @@ class MockFinder(MetaPathFinder):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def invalidate_caches(self):
|
def invalidate_caches(self) -> None:
|
||||||
# type: () -> None
|
|
||||||
"""Invalidate mocked modules on sys.modules."""
|
"""Invalidate mocked modules on sys.modules."""
|
||||||
for modname in self.mocked_modules:
|
for modname in self.mocked_modules:
|
||||||
sys.modules.pop(modname, None)
|
sys.modules.pop(modname, None)
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def mock(modnames):
|
def mock(modnames: List[str]) -> Generator[None, None, None]:
|
||||||
# type: (List[str]) -> Generator[None, None, None]
|
|
||||||
"""Insert mock modules during context::
|
"""Insert mock modules during context::
|
||||||
|
|
||||||
with mock(['target.module.name']):
|
with mock(['target.module.name']):
|
||||||
|
Loading…
Reference in New Issue
Block a user