From cdf0f8253c613dce89b41be50ffb791ff64d0450 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 21 Jul 2015 12:42:13 +0200 Subject: [PATCH] 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). --- CHANGES | 7 +++++-- sphinx/application.py | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 9960eb772..8a626e70a 100644 --- a/CHANGES +++ b/CHANGES @@ -7,12 +7,15 @@ Incompatible changes 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 ---------- * #1789: ``:pyobject:`` option of ``literalinclude`` directive includes following - lines after class definitions -* #1790: ``literalinclude`` strips empty lines at the head and tail + lines after class definitions. +* #1790: ``literalinclude`` strips empty lines at the head and tail. * #1913: C++, fix assert bug for enumerators in next-to-global and global scope. Documentation diff --git a/sphinx/application.py b/sphinx/application.py index 93bdeee60..35d81bc45 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -78,6 +78,7 @@ class Sphinx(object): self._extensions = {} self._extension_metadata = {} self._listeners = {} + self._setting_up_extension = '?' self.domains = BUILTIN_DOMAINS.copy() self.buildername = buildername self.builderclasses = BUILTIN_BUILDERS.copy() @@ -144,6 +145,7 @@ class Sphinx(object): self.setup_extension(extension) # the config file itself can be an extension if self.config.setup: + self._setting_up_extension = 'conf.py' # py31 doesn't have 'callable' function for below check if hasattr(self.config.setup, '__call__'): self.config.setup(self) @@ -426,6 +428,7 @@ class Sphinx(object): self.debug('[app] setting up extension: %r', extension) if extension in self._extensions: return + self._setting_up_extension = extension try: mod = __import__(extension, None, None, ['setup']) except ImportError as err: @@ -460,6 +463,7 @@ class Sphinx(object): ext_meta = {'version': 'unknown version'} self._extensions[extension] = mod self._extension_metadata[extension] = ext_meta + self._setting_up_extension = '?' def require_sphinx(self, version): # check the Sphinx version if requested @@ -550,6 +554,10 @@ class Sphinx(object): def add_node(self, 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__]) for key, val in iteritems(kwds): try: @@ -594,17 +602,29 @@ class Sphinx(object): def add_directive(self, name, obj, content=None, arguments=None, **options): self.debug('[app] adding directive: %r', (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( name, self._directive_helper(obj, content, arguments, **options)) def add_role(self, 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) def add_generic_role(self, name, nodeclass): # don't use roles.register_generic_role because it uses # register_canonical_role 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) roles.register_local_role(name, role)