Merge pull request #5696 from tk0miya/refactor_docutils_manipulation

Refactor docutils manipulation
This commit is contained in:
Takeshi KOMIYA 2018-12-02 00:57:54 +09:00 committed by GitHub
commit 1b039614bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 14 deletions

View File

@ -21,7 +21,7 @@ from inspect import isclass
from io import StringIO
from os import path
from docutils.parsers.rst import Directive, directives, roles
from docutils.parsers.rst import Directive, roles
import sphinx
from sphinx import package_dir, locale
@ -651,15 +651,15 @@ class Sphinx:
"""
logger.debug('[app] adding directive: %r',
(name, obj, content, arguments, options))
if name in directives._directives and not override:
if not override and docutils.is_directive_registered(name):
logger.warning(__('directive %r is already registered, it will be overridden'),
name, type='app', subtype='add_directive')
if not isclass(obj) or not issubclass(obj, Directive):
directive = directive_helper(obj, content, arguments, **options)
directives.register_directive(name, directive)
docutils.register_directive(name, directive)
else:
directives.register_directive(name, obj)
docutils.register_directive(name, obj)
def add_role(self, name, role, override=False):
# type: (unicode, Any, bool) -> None
@ -674,10 +674,10 @@ class Sphinx:
Add *override* keyword.
"""
logger.debug('[app] adding role: %r', (name, role))
if name in roles._roles and not override:
if not override and docutils.is_role_registered(name):
logger.warning(__('role %r is already registered, it will be overridden'),
name, type='app', subtype='add_role')
roles.register_local_role(name, role)
docutils.register_role(name, role)
def add_generic_role(self, name, nodeclass, override=False):
# type: (unicode, Any, bool) -> None
@ -693,11 +693,11 @@ class Sphinx:
# Don't use ``roles.register_generic_role`` because it uses
# ``register_canonical_role``.
logger.debug('[app] adding generic role: %r', (name, nodeclass))
if name in roles._roles and not override:
if not override and docutils.is_role_registered(name):
logger.warning(__('role %r is already registered, it will be overridden'),
name, type='app', subtype='add_generic_role')
role = roles.GenericRole(name, nodeclass)
roles.register_local_role(name, role)
docutils.register_role(name, role)
def add_domain(self, domain, override=False):
# type: (Type[Domain], bool) -> None

View File

@ -16,6 +16,7 @@ from docutils import nodes
from docutils.parsers.rst import directives, roles
from sphinx import addnodes
from sphinx.util import docutils
from sphinx.util.docfields import DocFieldTransformer
from sphinx.util.docutils import SphinxDirective
@ -202,15 +203,13 @@ class DefaultRole(SphinxDirective):
def run(self):
# type: () -> List[nodes.Node]
if not self.arguments:
if '' in roles._roles:
# restore the "default" default role
del roles._roles['']
docutils.unregister_role('')
return []
role_name = self.arguments[0]
role, messages = roles.role(role_name, self.state_machine.language,
self.lineno, self.state.reporter)
if role:
roles._roles[''] = role
docutils.register_role('', role)
self.env.temp_data['default_role'] = role_name
else:
literal_block = nodes.literal_block(self.block_text, self.block_text)

View File

@ -67,6 +67,44 @@ def docutils_namespace():
additional_nodes.discard(node)
def is_directive_registered(name):
# type: (unicode) -> bool
"""Check the *name* directive is already registered."""
return name in directives._directives
def register_directive(name, directive):
# type: (unicode, Type[Directive]) -> None
"""Register a directive to docutils.
This modifies global state of docutils. So it is better to use this
inside ``docutils_namespace()`` to prevent side-effects.
"""
directives.register_directive(name, directive)
def is_role_registered(name):
# type: (unicode) -> bool
"""Check the *name* role is already registered."""
return name in roles._roles
def register_role(name, role):
# type: (unicode, RoleFunction) -> None
"""Register a role to docutils.
This modifies global state of docutils. So it is better to use this
inside ``docutils_namespace()`` to prevent side-effects.
"""
roles.register_local_role(name, role)
def unregister_role(name):
# type: (unicode) -> None
"""Unregister a role from docutils."""
roles._roles.pop(name, None)
def is_node_registered(node):
# type: (Type[nodes.Element]) -> bool
"""Check the *node* is already registered."""

View File

@ -18,6 +18,7 @@ from docutils.parsers.rst.languages import en as english
from docutils.utils import Reporter
from sphinx.locale import __
from sphinx.util import docutils
from sphinx.util import logging
if False:
@ -43,10 +44,10 @@ def default_role(docname, name):
dummy_reporter = Reporter('', 4, 4)
role_fn, _ = roles.role(name, english, 0, dummy_reporter)
if role_fn:
roles._roles[''] = role_fn
docutils.register_role('', role_fn)
else:
logger.warning(__('default role %s not found'), name, location=docname)
yield
roles._roles.pop('', None) # if a document has set a local default role
docutils.unregister_role('')