Skip to content

Commit

Permalink
Add Extension class
Browse files Browse the repository at this point in the history
  • Loading branch information
tk0miya committed Mar 23, 2017
1 parent 064a0da commit 9025297
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 38 deletions.
4 changes: 2 additions & 2 deletions sphinx/application.py
Expand Up @@ -58,6 +58,7 @@
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',
Expand Down Expand Up @@ -112,8 +113,7 @@ def __init__(self, srcdir, confdir, outdir, doctreedir, buildername,
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]]
Expand Down
8 changes: 4 additions & 4 deletions sphinx/builders/__init__.py
Expand Up @@ -17,6 +17,7 @@
except ImportError:
multiprocessing = None

from six import itervalues
from docutils import nodes

from sphinx.util import i18n, path_stabilize, logging, status_iterator
Expand Down Expand Up @@ -337,11 +338,10 @@ def build(self, docnames, summary=None, method='update'):
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

Expand Down
29 changes: 14 additions & 15 deletions sphinx/environment/__init__.py
Expand Up @@ -43,6 +43,7 @@
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
Expand Down Expand Up @@ -559,22 +560,20 @@ def update(self, config, srcdir, doctreedir):
# 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:
Expand Down
4 changes: 2 additions & 2 deletions sphinx/environment/adapters/indexentries.py
Expand Up @@ -13,10 +13,10 @@
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
Expand Down
25 changes: 16 additions & 9 deletions sphinx/extensions.py
Expand Up @@ -33,11 +33,20 @@
} # 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 '
Expand Down Expand Up @@ -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()


Expand All @@ -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))
11 changes: 5 additions & 6 deletions sphinx/util/__init__.py
Expand Up @@ -22,7 +22,7 @@
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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 9025297

Please sign in to comment.