summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sphinx/application.py4
-rw-r--r--sphinx/builders/__init__.py8
-rw-r--r--sphinx/environment/__init__.py29
-rw-r--r--sphinx/environment/adapters/indexentries.py4
-rw-r--r--sphinx/extensions.py25
-rw-r--r--sphinx/util/__init__.py11
6 files changed, 43 insertions, 38 deletions
diff --git a/sphinx/application.py b/sphinx/application.py
index 92176487e..7b6b0788e 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -58,6 +58,7 @@ if False:
from sphinx.builders import Builder # NOQA
from sphinx.domains import Domain, Index # NOQA
from sphinx.environment.collectors import EnvironmentCollector # NOQA
+ from sphinx.extensions import Extension # NOQA
builtin_extensions = (
'sphinx.builders.applehelp',
@@ -112,8 +113,7 @@ class Sphinx(object):
parallel=0):
# type: (unicode, unicode, unicode, unicode, unicode, Dict, IO, IO, bool, bool, List[unicode], int, int) -> None # NOQA
self.verbosity = verbosity
- self._extensions = {} # type: Dict[unicode, Any]
- self._extension_metadata = {} # type: Dict[unicode, Dict[unicode, Any]]
+ self.extensions = {} # type: Dict[unicode, Extension]
self._additional_source_parsers = {} # type: Dict[unicode, Parser]
self._setting_up_extension = ['?'] # type: List[unicode]
self.domains = {} # type: Dict[unicode, Type[Domain]]
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index f7593020a..adb3a3b8a 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -17,6 +17,7 @@ try:
except ImportError:
multiprocessing = None
+from six import itervalues
from docutils import nodes
from sphinx.util import i18n, path_stabilize, logging, status_iterator
@@ -337,11 +338,10 @@ class Builder(object):
self.parallel_ok = False
if parallel_available and self.app.parallel > 1 and self.allow_parallel:
self.parallel_ok = True
- for extname, md in self.app._extension_metadata.items():
- par_ok = md.get('parallel_write_safe', True)
- if not par_ok:
+ for extension in itervalues(self.app.extensions):
+ if not extension.parallel_write_safe:
logger.warning('the %s extension is not safe for parallel '
- 'writing, doing serial write', extname)
+ 'writing, doing serial write', extension.name)
self.parallel_ok = False
break
diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py
index 014850f7f..45dfae8f5 100644
--- a/sphinx/environment/__init__.py
+++ b/sphinx/environment/__init__.py
@@ -43,6 +43,7 @@ from sphinx.util.matching import compile_matchers
from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks
from sphinx.util.websupport import is_commentable
from sphinx.errors import SphinxError, ExtensionError
+from sphinx.locale import _
from sphinx.transforms import SphinxTransformer
from sphinx.versioning import add_uids, merge_doctrees
from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning
@@ -559,22 +560,20 @@ class BuildEnvironment(object):
# check if we should do parallel or serial read
par_ok = False
if parallel_available and len(docnames) > 5 and self.app.parallel > 1:
- par_ok = True
- for extname, md in self.app._extension_metadata.items():
- ext_ok = md.get('parallel_read_safe')
- if ext_ok:
- continue
- if ext_ok is None:
- logger.warning('the %s extension does not declare if it '
- 'is safe for parallel reading, assuming it '
- 'isn\'t - please ask the extension author to '
- 'check and make it explicit', extname)
+ for ext in itervalues(self.app.extensions):
+ if ext.parallel_read_safe is None:
+ logger.warning(_('the %s extension does not declare if it is safe '
+ 'for parallel reading, assuming it isn\'t - please '
+ 'ask the extension author to check and make it '
+ 'explicit'), ext.name)
logger.warning('doing serial read')
- else:
- logger.warning('the %s extension is not safe for parallel '
- 'reading, doing serial read', extname)
- par_ok = False
- break
+ break
+ elif ext.parallel_read_safe is False:
+ break
+ else:
+ # all extensions support parallel-read
+ par_ok = True
+
if par_ok:
self._read_parallel(docnames, self.app, nproc=self.app.parallel)
else:
diff --git a/sphinx/environment/adapters/indexentries.py b/sphinx/environment/adapters/indexentries.py
index 31ec58301..4eb1f8a32 100644
--- a/sphinx/environment/adapters/indexentries.py
+++ b/sphinx/environment/adapters/indexentries.py
@@ -13,10 +13,10 @@ import bisect
import unicodedata
from itertools import groupby
-from six import text_type
+from six import text_type, iteritems
from sphinx.locale import _
-from sphinx.util import iteritems, split_into, logging
+from sphinx.util import split_into, logging
if False:
# For type annotation
diff --git a/sphinx/extensions.py b/sphinx/extensions.py
index d51b6760d..8e929a48b 100644
--- a/sphinx/extensions.py
+++ b/sphinx/extensions.py
@@ -33,11 +33,20 @@ EXTENSION_BLACKLIST = {
} # type: Dict[unicode, unicode]
+class Extension(object):
+ def __init__(self, name, module, **kwargs):
+ self.name = name
+ self.module = module
+ self.version = kwargs.pop('version', 'unknown version')
+ self.parallel_read_safe = kwargs.pop('parallel_read_safe', None)
+ self.parallel_write_safe = kwargs.pop('parallel_read_safe', True)
+ self.metadata = kwargs
+
+
def load(app, extname):
# type: (Sphinx, unicode) -> None
"""Load a Sphinx extension."""
- if extname in app._extensions:
- # alread loaded
+ if extname in app.extensions: # alread loaded
return
if extname in EXTENSION_BLACKLIST:
logger.warning(_('the extension %r was already merged with Sphinx since '
@@ -78,9 +87,7 @@ def load(app, extname):
'its setup() function; it should return None or a '
'metadata dictionary'), extname)
- metadata.setdefault('version', 'unknown version')
- app._extensions[extname] = mod
- app._extension_metadata[extname] = metadata
+ app.extensions[extname] = Extension(extname, mod, **metadata)
app._setting_up_extension.pop()
@@ -91,15 +98,15 @@ def confirm(app, requirements):
return
for extname, reqversion in iteritems(requirements):
- if extname not in app._extensions:
+ extension = app.extensions.get(extname)
+ if extension is None:
logger.warning(_('needs_extensions config value specifies a '
'version requirement for extension %s, but it is '
'not loaded'), extname)
continue
- extversion = app._extension_metadata[extname].get('version')
- if extversion == 'unknown version' or reqversion > extversion:
+ if extension.version == 'unknown version' or reqversion > extension.version:
raise VersionRequirementError(_('This project needs the extension %s at least in '
'version %s and therefore cannot be built with '
'the loaded version (%s).') %
- (extname, reqversion, extversion))
+ (extname, reqversion, extension.version))
diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py
index a3823546d..adf526e06 100644
--- a/sphinx/util/__init__.py
+++ b/sphinx/util/__init__.py
@@ -22,7 +22,7 @@ from os import path
from codecs import BOM_UTF8
from collections import deque
-from six import iteritems, text_type, binary_type
+from six import text_type, binary_type
from six.moves import range
from six.moves.urllib.parse import urlsplit, urlunsplit, quote_plus, parse_qsl, urlencode
from docutils.utils import relative_path
@@ -227,14 +227,13 @@ def save_traceback(app):
jinja2.__version__, # type: ignore
last_msgs)).encode('utf-8'))
if app is not None:
- for extname, extmod in iteritems(app._extensions):
- modfile = getattr(extmod, '__file__', 'unknown')
+ for ext in app.extensions:
+ modfile = getattr(ext.module, '__file__', 'unknown')
if isinstance(modfile, bytes):
modfile = modfile.decode(fs_encoding, 'replace')
- version = app._extension_metadata[extname]['version']
- if version != 'builtin':
+ if ext.version != 'builtin':
os.write(fd, ('# %s (%s) from %s\n' %
- (extname, version, modfile)).encode('utf-8'))
+ (ext.name, ext.version, modfile)).encode('utf-8'))
os.write(fd, exc_format.encode('utf-8'))
os.close(fd)
return path