mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
BuildEnvironment always own application object (after read phase)
This commit is contained in:
parent
a523f9893a
commit
c7bec75bcd
@ -301,15 +301,15 @@ class Sphinx(object):
|
|||||||
def _init_env(self, freshenv):
|
def _init_env(self, freshenv):
|
||||||
# type: (bool) -> None
|
# type: (bool) -> None
|
||||||
if freshenv:
|
if freshenv:
|
||||||
self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
|
self.env = BuildEnvironment(self)
|
||||||
self.env.find_files(self.config, self.buildername)
|
self.env.find_files(self.config, self.buildername)
|
||||||
for domain in self.domains.keys():
|
for domain in self.domains.keys():
|
||||||
self.env.domains[domain] = self.domains[domain](self.env)
|
self.env.domains[domain] = self.domains[domain](self.env)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
logger.info(bold('loading pickled environment... '), nonl=True)
|
logger.info(bold('loading pickled environment... '), nonl=True)
|
||||||
self.env = BuildEnvironment.frompickle(
|
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||||
self.srcdir, self.config, path.join(self.doctreedir, ENV_PICKLE_FILENAME))
|
self.env = BuildEnvironment.frompickle(filename, self)
|
||||||
self.env.domains = {}
|
self.env.domains = {}
|
||||||
for domain in self.domains.keys():
|
for domain in self.domains.keys():
|
||||||
# this can raise if the data version doesn't fit
|
# this can raise if the data version doesn't fit
|
||||||
@ -372,6 +372,7 @@ class Sphinx(object):
|
|||||||
else:
|
else:
|
||||||
self.emit('build-finished', None)
|
self.emit('build-finished', None)
|
||||||
self.builder.cleanup()
|
self.builder.cleanup()
|
||||||
|
self.env = None # clear environment
|
||||||
|
|
||||||
# ---- logging handling ----------------------------------------------------
|
# ---- logging handling ----------------------------------------------------
|
||||||
def warn(self, message, location=None, prefix=None,
|
def warn(self, message, location=None, prefix=None,
|
||||||
|
@ -289,8 +289,7 @@ class Builder(object):
|
|||||||
|
|
||||||
# while reading, collect all warnings from docutils
|
# while reading, collect all warnings from docutils
|
||||||
with logging.pending_warnings():
|
with logging.pending_warnings():
|
||||||
updated_docnames = set(self.env.update(self.config, self.srcdir,
|
updated_docnames = set(self.env.update(self.config, self.srcdir, self.doctreedir))
|
||||||
self.doctreedir, self.app))
|
|
||||||
|
|
||||||
doccount = len(updated_docnames)
|
doccount = len(updated_docnames)
|
||||||
logger.info(bold('looking for now-outdated files... '), nonl=1)
|
logger.info(bold('looking for now-outdated files... '), nonl=1)
|
||||||
|
@ -104,33 +104,36 @@ class BuildEnvironment(object):
|
|||||||
# --------- ENVIRONMENT PERSISTENCE ----------------------------------------
|
# --------- ENVIRONMENT PERSISTENCE ----------------------------------------
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(f, srcdir=None, config=None):
|
def load(f, app=None):
|
||||||
# type: (IO, unicode, Config) -> BuildEnvironment
|
# type: (IO, Sphinx) -> BuildEnvironment
|
||||||
env = pickle.load(f)
|
env = pickle.load(f)
|
||||||
if env.version != ENV_VERSION:
|
if env.version != ENV_VERSION:
|
||||||
raise IOError('build environment version not current')
|
raise IOError('build environment version not current')
|
||||||
if srcdir and env.srcdir != srcdir:
|
if app:
|
||||||
|
env.app = app
|
||||||
|
env.config.values = app.config.values
|
||||||
|
if env.srcdir != app.srcdir:
|
||||||
raise IOError('source directory has changed')
|
raise IOError('source directory has changed')
|
||||||
if config:
|
|
||||||
env.config.values = config.values
|
|
||||||
return env
|
return env
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def loads(cls, string, srcdir=None, config=None):
|
def loads(cls, string, app=None):
|
||||||
# type: (unicode, unicode, Config) -> BuildEnvironment
|
# type: (unicode, Sphinx) -> BuildEnvironment
|
||||||
io = StringIO(string)
|
io = StringIO(string)
|
||||||
return cls.load(io)
|
return cls.load(io, app)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def frompickle(cls, srcdir, config, filename):
|
def frompickle(cls, filename, app):
|
||||||
# type: (unicode, Config, unicode) -> BuildEnvironment
|
# type: (unicode, Sphinx) -> BuildEnvironment
|
||||||
with open(filename, 'rb') as f:
|
with open(filename, 'rb') as f:
|
||||||
return cls.load(f, srcdir, config)
|
return cls.load(f, app)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dump(env, f):
|
def dump(env, f):
|
||||||
# type: (BuildEnvironment, IO) -> None
|
# type: (BuildEnvironment, IO) -> None
|
||||||
# remove unpicklable attributes
|
# remove unpicklable attributes
|
||||||
|
app = env.app
|
||||||
|
del env.app
|
||||||
values = env.config.values
|
values = env.config.values
|
||||||
del env.config.values
|
del env.config.values
|
||||||
domains = env.domains
|
domains = env.domains
|
||||||
@ -146,6 +149,7 @@ class BuildEnvironment(object):
|
|||||||
# reset attributes
|
# reset attributes
|
||||||
env.domains = domains
|
env.domains = domains
|
||||||
env.config.values = values
|
env.config.values = values
|
||||||
|
env.app = app
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def dumps(cls, env):
|
def dumps(cls, env):
|
||||||
@ -161,19 +165,17 @@ class BuildEnvironment(object):
|
|||||||
|
|
||||||
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
|
# --------- ENVIRONMENT INITIALIZATION -------------------------------------
|
||||||
|
|
||||||
def __init__(self, srcdir, doctreedir, config):
|
def __init__(self, app):
|
||||||
# type: (unicode, unicode, Config) -> None
|
# type: (Sphinx) -> None
|
||||||
self.doctreedir = doctreedir
|
self.app = app
|
||||||
self.srcdir = srcdir # type: unicode
|
self.doctreedir = app.doctreedir
|
||||||
self.config = config # type: Config
|
self.srcdir = app.srcdir
|
||||||
|
self.config = app.config
|
||||||
|
|
||||||
# the method of doctree versioning; see set_versioning_method
|
# the method of doctree versioning; see set_versioning_method
|
||||||
self.versioning_condition = None # type: Union[bool, Callable]
|
self.versioning_condition = None # type: Union[bool, Callable]
|
||||||
self.versioning_compare = None # type: bool
|
self.versioning_compare = None # type: bool
|
||||||
|
|
||||||
# the application object; only set while update() runs
|
|
||||||
self.app = None # type: Sphinx
|
|
||||||
|
|
||||||
# all the registered domains, set by the application
|
# all the registered domains, set by the application
|
||||||
self.domains = {}
|
self.domains = {}
|
||||||
|
|
||||||
@ -490,8 +492,8 @@ class BuildEnvironment(object):
|
|||||||
|
|
||||||
return added, changed, removed
|
return added, changed, removed
|
||||||
|
|
||||||
def update(self, config, srcdir, doctreedir, app):
|
def update(self, config, srcdir, doctreedir):
|
||||||
# type: (Config, unicode, unicode, Sphinx) -> List[unicode]
|
# type: (Config, unicode, unicode) -> List[unicode]
|
||||||
"""(Re-)read all files new or changed since last update.
|
"""(Re-)read all files new or changed since last update.
|
||||||
|
|
||||||
Store all environment docnames in the canonical format (ie using SEP as
|
Store all environment docnames in the canonical format (ie using SEP as
|
||||||
@ -519,7 +521,7 @@ class BuildEnvironment(object):
|
|||||||
# the source and doctree directories may have been relocated
|
# the source and doctree directories may have been relocated
|
||||||
self.srcdir = srcdir
|
self.srcdir = srcdir
|
||||||
self.doctreedir = doctreedir
|
self.doctreedir = doctreedir
|
||||||
self.find_files(config, app.buildername)
|
self.find_files(config, self.app.buildername)
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
# this cache also needs to be updated every time
|
# this cache also needs to be updated every time
|
||||||
@ -530,7 +532,7 @@ class BuildEnvironment(object):
|
|||||||
added, changed, removed = self.get_outdated_files(config_changed)
|
added, changed, removed = self.get_outdated_files(config_changed)
|
||||||
|
|
||||||
# allow user intervention as well
|
# allow user intervention as well
|
||||||
for docs in app.emit('env-get-outdated', self, added, changed, removed):
|
for docs in self.app.emit('env-get-outdated', self, added, changed, removed):
|
||||||
changed.update(set(docs) & self.found_docs)
|
changed.update(set(docs) & self.found_docs)
|
||||||
|
|
||||||
# if files were added or removed, all documents with globbed toctrees
|
# if files were added or removed, all documents with globbed toctrees
|
||||||
@ -543,23 +545,21 @@ class BuildEnvironment(object):
|
|||||||
len(removed))
|
len(removed))
|
||||||
logger.info(msg)
|
logger.info(msg)
|
||||||
|
|
||||||
self.app = app
|
|
||||||
|
|
||||||
# clear all files no longer present
|
# clear all files no longer present
|
||||||
for docname in removed:
|
for docname in removed:
|
||||||
app.emit('env-purge-doc', self, docname)
|
self.app.emit('env-purge-doc', self, docname)
|
||||||
self.clear_doc(docname)
|
self.clear_doc(docname)
|
||||||
|
|
||||||
# read all new and changed files
|
# read all new and changed files
|
||||||
docnames = sorted(added | changed)
|
docnames = sorted(added | changed)
|
||||||
# allow changing and reordering the list of docs to read
|
# allow changing and reordering the list of docs to read
|
||||||
app.emit('env-before-read-docs', self, docnames)
|
self.app.emit('env-before-read-docs', self, docnames)
|
||||||
|
|
||||||
# check if we should do parallel or serial read
|
# check if we should do parallel or serial read
|
||||||
par_ok = False
|
par_ok = False
|
||||||
if parallel_available and len(docnames) > 5 and app.parallel > 1:
|
if parallel_available and len(docnames) > 5 and self.app.parallel > 1:
|
||||||
par_ok = True
|
par_ok = True
|
||||||
for extname, md in app._extension_metadata.items():
|
for extname, md in self.app._extension_metadata.items():
|
||||||
ext_ok = md.get('parallel_read_safe')
|
ext_ok = md.get('parallel_read_safe')
|
||||||
if ext_ok:
|
if ext_ok:
|
||||||
continue
|
continue
|
||||||
@ -575,17 +575,15 @@ class BuildEnvironment(object):
|
|||||||
par_ok = False
|
par_ok = False
|
||||||
break
|
break
|
||||||
if par_ok:
|
if par_ok:
|
||||||
self._read_parallel(docnames, app, nproc=app.parallel)
|
self._read_parallel(docnames, self.app, nproc=self.app.parallel)
|
||||||
else:
|
else:
|
||||||
self._read_serial(docnames, app)
|
self._read_serial(docnames, self.app)
|
||||||
|
|
||||||
if config.master_doc not in self.all_docs:
|
if config.master_doc not in self.all_docs:
|
||||||
raise SphinxError('master file %s not found' %
|
raise SphinxError('master file %s not found' %
|
||||||
self.doc2path(config.master_doc))
|
self.doc2path(config.master_doc))
|
||||||
|
|
||||||
self.app = None
|
for retval in self.app.emit('env-updated', self):
|
||||||
|
|
||||||
for retval in app.emit('env-updated', self):
|
|
||||||
if retval is not None:
|
if retval is not None:
|
||||||
docnames.extend(retval)
|
docnames.extend(retval)
|
||||||
|
|
||||||
@ -608,20 +606,17 @@ class BuildEnvironment(object):
|
|||||||
self.clear_doc(docname)
|
self.clear_doc(docname)
|
||||||
|
|
||||||
def read_process(docs):
|
def read_process(docs):
|
||||||
# type: (List[unicode]) -> BuildEnvironment
|
# type: (List[unicode]) -> unicode
|
||||||
self.app = app
|
self.app = app
|
||||||
for docname in docs:
|
for docname in docs:
|
||||||
self.read_doc(docname, app)
|
self.read_doc(docname, app)
|
||||||
# allow pickling self to send it back
|
# allow pickling self to send it back
|
||||||
del self.app
|
return BuildEnvironment.dumps(self)
|
||||||
del self.domains
|
|
||||||
del self.config.values
|
|
||||||
del self.config
|
|
||||||
return self
|
|
||||||
|
|
||||||
def merge(docs, otherenv):
|
def merge(docs, otherenv):
|
||||||
# type: (List[unicode], BuildEnvironment) -> None
|
# type: (List[unicode], unicode) -> None
|
||||||
self.merge_info_from(docs, otherenv, app)
|
env = BuildEnvironment.loads(otherenv)
|
||||||
|
self.merge_info_from(docs, env, app)
|
||||||
|
|
||||||
tasks = ParallelTasks(nproc)
|
tasks = ParallelTasks(nproc)
|
||||||
chunks = make_chunks(docnames, nproc)
|
chunks = make_chunks(docnames, nproc)
|
||||||
|
@ -31,7 +31,7 @@ def teardown_module():
|
|||||||
# afford to not run update() in the setup but in its own test
|
# afford to not run update() in the setup but in its own test
|
||||||
|
|
||||||
def test_first_update():
|
def test_first_update():
|
||||||
updated = env.update(app.config, app.srcdir, app.doctreedir, app)
|
updated = env.update(app.config, app.srcdir, app.doctreedir)
|
||||||
assert set(updated) == env.found_docs == set(env.all_docs)
|
assert set(updated) == env.found_docs == set(env.all_docs)
|
||||||
# test if exclude_patterns works ok
|
# test if exclude_patterns works ok
|
||||||
assert 'subdir/excluded' not in env.found_docs
|
assert 'subdir/excluded' not in env.found_docs
|
||||||
@ -71,7 +71,7 @@ def test_second_update():
|
|||||||
# the contents.txt toctree; otherwise section numbers would shift
|
# the contents.txt toctree; otherwise section numbers would shift
|
||||||
(root / 'autodoc.txt').unlink()
|
(root / 'autodoc.txt').unlink()
|
||||||
(root / 'new.txt').write_text('New file\n========\n')
|
(root / 'new.txt').write_text('New file\n========\n')
|
||||||
updated = env.update(app.config, app.srcdir, app.doctreedir, app)
|
updated = env.update(app.config, app.srcdir, app.doctreedir)
|
||||||
# "includes" and "images" are in there because they contain references
|
# "includes" and "images" are in there because they contain references
|
||||||
# to nonexisting downloadable or image files, which are given another
|
# to nonexisting downloadable or image files, which are given another
|
||||||
# chance to exist
|
# chance to exist
|
||||||
@ -87,7 +87,7 @@ def test_env_read_docs():
|
|||||||
|
|
||||||
app.connect('env-before-read-docs', on_env_read_docs_1)
|
app.connect('env-before-read-docs', on_env_read_docs_1)
|
||||||
|
|
||||||
read_docnames = env.update(app.config, app.srcdir, app.doctreedir, app)
|
read_docnames = env.update(app.config, app.srcdir, app.doctreedir)
|
||||||
assert len(read_docnames) > 2 and read_docnames == sorted(read_docnames)
|
assert len(read_docnames) > 2 and read_docnames == sorted(read_docnames)
|
||||||
|
|
||||||
def on_env_read_docs_2(app, env, docnames):
|
def on_env_read_docs_2(app, env, docnames):
|
||||||
@ -95,7 +95,7 @@ def test_env_read_docs():
|
|||||||
|
|
||||||
app.connect('env-before-read-docs', on_env_read_docs_2)
|
app.connect('env-before-read-docs', on_env_read_docs_2)
|
||||||
|
|
||||||
read_docnames = env.update(app.config, app.srcdir, app.doctreedir, app)
|
read_docnames = env.update(app.config, app.srcdir, app.doctreedir)
|
||||||
assert len(read_docnames) == 2
|
assert len(read_docnames) == 2
|
||||||
|
|
||||||
|
|
||||||
|
@ -497,7 +497,7 @@ def test_gettext_buildr_ignores_only_directive(app):
|
|||||||
def test_gettext_dont_rebuild_mo(make_app, app_params, build_mo):
|
def test_gettext_dont_rebuild_mo(make_app, app_params, build_mo):
|
||||||
# --- don't rebuild by .mo mtime
|
# --- don't rebuild by .mo mtime
|
||||||
def get_number_of_update_targets(app_):
|
def get_number_of_update_targets(app_):
|
||||||
updated = app_.env.update(app_.config, app_.srcdir, app_.doctreedir, app_)
|
updated = app_.env.update(app_.config, app_.srcdir, app_.doctreedir)
|
||||||
return len(updated)
|
return len(updated)
|
||||||
|
|
||||||
# setup new directory
|
# setup new directory
|
||||||
@ -680,12 +680,12 @@ def test_html_rebuild_mo(app):
|
|||||||
app.build()
|
app.build()
|
||||||
# --- rebuild by .mo mtime
|
# --- rebuild by .mo mtime
|
||||||
app.builder.build_update()
|
app.builder.build_update()
|
||||||
updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
|
updated = app.env.update(app.config, app.srcdir, app.doctreedir)
|
||||||
assert len(updated) == 0
|
assert len(updated) == 0
|
||||||
|
|
||||||
mtime = (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').stat().st_mtime
|
mtime = (app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').stat().st_mtime
|
||||||
(app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime((mtime + 5, mtime + 5))
|
(app.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').utime((mtime + 5, mtime + 5))
|
||||||
updated = app.env.update(app.config, app.srcdir, app.doctreedir, app)
|
updated = app.env.update(app.config, app.srcdir, app.doctreedir)
|
||||||
assert len(updated) == 1
|
assert len(updated) == 1
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user