[Python-checkins] r61884 - in doctools/trunk: CHANGES sphinx/builder.py sphinx/directives.py sphinx/environment.py sphinx/ext/doctest.py sphinx/linkcheck.py
georg.brandl
python-checkins at python.org
Tue Mar 25 11:16:52 CET 2008
Author: georg.brandl
Date: Tue Mar 25 11:16:51 2008
New Revision: 61884
Modified:
doctools/trunk/CHANGES
doctools/trunk/sphinx/builder.py
doctools/trunk/sphinx/directives.py
doctools/trunk/sphinx/environment.py
doctools/trunk/sphinx/ext/doctest.py
doctools/trunk/sphinx/linkcheck.py
Log:
Add a dependency system for handling .. include, .. literalinclude
and later .. image dependencies.
Modified: doctools/trunk/CHANGES
==============================================================================
--- doctools/trunk/CHANGES (original)
+++ doctools/trunk/CHANGES Tue Mar 25 11:16:51 2008
@@ -1,3 +1,10 @@
+Changes in trunk
+================
+
+* sphinx.environment: Take dependent files into account when collecting
+ the set of outdated sources.
+
+
Release 0.1.61843 (Mar 24, 2008)
================================
Modified: doctools/trunk/sphinx/builder.py
==============================================================================
--- doctools/trunk/sphinx/builder.py (original)
+++ doctools/trunk/sphinx/builder.py Tue Mar 25 11:16:51 2008
@@ -127,8 +127,7 @@
# build methods
def load_env(self):
- """Set up the build environment. Return True if a pickled file could be
- successfully loaded, False if a new environment had to be created."""
+ """Set up the build environment."""
if self.env:
return
if not self.freshenv:
@@ -143,8 +142,10 @@
else:
self.info('failed: %s' % err)
self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
+ self.env.find_files(self.config)
else:
self.env = BuildEnvironment(self.srcdir, self.doctreedir, self.config)
+ self.env.find_files(self.config)
self.env.set_warnfunc(self.warn)
def build_all(self):
@@ -171,10 +172,6 @@
def build_update(self):
"""Only rebuild files changed or added since last build."""
to_build = self.get_outdated_docs()
- if not to_build and self.env.all_docs:
- # if there is nothing in all_docs, it's a fresh env
- self.info(bold('no target files are out of date, exiting.'))
- return
if isinstance(to_build, str):
self.build([], to_build)
else:
@@ -213,6 +210,10 @@
# global actions
self.info(bold('checking consistency...'))
self.env.check_consistency()
+ else:
+ if not docnames:
+ self.info(bold('no targets are out of date.'))
+ return
# another indirection to support methods which don't build files
# individually
@@ -222,14 +223,15 @@
self.info(bold('finishing... '))
self.finish()
if self.app._warncount:
- self.info(bold('build succeeded, %s warnings.' % self.app._warncount))
+ self.info(bold('build succeeded, %s warning%s.' %
+ (self.app._warncount, self.app._warncount != 1 and 's' or '')))
else:
self.info(bold('build succeeded.'))
def write(self, build_docnames, updated_docnames, method='update'):
if build_docnames is None:
# build_all
- build_docnames = self.env.all_docs
+ build_docnames = self.env.found_docs
if method == 'update':
# build updated ones as well
docnames = set(build_docnames) | set(updated_docnames)
@@ -383,7 +385,7 @@
self.handle_page(docname, ctx)
def finish(self):
- self.info(bold('writing additional files...'))
+ self.info(bold('writing additional files...'), nonl=1)
# the global general index
@@ -397,6 +399,7 @@
genindexentries = self.env.index,
genindexcounts = indexcounts,
)
+ self.info(' genindex', nonl=1)
self.handle_page('genindex', genindexcontext, 'genindex.html')
# the global module index
@@ -442,21 +445,26 @@
modindexentries = modindexentries,
platforms = platforms,
)
+ self.info(' modindex', nonl=1)
self.handle_page('modindex', modindexcontext, 'modindex.html')
# the search page
+ self.info(' search', nonl=1)
self.handle_page('search', {}, 'search.html')
# additional pages from conf.py
for pagename, template in self.config.html_additional_pages.items():
+ self.info(' '+pagename, nonl=1)
self.handle_page(pagename, {}, template)
# the index page
indextemplate = self.config.html_index
if indextemplate:
+ self.info(' index', nonl=1)
self.handle_page('index', {'indextemplate': indextemplate}, 'index.html')
# copy static files
+ self.info()
self.info(bold('copying static files...'))
ensuredir(path.join(self.outdir, 'static'))
staticdirnames = [path.join(path.dirname(__file__), 'static')] + \
@@ -481,10 +489,7 @@
return docname + '.html'
def get_outdated_docs(self):
- for docname in get_matching_docs(
- self.srcdir, self.config.source_suffix,
- exclude=set(self.config.unused_docs),
- prune=['_sources']):
+ for docname in self.env.found_docs:
targetname = self.env.doc2path(docname, self.outdir, '.html')
try:
targetmtime = path.getmtime(targetname)
@@ -566,10 +571,7 @@
self.init_translator_class()
def get_outdated_docs(self):
- for docname in get_matching_docs(
- self.srcdir, self.config.source_suffix,
- exclude=set(self.config.unused_docs),
- prune=['_sources']):
+ for docname in self.env.found_docs:
targetname = self.env.doc2path(docname, self.outdir, '.fpickle')
try:
targetmtime = path.getmtime(targetname)
Modified: doctools/trunk/sphinx/directives.py
==============================================================================
--- doctools/trunk/sphinx/directives.py (original)
+++ doctools/trunk/sphinx/directives.py Tue Mar 25 11:16:51 2008
@@ -664,10 +664,10 @@
if not state.document.settings.file_insertion_enabled:
return [state.document.reporter.warning('File insertion disabled', line=lineno)]
env = state.document.settings.env
- fn = arguments[0]
+ rel_fn = arguments[0]
source_dir = path.dirname(path.abspath(state_machine.input_lines.source(
lineno - state_machine.input_offset - 1)))
- fn = path.normpath(path.join(source_dir, fn))
+ fn = path.normpath(path.join(source_dir, rel_fn))
try:
f = open(fn)
@@ -683,6 +683,7 @@
retnode['language'] = options['language']
if 'linenos' in options:
retnode['linenos'] = True
+ state.document.settings.env.note_dependency(rel_fn)
return [retnode]
literalinclude_directive.options = {'linenos': directives.flag,
Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py (original)
+++ doctools/trunk/sphinx/environment.py Tue Mar 25 11:16:51 2008
@@ -57,7 +57,7 @@
# This is increased every time a new environment attribute is added
# to properly invalidate pickle files.
-ENV_VERSION = 18
+ENV_VERSION = 19
def walk_depth(node, depth, maxdepth):
@@ -218,8 +218,10 @@
# All "docnames" here are /-separated and relative and exclude the source suffix.
self.found_docs = set() # contains all existing docnames
- self.all_docs = {} # docname -> (mtime, md5sum) at the time of build
+ self.all_docs = {} # docname -> mtime at the time of build
# contains all built docnames
+ self.dependencies = {} # docname -> set of dependent file names, relative to
+ # documentation root
# File metadata
self.metadata = {} # docname -> dict of metadata items
@@ -278,6 +280,7 @@
if docname in self.all_docs:
self.all_docs.pop(docname, None)
self.metadata.pop(docname, None)
+ self.dependencies.pop(docname, None)
self.titles.pop(docname, None)
self.tocs.pop(docname, None)
self.toc_num_entries.pop(docname, None)
@@ -318,14 +321,18 @@
else:
return path.join(base, docname.replace(SEP, path.sep)) + suffix
- def get_outdated_files(self, config, config_changed):
+ def find_files(self, config):
"""
- Return (added, changed, removed) sets.
+ Find all source files in the source dir and put them in self.found_docs.
"""
self.found_docs = set(get_matching_docs(self.srcdir, config.source_suffix,
exclude=set(config.unused_docs),
prune=['_sources']))
+ def get_outdated_files(self, config_changed):
+ """
+ Return (added, changed, removed) sets.
+ """
# clear all files no longer present
removed = set(self.all_docs) - self.found_docs
@@ -339,17 +346,28 @@
for docname in self.found_docs:
if docname not in self.all_docs:
added.add(docname)
- else:
- # if the doctree file is not there, rebuild
- if not path.isfile(self.doc2path(docname, self.doctreedir,
- '.doctree')):
- changed.add(docname)
- continue
- mtime, md5sum = self.all_docs[docname]
- newmtime = path.getmtime(self.doc2path(docname))
- if newmtime == mtime:
- continue
+ continue
+ # if the doctree file is not there, rebuild
+ if not path.isfile(self.doc2path(docname, self.doctreedir,
+ '.doctree')):
changed.add(docname)
+ continue
+ # check the mtime of the document
+ mtime = self.all_docs[docname]
+ newmtime = path.getmtime(self.doc2path(docname))
+ if newmtime > mtime:
+ changed.add(docname)
+ continue
+ # finally, check the mtime of dependencies
+ for dep in self.dependencies.get(docname, ()):
+ deppath = path.join(self.srcdir, dep)
+ if not path.isfile(deppath):
+ changed.add(docname)
+ break
+ depmtime = path.getmtime(deppath)
+ if depmtime > mtime:
+ changed.add(docname)
+ break
return added, changed, removed
@@ -369,12 +387,14 @@
continue
if not hasattr(self.config, key) or \
self.config[key] != config[key]:
+
msg = '[config changed] '
config_changed = True
break
else:
msg = ''
- added, changed, removed = self.get_outdated_files(config, config_changed)
+ self.find_files(config)
+ added, changed, removed = self.get_outdated_files(config_changed)
msg += '%s added, %s changed, %s removed' % (len(added), len(changed),
len(removed))
yield msg
@@ -409,18 +429,14 @@
doctree = publish_doctree(None, src_path, FileInput,
settings_overrides=self.settings,
reader=MyStandaloneReader())
+ self.process_dependencies(docname, doctree)
self.process_metadata(docname, doctree)
self.create_title_from(docname, doctree)
self.note_labels_from(docname, doctree)
self.build_toc_from(docname, doctree)
- # calculate the MD5 of the file at time of build
- f = open(src_path, 'rb')
- try:
- md5sum = md5(f.read()).digest()
- finally:
- f.close()
- self.all_docs[docname] = (path.getmtime(src_path), md5sum)
+ # store time of reading, used to find outdated files
+ self.all_docs[docname] = time.time()
if app:
app.emit('doctree-read', doctree)
@@ -430,6 +446,7 @@
doctree.transformer = None
doctree.settings.warning_stream = None
doctree.settings.env = None
+ doctree.settings.record_dependencies = None
# cleanup
self.docname = None
@@ -452,6 +469,18 @@
else:
return doctree
+ def process_dependencies(self, docname, doctree):
+ """
+ Process docutils-generated dependency info.
+ """
+ deps = doctree.settings.record_dependencies
+ if not deps:
+ return
+ basename = path.dirname(self.doc2path(docname, base=None))
+ for dep in deps.list:
+ dep = path.join(basename, dep)
+ self.dependencies.setdefault(docname, set()).add(dep)
+
def process_metadata(self, docname, doctree):
"""
Process the docinfo part of the doctree as metadata.
@@ -602,6 +631,11 @@
def note_versionchange(self, type, version, node, lineno):
self.versionchanges.setdefault(version, []).append(
(type, self.docname, lineno, self.currmodule, self.currdesc, node.astext()))
+
+ def note_dependency(self, filename):
+ basename = path.dirname(self.doc2path(self.docname, base=None))
+ filename = path.join(basename, filename)
+ self.dependencies.setdefault(self.docname, set()).add(filename)
# -------
# --------- RESOLVING REFERENCES AND TOCTREES ------------------------------
Modified: doctools/trunk/sphinx/ext/doctest.py
==============================================================================
--- doctools/trunk/sphinx/ext/doctest.py (original)
+++ doctools/trunk/sphinx/ext/doctest.py Tue Mar 25 11:16:51 2008
@@ -183,7 +183,7 @@
return ''
def get_outdated_docs(self):
- return self.env.all_docs
+ return self.env.found_docs
def finish(self):
# write executive summary
@@ -204,7 +204,7 @@
def write(self, build_docnames, updated_docnames, method='update'):
if build_docnames is None:
- build_docnames = self.env.all_docs
+ build_docnames = sorted(self.env.all_docs)
self.info(bold('running tests...'))
for docname in build_docnames:
Modified: doctools/trunk/sphinx/linkcheck.py
==============================================================================
--- doctools/trunk/sphinx/linkcheck.py (original)
+++ doctools/trunk/sphinx/linkcheck.py Tue Mar 25 11:16:51 2008
@@ -42,7 +42,7 @@
return ''
def get_outdated_docs(self):
- return self.env.all_docs
+ return self.env.found_docs
def prepare_writing(self, docnames):
return
More information about the Python-checkins
mailing list