diff options
Diffstat (limited to 'sphinx/util/docutils.py')
-rw-r--r-- | sphinx/util/docutils.py | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 38f275824..949bec3b4 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -12,6 +12,7 @@ from __future__ import absolute_import import re import types +import warnings from contextlib import contextmanager from copy import copy from distutils.version import LooseVersion @@ -23,6 +24,7 @@ from docutils.parsers.rst import directives, roles, convert_directive_function from docutils.statemachine import StateMachine from docutils.utils import Reporter +from sphinx.deprecation import RemovedInSphinx30Warning from sphinx.errors import ExtensionError from sphinx.locale import __ from sphinx.util import logging @@ -32,13 +34,14 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/( if False: # For type annotation - from typing import Any, Callable, Generator, Iterator, List, Tuple # NOQA + from typing import Any, Callable, Generator, Iterator, List, Set, Tuple # NOQA from docutils.statemachine import State, ViewList # NOQA from sphinx.environment import BuildEnvironment # NOQA from sphinx.io import SphinxFileInput # NOQA __version_info__ = tuple(LooseVersion(docutils.__version__).version) +additional_nodes = set() # type: Set[nodes.Node] @contextmanager @@ -54,6 +57,41 @@ def docutils_namespace(): directives._directives = _directives roles._roles = _roles + for node in list(additional_nodes): + unregister_node(node) + additional_nodes.discard(node) + + +def is_node_registered(node): + # type: (nodes.Node) -> bool + """Check the *node* is already registered.""" + return hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__) + + +def register_node(node): + # type: (nodes.Node) -> None + """Register a node to docutils. + + This modifies global state of some visitors. So it is better to use this + inside ``docutils_namespace()`` to prevent side-effects. + """ + if not hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__): + nodes._add_node_class_names([node.__name__]) + additional_nodes.add(node) + + +def unregister_node(node): + # type: (nodes.Node) -> None + """Unregister a node from docutils. + + This is inverse of ``nodes._add_nodes_class_names()``. + """ + if hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__): + delattr(nodes.GenericNodeVisitor, "visit_" + node.__name__) + delattr(nodes.GenericNodeVisitor, "depart_" + node.__name__) + delattr(nodes.SparseNodeVisitor, 'visit_' + node.__name__) + delattr(nodes.SparseNodeVisitor, 'depart_' + node.__name__) + def patched_get_language(language_code, reporter=None): # type: (unicode, Reporter) -> Any @@ -200,6 +238,10 @@ def is_html5_writer_available(): def directive_helper(obj, has_content=None, argument_spec=None, **option_spec): # type: (Any, bool, Tuple[int, int, bool], Any) -> Any + warnings.warn('function based directive support is now deprecated. ' + 'Use class based directive instead.', + RemovedInSphinx30Warning) + if isinstance(obj, (types.FunctionType, types.MethodType)): obj.content = has_content # type: ignore obj.arguments = argument_spec or (0, 0, False) # type: ignore |