summaryrefslogtreecommitdiff
path: root/sphinx/util/docutils.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/docutils.py')
-rw-r--r--sphinx/util/docutils.py49
1 files changed, 45 insertions, 4 deletions
diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py
index ecc03f066..ae106c190 100644
--- a/sphinx/util/docutils.py
+++ b/sphinx/util/docutils.py
@@ -10,17 +10,33 @@
"""
from __future__ import absolute_import
+import re
from copy import copy
from contextlib import contextmanager
+
import docutils
+from docutils.utils import Reporter
from docutils.parsers.rst import directives, roles
+from sphinx.util import logging
+
+logger = logging.getLogger(__name__)
+report_re = re.compile('^(.+?:\d+): \((DEBUG|INFO|WARNING|ERROR|SEVERE)/(\d+)?\) (.+?)\n?$')
+
+
+if False:
+ # For type annotation
+ from typing import Any, Callable, Iterator, Tuple # NOQA
+ from docutils import nodes # NOQA
+ from sphinx.environment import BuildEnvironment # NOQA
+
__version_info__ = tuple(map(int, docutils.__version__.split('.')))
@contextmanager
def docutils_namespace():
+ # type: () -> Iterator[None]
"""Create namespace for reST parsers."""
try:
_directives = copy(directives._directives)
@@ -41,9 +57,10 @@ class sphinx_domains(object):
markup takes precedence.
"""
def __init__(self, env):
+ # type: (BuildEnvironment) -> None
self.env = env
- self.directive_func = None
- self.roles_func = None
+ self.directive_func = None # type: Callable
+ self.roles_func = None # type: Callable
def __enter__(self):
self.enable()
@@ -63,6 +80,7 @@ class sphinx_domains(object):
roles.role = self.role_func
def lookup_domain_element(self, type, name):
+ # type: (unicode, unicode) -> Tuple[Any, List]
"""Lookup a markup element (directive or role), given its name which can
be a full name (with domain).
"""
@@ -71,7 +89,7 @@ class sphinx_domains(object):
if ':' in name:
domain_name, name = name.split(':', 1)
if domain_name in self.env.domains:
- domain = self.env.domains[domain_name]
+ domain = self.env.get_domain(domain_name)
element = getattr(domain, type)(name)
if element is not None:
return element, []
@@ -84,20 +102,43 @@ class sphinx_domains(object):
return element, []
# always look in the std domain
- element = getattr(self.env.domains['std'], type)(name)
+ element = getattr(self.env.get_domain('std'), type)(name)
if element is not None:
return element, []
raise ElementLookupError
def lookup_directive(self, name, lang_module, document):
+ # type: (unicode, unicode, nodes.document) -> Tuple[Any, List]
try:
return self.lookup_domain_element('directive', name)
except ElementLookupError:
return self.directive_func(name, lang_module, document)
def lookup_role(self, name, lang_module, lineno, reporter):
+ # type: (unicode, unicode, int, Any) -> Tuple[Any, List]
try:
return self.lookup_domain_element('role', name)
except ElementLookupError:
return self.role_func(name, lang_module, lineno, reporter)
+
+
+class WarningStream(object):
+ def write(self, text):
+ matched = report_re.search(text)
+ if not matched:
+ logger.warning(text.rstrip("\r\n"))
+ else:
+ location, type, level, message = matched.groups()
+ logger.log(type, message, location=location)
+
+
+class LoggingReporter(Reporter):
+ def __init__(self, source, report_level, halt_level,
+ debug=False, error_handler='backslashreplace'):
+ stream = WarningStream()
+ Reporter.__init__(self, source, report_level, halt_level,
+ stream, debug, error_handler=error_handler)
+
+ def set_conditions(self, category, report_level, halt_level, debug=False):
+ Reporter.set_conditions(self, category, report_level, halt_level, debug=debug)