mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix sphinx.ext.autodoc
crashes if target code imports * from mock modules by autodoc_mock_imports
This commit is contained in:
parent
54dd5c5fd1
commit
e15216c568
2
CHANGES
2
CHANGES
@ -101,6 +101,8 @@ Bugs fixed
|
|||||||
* #2707: (latex) the column width is badly computed for tabular
|
* #2707: (latex) the column width is badly computed for tabular
|
||||||
* #2799: Sphinx installs roles and directives automatically on importing sphinx
|
* #2799: Sphinx installs roles and directives automatically on importing sphinx
|
||||||
module. Now Sphinx installs them on running application.
|
module. Now Sphinx installs them on running application.
|
||||||
|
* `sphinx.ext.autodoc` crashes if target code imports * from mock modules
|
||||||
|
by `autodoc_mock_imports`.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
|
@ -86,17 +86,21 @@ class Options(dict):
|
|||||||
|
|
||||||
class _MockModule(object):
|
class _MockModule(object):
|
||||||
"""Used by autodoc_mock_imports."""
|
"""Used by autodoc_mock_imports."""
|
||||||
|
__file__ = '/dev/null'
|
||||||
|
__path__ = '/dev/null'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
pass
|
self.__all__ = []
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
return _MockModule()
|
return _MockModule()
|
||||||
|
|
||||||
|
def _append_submodule(self, submod):
|
||||||
|
self.__all__.append(submod)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __getattr__(cls, name):
|
def __getattr__(cls, name):
|
||||||
if name in ('__file__', '__path__'):
|
if name[0] == name[0].upper():
|
||||||
return '/dev/null'
|
|
||||||
elif name[0] == name[0].upper():
|
|
||||||
# Not very good, we assume Uppercase names are classes...
|
# Not very good, we assume Uppercase names are classes...
|
||||||
mocktype = type(name, (), {})
|
mocktype = type(name, (), {})
|
||||||
mocktype.__module__ = __name__
|
mocktype.__module__ = __name__
|
||||||
@ -109,9 +113,12 @@ def mock_import(modname):
|
|||||||
if '.' in modname:
|
if '.' in modname:
|
||||||
pkg, _n, mods = modname.rpartition('.')
|
pkg, _n, mods = modname.rpartition('.')
|
||||||
mock_import(pkg)
|
mock_import(pkg)
|
||||||
|
if isinstance(sys.modules[pkg], _MockModule):
|
||||||
|
sys.modules[pkg]._append_submodule(mods)
|
||||||
|
|
||||||
|
if modname not in sys.modules:
|
||||||
mod = _MockModule()
|
mod = _MockModule()
|
||||||
sys.modules[modname] = mod
|
sys.modules[modname] = mod
|
||||||
return mod
|
|
||||||
|
|
||||||
|
|
||||||
ALL = object()
|
ALL = object()
|
||||||
@ -514,7 +521,7 @@ class Documenter(object):
|
|||||||
try:
|
try:
|
||||||
dbg('[autodoc] import %s', self.modname)
|
dbg('[autodoc] import %s', self.modname)
|
||||||
for modname in self.env.config.autodoc_mock_imports:
|
for modname in self.env.config.autodoc_mock_imports:
|
||||||
dbg('[autodoc] adding a mock module %s!', self.modname)
|
dbg('[autodoc] adding a mock module %s!', modname)
|
||||||
mock_import(modname)
|
mock_import(modname)
|
||||||
__import__(self.modname)
|
__import__(self.modname)
|
||||||
parent = None
|
parent = None
|
||||||
|
6
tests/roots/test-ext-autodoc/autodoc_dummy_module.py
Normal file
6
tests/roots/test-ext-autodoc/autodoc_dummy_module.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from dummy import *
|
||||||
|
|
||||||
|
|
||||||
|
def test():
|
||||||
|
"""Dummy function using dummy.*"""
|
||||||
|
dummy_function()
|
12
tests/roots/test-ext-autodoc/conf.py
Normal file
12
tests/roots/test-ext-autodoc/conf.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import sys, os
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
extensions = ['sphinx.ext.autodoc']
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
autodoc_mock_imports = [
|
||||||
|
'dummy'
|
||||||
|
]
|
3
tests/roots/test-ext-autodoc/contents.rst
Normal file
3
tests/roots/test-ext-autodoc/contents.rst
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
.. automodule:: autodoc_dummy_module
|
||||||
|
:members:
|
25
tests/test_ext_autodoc.py
Normal file
25
tests/test_ext_autodoc.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
test_autodoc
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Test the autodoc extension.
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pickle
|
||||||
|
from docutils import nodes
|
||||||
|
from sphinx import addnodes
|
||||||
|
from util import with_app
|
||||||
|
|
||||||
|
|
||||||
|
@with_app(buildername='dummy', testroot='ext-autodoc')
|
||||||
|
def test_autodoc(app, status, warning):
|
||||||
|
app.builder.build_all()
|
||||||
|
|
||||||
|
content = pickle.loads((app.doctreedir / 'contents.doctree').bytes())
|
||||||
|
assert isinstance(content[3], addnodes.desc)
|
||||||
|
assert content[3][0].astext() == 'autodoc_dummy_module.test'
|
||||||
|
assert content[3][1].astext() == 'Dummy function using dummy.*'
|
Loading…
Reference in New Issue
Block a user