diff options
Diffstat (limited to 'sphinx/application.py')
-rw-r--r-- | sphinx/application.py | 82 |
1 files changed, 51 insertions, 31 deletions
diff --git a/sphinx/application.py b/sphinx/application.py index 8f90e3e64..1e3435c5a 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -36,7 +36,8 @@ from sphinx.domains import ObjType, BUILTIN_DOMAINS from sphinx.domains.std import GenericObject, Target, StandardDomain from sphinx.builders import BUILTIN_BUILDERS from sphinx.environment import BuildEnvironment, SphinxStandaloneReader -from sphinx.util import pycompat # imported for side-effects +from sphinx.util import pycompat # noqa: imported for side-effects +from sphinx.util import import_object from sphinx.util.tags import Tags from sphinx.util.osutil import ENOENT from sphinx.util.console import bold, lightgray, darkgray, darkgreen, \ @@ -77,7 +78,9 @@ 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() self.builder = None self.env = None @@ -110,7 +113,7 @@ class Sphinx(object): self.messagelog = deque(maxlen=10) # say hello to the world - self.info(bold('Running Sphinx v%s' % sphinx.__version__)) + self.info(bold('Running Sphinx v%s' % sphinx.__display_version__)) # status code for command-line application self.statuscode = 0 @@ -142,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) @@ -157,7 +161,7 @@ class Sphinx(object): # check the Sphinx version if requested if self.config.needs_sphinx and \ - self.config.needs_sphinx > sphinx.__version__[:3]: + self.config.needs_sphinx > sphinx.__display_version__[:3]: raise VersionRequirementError( 'This project needs at least Sphinx v%s and therefore cannot ' 'be built with this version.' % self.config.needs_sphinx) @@ -184,7 +188,7 @@ class Sphinx(object): # set up the build environment self._init_env(freshenv) # set up the builder - self._init_builder(buildername) + self._init_builder(self.buildername) def _init_i18n(self): """Load translated strings from the configured localedirs if enabled in @@ -198,7 +202,8 @@ class Sphinx(object): else: locale_dirs = [] self.translator, has_translation = locale.init(locale_dirs, - self.config.language) + self.config.language, + charset=self.config.source_encoding) if self.config.language is not None: if has_translation or self.config.language == 'en': # "en" never needs to be translated @@ -262,8 +267,8 @@ class Sphinx(object): self.builder.compile_update_catalogs() self.builder.build_update() - status = (self.statuscode == 0 - and 'succeeded' or 'finished with problems') + status = (self.statuscode == 0 and + 'succeeded' or 'finished with problems') if self._warncount: self.info(bold('build %s, %s warning%s.' % (status, self._warncount, @@ -424,6 +429,7 @@ class Sphinx(object): self.debug('[app] setting up extension: %r', extension) if extension in self._extensions: return + self._setting_up_extension.append(extension) try: mod = __import__(extension, None, None, ['setup']) except ImportError as err: @@ -445,34 +451,29 @@ class Sphinx(object): 'version.' % (extension, err)) if ext_meta is None: ext_meta = {} - if not ext_meta.get('version'): - ext_meta['version'] = 'unknown version' + # special-case for compatibility + if extension == 'rst2pdf.pdfbuilder': + ext_meta = {'parallel_read_safe': True} + try: + if not ext_meta.get('version'): + ext_meta['version'] = 'unknown version' + except Exception: + self.warn('extension %r returned an unsupported object from ' + 'its setup() function; it should return None or a ' + 'metadata dictionary' % extension) + ext_meta = {'version': 'unknown version'} self._extensions[extension] = mod self._extension_metadata[extension] = ext_meta + self._setting_up_extension.pop() def require_sphinx(self, version): # check the Sphinx version if requested - if version > sphinx.__version__[:3]: + if version > sphinx.__display_version__[:3]: raise VersionRequirementError(version) def import_object(self, objname, source=None): """Import an object from a 'module.name' string.""" - try: - module, name = objname.rsplit('.', 1) - except ValueError as err: - raise ExtensionError('Invalid full object name %s' % objname + - (source and ' (needed for %s)' % source or ''), - err) - try: - return getattr(__import__(module, None, None, [name]), name) - except ImportError as err: - raise ExtensionError('Could not import %s' % module + - (source and ' (needed for %s)' % source or ''), - err) - except AttributeError as err: - raise ExtensionError('Could not find %s' % objname + - (source and ' (needed for %s)' % source or ''), - err) + return import_object(objname, source=None) # event interface @@ -501,8 +502,9 @@ class Sphinx(object): def emit(self, event, *args): try: self.debug2('[app] emitting event: %r%s', event, repr(args)[:100]) - except Exception: # not every object likes to be repr()'d (think - # random stuff coming via autodoc) + except Exception: + # not every object likes to be repr()'d (think + # random stuff coming via autodoc) pass results = [] if event in self._listeners: @@ -533,13 +535,14 @@ class Sphinx(object): builder.name, self.builderclasses[builder.name].__module__)) self.builderclasses[builder.name] = builder - def add_config_value(self, name, default, rebuild): - self.debug('[app] adding config value: %r', (name, default, rebuild)) + def add_config_value(self, name, default, rebuild, types=()): + self.debug('[app] adding config value: %r', + (name, default, rebuild) + ((types,) if types else ())) if name in self.config.values: raise ExtensionError('Config value %r already present' % name) if rebuild in (False, True): rebuild = rebuild and 'env' or '' - self.config.values[name] = (default, rebuild) + self.config.values[name] = (default, rebuild, types) def add_event(self, name): self.debug('[app] adding event: %r', name) @@ -553,6 +556,11 @@ class Sphinx(object): def add_node(self, node, **kwds): self.debug('[app] adding node: %r', (node, kwds)) + if not kwds.pop('override', False) and \ + 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: @@ -597,17 +605,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[-1], 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[-1], 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[-1], name)) role = roles.GenericRole(name, nodeclass) roles.register_local_role(name, role) |