mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add BuildEnvironment.setup() to re-initialize (after unpickle)
This commit is contained in:
parent
ad991e7f4c
commit
3ffde92c54
@ -287,24 +287,15 @@ class Sphinx(object):
|
||||
# type: (bool) -> None
|
||||
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||
if freshenv or not os.path.exists(filename):
|
||||
self.env = BuildEnvironment(self)
|
||||
self.env = BuildEnvironment()
|
||||
self.env.setup(self)
|
||||
self.env.find_files(self.config, self.builder)
|
||||
for domain in self.registry.create_domains(self.env):
|
||||
self.env.domains[domain.name] = domain
|
||||
else:
|
||||
try:
|
||||
logger.info(bold(__('loading pickled environment... ')), nonl=True)
|
||||
with open(filename, 'rb') as f:
|
||||
self.env = pickle.load(f)
|
||||
self.env.app = self
|
||||
self.env.config.values = self.config.values
|
||||
needed, reason = self.env.need_refresh(self)
|
||||
if needed:
|
||||
raise IOError(reason)
|
||||
self.env.domains = {}
|
||||
for domain in self.registry.create_domains(self.env):
|
||||
# this can raise if the data version doesn't fit
|
||||
self.env.domains[domain.name] = domain
|
||||
self.env.setup(self)
|
||||
logger.info(__('done'))
|
||||
except Exception as err:
|
||||
logger.info(__('failed: %s'), err)
|
||||
|
@ -17,6 +17,7 @@ from docutils import nodes
|
||||
from six.moves import cPickle as pickle
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment import CONFIG_OK, CONFIG_CHANGED_REASON
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.io import read_doc
|
||||
@ -422,11 +423,10 @@ class Builder(object):
|
||||
Store all environment docnames in the canonical format (ie using SEP as
|
||||
a separator in place of os.path.sep).
|
||||
"""
|
||||
updated, reason = self.env.update_config(self.config, self.srcdir, self.doctreedir)
|
||||
|
||||
logger.info(bold('updating environment: '), nonl=True)
|
||||
|
||||
self.env.find_files(self.config, self)
|
||||
updated = (self.env.config_status != CONFIG_OK)
|
||||
added, changed, removed = self.env.get_outdated_files(updated)
|
||||
|
||||
# allow user intervention as well
|
||||
@ -440,6 +440,7 @@ class Builder(object):
|
||||
changed.update(self.env.glob_toctrees & self.env.found_docs)
|
||||
|
||||
if changed:
|
||||
reason = CONFIG_CHANGED_REASON.get(self.env.config_status, '')
|
||||
logger.info('[%s] ', reason, nonl=True)
|
||||
logger.info('%s added, %s changed, %s removed',
|
||||
len(added), len(changed), len(removed))
|
||||
@ -473,6 +474,9 @@ class Builder(object):
|
||||
if retval is not None:
|
||||
docnames.extend(retval)
|
||||
|
||||
# workaround: marked as okay to call builder.read() twice in same process
|
||||
self.env.config_status = CONFIG_OK
|
||||
|
||||
return sorted(docnames)
|
||||
|
||||
def _read_serial(self, docnames):
|
||||
|
@ -25,7 +25,7 @@ from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.errors import SphinxError, ExtensionError
|
||||
from sphinx.errors import SphinxError, BuildEnvironmentError, ExtensionError
|
||||
from sphinx.locale import __
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import get_matching_docs, FilenameUniqDict
|
||||
@ -69,6 +69,18 @@ default_settings = {
|
||||
# NOTE: increase base version by 2 to have distinct numbers for Py2 and 3
|
||||
ENV_VERSION = 53 + (sys.version_info[0] - 2)
|
||||
|
||||
# config status
|
||||
CONFIG_OK = 1
|
||||
CONFIG_NEW = 2
|
||||
CONFIG_CHANGED = 3
|
||||
CONFIG_EXTENSIONS_CHANGED = 4
|
||||
|
||||
CONFIG_CHANGED_REASON = {
|
||||
CONFIG_NEW: __('new config'),
|
||||
CONFIG_CHANGED: __('config changed'),
|
||||
CONFIG_EXTENSIONS_CHANGED: __('extensions changed'),
|
||||
}
|
||||
|
||||
|
||||
versioning_conditions = {
|
||||
'none': False,
|
||||
@ -93,12 +105,14 @@ class BuildEnvironment(object):
|
||||
|
||||
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
|
||||
|
||||
def __init__(self, app):
|
||||
def __init__(self, app=None):
|
||||
# type: (Sphinx) -> None
|
||||
self.app = app
|
||||
self.doctreedir = app.doctreedir
|
||||
self.srcdir = app.srcdir # type: unicode
|
||||
self.config = app.config # type: Config
|
||||
self.app = None # type: Sphinx
|
||||
self.doctreedir = None # type: unicode
|
||||
self.srcdir = None # type: unicode
|
||||
self.config = None # type: Config
|
||||
self.config_status = None # type: int
|
||||
self.version = None # type: Dict[unicode, unicode]
|
||||
|
||||
# the method of doctree versioning; see set_versioning_method
|
||||
self.versioning_condition = None # type: Union[bool, Callable]
|
||||
@ -114,9 +128,6 @@ class BuildEnvironment(object):
|
||||
# the function to write warning messages with
|
||||
self._warnfunc = None # type: Callable
|
||||
|
||||
# this is to invalidate old pickles
|
||||
self.version = app.registry.get_envversion(app) # type: Dict[unicode, unicode]
|
||||
|
||||
# All "docnames" here are /-separated and relative and exclude
|
||||
# the source suffix.
|
||||
|
||||
@ -193,6 +204,10 @@ class BuildEnvironment(object):
|
||||
# attributes of "any" cross references
|
||||
self.ref_context = {} # type: Dict[unicode, Any]
|
||||
|
||||
# set up environment
|
||||
if app:
|
||||
self.setup(app)
|
||||
|
||||
def __getstate__(self):
|
||||
# type: () -> Dict
|
||||
"""Obtains serializable data for pickling."""
|
||||
@ -204,6 +219,61 @@ class BuildEnvironment(object):
|
||||
# type: (Dict) -> None
|
||||
self.__dict__.update(state)
|
||||
|
||||
def setup(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
"""Set up BuildEnvironment object."""
|
||||
if self.version and self.version != app.registry.get_envversion(app):
|
||||
raise BuildEnvironmentError(__('build environment version not current'))
|
||||
elif self.srcdir and self.srcdir != app.srcdir:
|
||||
raise BuildEnvironmentError(__('source directory has changed'))
|
||||
|
||||
self.app = app
|
||||
self.doctreedir = app.doctreedir
|
||||
self.srcdir = app.srcdir
|
||||
self.version = app.registry.get_envversion(app)
|
||||
|
||||
# initialize domains
|
||||
self.domains = {}
|
||||
for domain in app.registry.create_domains(self):
|
||||
self.domains[domain.name] = domain
|
||||
|
||||
# initialize config
|
||||
self._update_config(app.config)
|
||||
|
||||
# initialie settings
|
||||
self._update_settings(app.config)
|
||||
|
||||
def _update_config(self, config):
|
||||
# type: (Config) -> None
|
||||
"""Update configurations by new one."""
|
||||
self.config_status = CONFIG_OK
|
||||
if self.config is None:
|
||||
self.config_status = CONFIG_NEW
|
||||
else:
|
||||
# check if a config value was changed that affects how
|
||||
# doctrees are read
|
||||
for item in config.filter('env'):
|
||||
if self.config[item.name] != item.value:
|
||||
self.config_status = CONFIG_CHANGED
|
||||
break
|
||||
|
||||
# this value is not covered by the above loop because it is handled
|
||||
# specially by the config class
|
||||
if self.config.extensions != config.extensions:
|
||||
self.config_status = CONFIG_EXTENSIONS_CHANGED
|
||||
|
||||
self.config = config
|
||||
|
||||
def _update_settings(self, config):
|
||||
# type: (Config) -> None
|
||||
"""Update settings by new config."""
|
||||
self.settings['input_encoding'] = config.source_encoding
|
||||
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
||||
self.settings['language_code'] = config.language or 'en'
|
||||
|
||||
# Allow to disable by 3rd party extension (workaround)
|
||||
self.settings.setdefault('smart_quotes', True)
|
||||
|
||||
def set_warnfunc(self, func):
|
||||
# type: (Callable) -> None
|
||||
warnings.warn('env.set_warnfunc() is now deprecated. Use sphinx.util.logging instead.',
|
||||
@ -451,44 +521,6 @@ class BuildEnvironment(object):
|
||||
if docname not in already:
|
||||
yield docname
|
||||
|
||||
def update_config(self, config, srcdir, doctreedir):
|
||||
# type: (Config, unicode, unicode) -> Tuple[bool, unicode]
|
||||
"""Update configurations by new one."""
|
||||
changed_reason = ''
|
||||
if self.config is None:
|
||||
changed_reason = __('new config')
|
||||
else:
|
||||
# check if a config value was changed that affects how
|
||||
# doctrees are read
|
||||
for confval in config.filter('env'):
|
||||
if self.config[confval.name] != confval.value:
|
||||
changed_reason = __('config changed')
|
||||
break
|
||||
|
||||
# this value is not covered by the above loop because it is handled
|
||||
# specially by the config class
|
||||
if self.config.extensions != config.extensions:
|
||||
changed_reason = __('extensions changed')
|
||||
|
||||
# the source and doctree directories may have been relocated
|
||||
self.srcdir = srcdir
|
||||
self.doctreedir = doctreedir
|
||||
self.config = config
|
||||
self._update_settings(config)
|
||||
|
||||
# return tuple of (changed, reason)
|
||||
return bool(changed_reason), changed_reason
|
||||
|
||||
def _update_settings(self, config):
|
||||
# type: (Config) -> None
|
||||
"""Update settings by new config."""
|
||||
self.settings['input_encoding'] = config.source_encoding
|
||||
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
||||
self.settings['language_code'] = config.language or 'en'
|
||||
|
||||
# Allow to disable by 3rd party extension (workaround)
|
||||
self.settings.setdefault('smart_quotes', True)
|
||||
|
||||
# --------- SINGLE FILE READING --------------------------------------------
|
||||
|
||||
def prepare_settings(self, docname):
|
||||
|
@ -72,6 +72,11 @@ class ExtensionError(SphinxError):
|
||||
return parent_str
|
||||
|
||||
|
||||
class BuildEnvironmentError(SphinxError):
|
||||
"""BuildEnvironment error."""
|
||||
category = 'BuildEnvironment error'
|
||||
|
||||
|
||||
class ConfigError(SphinxError):
|
||||
"""Configuration error."""
|
||||
category = 'Configuration error'
|
||||
|
Loading…
Reference in New Issue
Block a user