Add app.is_parallel_allowed()

This commit is contained in:
Takeshi KOMIYA 2017-12-30 00:54:55 +09:00
parent 54699dd263
commit 1d3362425b
9 changed files with 91 additions and 23 deletions

View File

@ -19,7 +19,7 @@ import posixpath
from os import path
from collections import deque
from six import iteritems
from six import iteritems, itervalues
from six.moves import cStringIO
from docutils import nodes
@ -673,6 +673,34 @@ class Sphinx(object):
logger.debug('[app] adding HTML theme: %r, %r', name, theme_path)
self.html_themes[name] = theme_path
# ---- other methods -------------------------------------------------
def is_parallel_allowed(self, typ):
# type: (unicode) -> bool
"""Check parallel processing is allowed or not.
``typ`` is a type of processing; ``'read'`` or ``'write'``.
"""
if typ == 'read':
attrname = 'parallel_read_safe'
elif typ == 'write':
attrname = 'parallel_write_safe'
else:
raise ValueError('parallel type %s is not supported' % typ)
for ext in itervalues(self.extensions):
allowed = getattr(ext, attrname, None)
if allowed is None:
logger.warning(__("the %s extension does not declare if it is safe "
"for parallel %sing, assuming it isn't - please "
"ask the extension author to check and make it "
"explicit"), ext.name, typ)
logger.warning('doing serial %s', typ)
return False
elif not allowed:
return False
return True
class TemplateBridge(object):
"""

View File

@ -371,15 +371,10 @@ class Builder(object):
docnames = set(docnames) & self.env.found_docs
# determine if we can write in parallel
self.parallel_ok = False
if parallel_available and self.app.parallel > 1 and self.allow_parallel:
self.parallel_ok = True
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', extension.name)
self.parallel_ok = False
break
self.parallel_ok = self.app.is_parallel_allowed('write')
else:
self.parallel_ok = False
# create a task executor to use for misc. "finish-up" tasks
# if self.parallel_ok:

View File

@ -558,21 +558,10 @@ class BuildEnvironment(object):
self.app.emit('env-before-read-docs', self, docnames)
# check if we should do parallel or serial read
par_ok = False
if parallel_available and len(docnames) > 5 and self.app.parallel > 1:
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')
break
elif ext.parallel_read_safe is False:
break
else:
# all extensions support parallel-read
par_ok = True
par_ok = self.app.is_parallel_allowed('read')
else:
par_ok = False
if par_ok:
self._read_parallel(docnames, self.app, nproc=self.app.parallel)

View File

@ -0,0 +1,4 @@
import os
import sys
sys.path.insert(0, os.path.abspath('.'))

View File

@ -0,0 +1,4 @@
def setup(app):
return {
'parallel_read_safe': True
}

View File

@ -0,0 +1,4 @@
def setup(app):
return {
'parallel_read_safe': False
}

View File

@ -0,0 +1,4 @@
def setup(app):
return {
'parallel_write_safe': True,
}

View File

@ -0,0 +1,4 @@
def setup(app):
return {
'parallel_write_safe': False
}

View File

@ -12,6 +12,7 @@ from docutils import nodes
from sphinx.application import ExtensionError
from sphinx.domains import Domain
from sphinx.util import logging
from sphinx.testing.util import strip_escseq
import pytest
@ -86,3 +87,38 @@ def test_add_source_parser(app, status, warning):
assert set(app.registry.get_source_parsers().keys()) == set(['*', '.md', '.test'])
assert app.registry.get_source_parsers()['.md'].__name__ == 'DummyMarkdownParser'
assert app.registry.get_source_parsers()['.test'].__name__ == 'TestSourceParser'
@pytest.mark.sphinx(testroot='extensions')
def test_add_is_parallel_allowed(app, status, warning):
logging.setup(app, status, warning)
assert app.is_parallel_allowed('read') is True
assert app.is_parallel_allowed('write') is True
assert warning.getvalue() == ''
app.setup_extension('read_parallel')
assert app.is_parallel_allowed('read') is True
assert app.is_parallel_allowed('write') is True
assert warning.getvalue() == ''
app.extensions.pop('read_parallel')
app.setup_extension('write_parallel')
assert app.is_parallel_allowed('read') is False
assert app.is_parallel_allowed('write') is True
assert 'the write_parallel extension does not declare' in warning.getvalue()
app.extensions.pop('write_parallel')
warning.truncate(0) # reset warnings
app.setup_extension('read_serial')
assert app.is_parallel_allowed('read') is False
assert app.is_parallel_allowed('write') is True
assert warning.getvalue() == ''
app.extensions.pop('read_serial')
app.setup_extension('write_serial')
assert app.is_parallel_allowed('read') is False
assert app.is_parallel_allowed('write') is False
assert 'the write_serial extension does not declare' in warning.getvalue()
app.extensions.pop('write_serial')
warning.truncate(0) # reset warnings