Closes #1962: when adding directives, roles or nodes from an extension, warn if such

an element is already present (built-in or added by another extension).
This commit is contained in:
Georg Brandl 2015-07-21 12:42:13 +02:00
parent cb2f35e229
commit cdf0f8253c
2 changed files with 25 additions and 2 deletions

View File

@ -7,12 +7,15 @@ Incompatible changes
Features added Features added
-------------- --------------
* #1962: when adding directives, roles or nodes from an extension, warn if such
an element is already present (built-in or added by another extension).
Bugs fixed Bugs fixed
---------- ----------
* #1789: ``:pyobject:`` option of ``literalinclude`` directive includes following * #1789: ``:pyobject:`` option of ``literalinclude`` directive includes following
lines after class definitions lines after class definitions.
* #1790: ``literalinclude`` strips empty lines at the head and tail * #1790: ``literalinclude`` strips empty lines at the head and tail.
* #1913: C++, fix assert bug for enumerators in next-to-global and global scope. * #1913: C++, fix assert bug for enumerators in next-to-global and global scope.
Documentation Documentation

View File

@ -78,6 +78,7 @@ class Sphinx(object):
self._extensions = {} self._extensions = {}
self._extension_metadata = {} self._extension_metadata = {}
self._listeners = {} self._listeners = {}
self._setting_up_extension = '?'
self.domains = BUILTIN_DOMAINS.copy() self.domains = BUILTIN_DOMAINS.copy()
self.buildername = buildername self.buildername = buildername
self.builderclasses = BUILTIN_BUILDERS.copy() self.builderclasses = BUILTIN_BUILDERS.copy()
@ -144,6 +145,7 @@ class Sphinx(object):
self.setup_extension(extension) self.setup_extension(extension)
# the config file itself can be an extension # the config file itself can be an extension
if self.config.setup: if self.config.setup:
self._setting_up_extension = 'conf.py'
# py31 doesn't have 'callable' function for below check # py31 doesn't have 'callable' function for below check
if hasattr(self.config.setup, '__call__'): if hasattr(self.config.setup, '__call__'):
self.config.setup(self) self.config.setup(self)
@ -426,6 +428,7 @@ class Sphinx(object):
self.debug('[app] setting up extension: %r', extension) self.debug('[app] setting up extension: %r', extension)
if extension in self._extensions: if extension in self._extensions:
return return
self._setting_up_extension = extension
try: try:
mod = __import__(extension, None, None, ['setup']) mod = __import__(extension, None, None, ['setup'])
except ImportError as err: except ImportError as err:
@ -460,6 +463,7 @@ class Sphinx(object):
ext_meta = {'version': 'unknown version'} ext_meta = {'version': 'unknown version'}
self._extensions[extension] = mod self._extensions[extension] = mod
self._extension_metadata[extension] = ext_meta self._extension_metadata[extension] = ext_meta
self._setting_up_extension = '?'
def require_sphinx(self, version): def require_sphinx(self, version):
# check the Sphinx version if requested # check the Sphinx version if requested
@ -550,6 +554,10 @@ class Sphinx(object):
def add_node(self, node, **kwds): def add_node(self, node, **kwds):
self.debug('[app] adding node: %r', (node, kwds)) self.debug('[app] adding node: %r', (node, kwds))
if hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__):
self.warn('while setting up extension %s: node class %r is '
'already registered, its visitors will be overridden' %
(self._setting_up_extension, node.__name__))
nodes._add_node_class_names([node.__name__]) nodes._add_node_class_names([node.__name__])
for key, val in iteritems(kwds): for key, val in iteritems(kwds):
try: try:
@ -594,17 +602,29 @@ class Sphinx(object):
def add_directive(self, name, obj, content=None, arguments=None, **options): def add_directive(self, name, obj, content=None, arguments=None, **options):
self.debug('[app] adding directive: %r', self.debug('[app] adding directive: %r',
(name, obj, content, arguments, options)) (name, obj, content, arguments, options))
if name in directives._directives:
self.warn('while setting up extension %s: directive %r is '
'already registered, it will be overridden' %
(self._setting_up_extension, name))
directives.register_directive( directives.register_directive(
name, self._directive_helper(obj, content, arguments, **options)) name, self._directive_helper(obj, content, arguments, **options))
def add_role(self, name, role): def add_role(self, name, role):
self.debug('[app] adding role: %r', (name, role)) self.debug('[app] adding role: %r', (name, role))
if name in roles._roles:
self.warn('while setting up extension %s: role %r is '
'already registered, it will be overridden' %
(self._setting_up_extension, name))
roles.register_local_role(name, role) roles.register_local_role(name, role)
def add_generic_role(self, name, nodeclass): def add_generic_role(self, name, nodeclass):
# don't use roles.register_generic_role because it uses # don't use roles.register_generic_role because it uses
# register_canonical_role # register_canonical_role
self.debug('[app] adding generic role: %r', (name, nodeclass)) self.debug('[app] adding generic role: %r', (name, nodeclass))
if name in roles._roles:
self.warn('while setting up extension %s: role %r is '
'already registered, it will be overridden' %
(self._setting_up_extension, name))
role = roles.GenericRole(name, nodeclass) role = roles.GenericRole(name, nodeclass)
roles.register_local_role(name, role) roles.register_local_role(name, role)