diff options
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | sphinx/ext/autodoc/__init__.py | 33 | ||||
-rw-r--r-- | sphinx/ext/autodoc/directive.py | 14 | ||||
-rw-r--r-- | tests/py35/test_autodoc_py35.py | 25 | ||||
-rw-r--r-- | tests/test_autodoc.py | 38 |
5 files changed, 54 insertions, 58 deletions
@@ -14,6 +14,8 @@ Incompatible changes * #4226: apidoc: Generate new style makefile (make-mode) * #4274: sphinx-build returns 2 as an exit code on argument error * #4389: output directory will be created after loading extensions +* autodoc does not generate warnings messages to the generated document even if + :confval:`keep_warnings` is True. They are only emitted to stderr. Deprecated ---------- diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 386245d20..d9e82813d 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -328,8 +328,7 @@ class Documenter(object): explicit_modname, path, base, args, retann = \ py_ext_sig_re.match(self.name).groups() # type: ignore except AttributeError: - self.directive.warn('invalid signature for auto%s (%r)' % - (self.objtype, self.name)) + logger.warning('invalid signature for auto%s (%r)' % (self.objtype, self.name)) return False # support explicit module and class name separation via :: @@ -366,7 +365,7 @@ class Documenter(object): self.module, self.parent, self.object_name, self.object = ret return True except ImportError as exc: - self.directive.warn(exc.args[0]) + logger.warning(exc.args[0]) self.env.note_reread() return False @@ -426,8 +425,8 @@ class Documenter(object): try: args = self.format_args() except Exception as err: - self.directive.warn('error while formatting arguments for ' - '%s: %s' % (self.fullname, err)) + logger.warning('error while formatting arguments for %s: %s' % + (self.fullname, err)) args = None retann = self.retann @@ -549,8 +548,8 @@ class Documenter(object): if name in members: selected.append((name, members[name].value)) else: - self.directive.warn('missing attribute %s in object %s' % - (name, self.fullname)) + logger.warning('missing attribute %s in object %s' % + (name, self.fullname)) return False, sorted(selected) elif self.options.inherited_members: return False, sorted((m.name, m.value) for m in itervalues(members)) @@ -719,11 +718,11 @@ class Documenter(object): """ if not self.parse_name(): # need a module to import - self.directive.warn( + logger.warning( 'don\'t know which module to import for autodocumenting ' '%r (try placing a "module" or "currentmodule" directive ' - 'in the document, or giving an explicit module name)' - % self.name) + 'in the document, or giving an explicit module name)' % + self.name) return # now, import the module and get object to document @@ -809,15 +808,15 @@ class ModuleDocumenter(Documenter): def resolve_name(self, modname, parents, path, base): # type: (str, Any, str, Any) -> Tuple[str, List[unicode]] if modname is not None: - self.directive.warn('"::" in automodule name doesn\'t make sense') + logger.warning('"::" in automodule name doesn\'t make sense') return (path or '') + base, [] def parse_name(self): # type: () -> bool ret = Documenter.parse_name(self) if self.args or self.retann: - self.directive.warn('signature arguments or return annotation ' - 'given for automodule %s' % self.fullname) + logger.warning('signature arguments or return annotation ' + 'given for automodule %s' % self.fullname) return ret def add_directive_header(self, sig): @@ -849,7 +848,7 @@ class ModuleDocumenter(Documenter): # Sometimes __all__ is broken... if not isinstance(memberlist, (list, tuple)) or not \ all(isinstance(entry, string_types) for entry in memberlist): - self.directive.warn( + logger.warning( '__all__ should be a list of strings, not %r ' '(in module %s) -- ignoring __all__' % (memberlist, self.fullname)) @@ -862,10 +861,10 @@ class ModuleDocumenter(Documenter): try: ret.append((mname, safe_getattr(self.object, mname))) except AttributeError: - self.directive.warn( + logger.warning( 'missing attribute mentioned in :members: or __all__: ' - 'module %s, attribute %s' % ( - safe_getattr(self.object, '__name__', '???'), mname)) + 'module %s, attribute %s' % + (safe_getattr(self.object, '__name__', '???'), mname)) return False, ret diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index 5d17481eb..6de6e5517 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -63,12 +63,11 @@ class DocumenterBridge(object): self.genopt = options self.lineno = lineno self.filename_set = set() # type: Set[unicode] - self.warnings = [] # type: List[nodes.Node] self.result = ViewList() def warn(self, msg): # type: (unicode) -> None - self.warnings.append(self.reporter.warning(msg, line=self.lineno)) + logger.warning(msg, line=self.lineno) def process_documenter_options(documenter, config, options): @@ -134,17 +133,16 @@ class AutodocDirective(Directive): documenter_options = process_documenter_options(doccls, env.config, self.options) except (KeyError, ValueError, TypeError) as exc: # an option is either unknown or has a wrong type - msg = reporter.error('An option to %s is either unknown or ' - 'has an invalid value: %s' % (self.name, exc), - line=lineno) - return [msg] + logger.error('An option to %s is either unknown or has an invalid value: %s' % + (self.name, exc), line=lineno) + return [] # generate the output params = DocumenterBridge(env, reporter, documenter_options, lineno) documenter = doccls(params, self.arguments[0]) documenter.generate(more_content=self.content) if not params.result: - return params.warnings + return [] logger.debug('[autodoc] output:\n%s', '\n'.join(params.result)) @@ -154,4 +152,4 @@ class AutodocDirective(Directive): self.state.document.settings.record_dependencies.add(fn) result = parse_generated_content(self.state, params.result, documenter) - return params.warnings + result + return result diff --git a/tests/py35/test_autodoc_py35.py b/tests/py35/test_autodoc_py35.py index d13e50d9c..439ebd67a 100644 --- a/tests/py35/test_autodoc_py35.py +++ b/tests/py35/test_autodoc_py35.py @@ -21,6 +21,7 @@ from docutils.statemachine import ViewList from sphinx.ext.autodoc import AutoDirective, add_documenter, \ ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL +from sphinx.util import logging app = None @@ -30,7 +31,7 @@ def setup_module(rootdir, sphinx_test_tempdir): global app srcdir = sphinx_test_tempdir / 'autodoc-root' if not srcdir.exists(): - (rootdir/'test-root').copytree(srcdir) + (rootdir / 'test-root').copytree(srcdir) app = SphinxTestApp(srcdir=srcdir) app.builder.env.app = app app.builder.env.temp_data['docname'] = 'dummy' @@ -47,7 +48,7 @@ directive = options = None @pytest.fixture def setup_test(): global options, directive - global processed_docstrings, processed_signatures, _warnings + global processed_docstrings, processed_signatures options = Struct( inherited_members = False, @@ -70,24 +71,17 @@ def setup_test(): env = app.builder.env, genopt = options, result = ViewList(), - warn = warnfunc, filename_set = set(), ) processed_docstrings = [] processed_signatures = [] - _warnings = [] -_warnings = [] processed_docstrings = [] processed_signatures = [] -def warnfunc(msg): - _warnings.append(msg) - - def process_docstring(app, what, name, obj, options, lines): processed_docstrings.append((what, name)) if name == 'bar': @@ -111,20 +105,21 @@ def skip_member(app, what, name, obj, skip, options): @pytest.mark.usefixtures('setup_test') def test_generate(): + logging.setup(app, app._status, app._warning) + def assert_warns(warn_str, objtype, name, **kw): inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert len(directive.result) == 0, directive.result - assert len(_warnings) == 1, _warnings - assert warn_str in _warnings[0], _warnings - del _warnings[:] + assert warn_str in app._warning.getvalue() + app._warning.truncate(0) def assert_works(objtype, name, **kw): inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert directive.result # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' del directive.result[:] def assert_processes(items, objtype, name, **kw): @@ -137,7 +132,7 @@ def test_generate(): inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' assert item in directive.result del directive.result[:] @@ -145,7 +140,7 @@ def test_generate(): inst = app.registry.documenters[objtype](directive, name) inst.options.member_order = member_order inst.generate(**kw) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' items = list(reversed(items)) lineiter = iter(directive.result) # for line in directive.result: diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 1abd01b5f..d9c94bc0d 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -20,6 +20,7 @@ from docutils.statemachine import ViewList from sphinx.ext.autodoc import AutoDirective, add_documenter, \ ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL +from sphinx.util import logging app = None @@ -51,7 +52,7 @@ directive = options = None @pytest.fixture def setup_test(): global options, directive - global processed_docstrings, processed_signatures, _warnings + global processed_docstrings, processed_signatures options = Struct( inherited_members = False, @@ -75,28 +76,24 @@ def setup_test(): env = app.builder.env, genopt = options, result = ViewList(), - warn = warnfunc, filename_set = set(), ) processed_docstrings = [] processed_signatures = [] - _warnings = [] + + app._status.truncate(0) + app._warning.truncate(0) yield AutoDirective._special_attrgetters.clear() -_warnings = [] processed_docstrings = [] processed_signatures = [] -def warnfunc(msg): - _warnings.append(msg) - - def process_docstring(app, what, name, obj, options, lines): processed_docstrings.append((what, name)) if name == 'bar': @@ -120,6 +117,8 @@ def skip_member(app, what, name, obj, skip, options): @pytest.mark.usefixtures('setup_test') def test_parse_name(): + logging.setup(app, app._status, app._warning) + def verify(objtype, name, result): inst = app.registry.documenters[objtype](directive, name) assert inst.parse_name() @@ -129,8 +128,7 @@ def test_parse_name(): verify('module', 'test_autodoc', ('test_autodoc', [], None, None)) verify('module', 'test.test_autodoc', ('test.test_autodoc', [], None, None)) verify('module', 'test(arg)', ('test', [], 'arg', None)) - assert 'signature arguments' in _warnings[0] - del _warnings[:] + assert 'signature arguments' in app._warning.getvalue() # for functions/classes verify('function', 'test_autodoc.raises', @@ -246,7 +244,6 @@ def test_format_signature(): # test exception handling (exception is caught and args is '') directive.env.config.autodoc_docstring_signature = False assert formatsig('function', 'int', int, None, None) == '' - del _warnings[:] # test processing by event handler assert formatsig('method', 'bar', H.foo1, None, None) == '42' @@ -540,6 +537,8 @@ def test_docstring_property_processing(): @pytest.mark.usefixtures('setup_test') def test_new_documenter(): + logging.setup(app, app._status, app._warning) + class MyDocumenter(ModuleLevelDocumenter): objtype = 'integer' directivetype = 'data' @@ -555,10 +554,11 @@ def test_new_documenter(): add_documenter(MyDocumenter) def assert_result_contains(item, objtype, name, **kw): + app._warning.truncate(0) inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' assert item in directive.result del directive.result[:] @@ -602,20 +602,22 @@ def test_attrgetter_using(): @pytest.mark.usefixtures('setup_test') def test_generate(): + logging.setup(app, app._status, app._warning) + def assert_warns(warn_str, objtype, name, **kw): inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert len(directive.result) == 0, directive.result - assert len(_warnings) == 1, _warnings - assert warn_str in _warnings[0], _warnings - del _warnings[:] + + assert warn_str in app._warning.getvalue() + app._warning.truncate(0) def assert_works(objtype, name, **kw): inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert directive.result # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' del directive.result[:] def assert_processes(items, objtype, name, **kw): @@ -628,7 +630,7 @@ def test_generate(): inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' assert item in directive.result del directive.result[:] @@ -636,7 +638,7 @@ def test_generate(): inst = app.registry.documenters[objtype](directive, name) inst.options.member_order = member_order inst.generate(**kw) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' items = list(reversed(items)) lineiter = iter(directive.result) # for line in directive.result: |