Apply static path exclusion patterns again.

Refactor exclusion stuff a bit, so that matchers only have to be compiled once.
This commit is contained in:
Georg Brandl 2010-01-07 16:39:59 +01:00
parent c9345b33b2
commit 5cb64a7228
4 changed files with 36 additions and 23 deletions

View File

@ -29,7 +29,7 @@ from docutils.readers.doctree import Reader as DoctreeReader
from sphinx import package_dir, __version__ from sphinx import package_dir, __version__
from sphinx.util import SEP, os_path, relative_uri, ensuredir, \ from sphinx.util import SEP, os_path, relative_uri, ensuredir, \
movefile, ustrftime, copy_static_entry, copyfile movefile, ustrftime, copy_static_entry, copyfile, compile_matchers
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.search import js_index from sphinx.search import js_index
from sphinx.theming import Theme from sphinx.theming import Theme
@ -562,16 +562,20 @@ class StandaloneHTMLBuilder(Builder):
for themepath in self.theme.get_dirchain()[::-1]] for themepath in self.theme.get_dirchain()[::-1]]
for entry in themeentries: for entry in themeentries:
copy_static_entry(entry, path.join(self.outdir, '_static'), copy_static_entry(entry, path.join(self.outdir, '_static'),
self, self.globalcontext, exclude=False) self, self.globalcontext)
# then, copy over all user-supplied static files # then, copy over all user-supplied static files
staticentries = [path.join(self.confdir, spath) staticentries = [path.join(self.confdir, spath)
for spath in self.config.html_static_path] for spath in self.config.html_static_path]
matchers = compile_matchers(
self.config.exclude_patterns +
['**/' + d for d in self.config.exclude_dirnames]
)
for entry in staticentries: for entry in staticentries:
if not path.exists(entry): if not path.exists(entry):
self.warn('html_static_path entry %r does not exist' % entry) self.warn('html_static_path entry %r does not exist' % entry)
continue continue
copy_static_entry(entry, path.join(self.outdir, '_static'), copy_static_entry(entry, path.join(self.outdir, '_static'), self,
self, self.globalcontext) self.globalcontext, exclude_matchers=matchers)
# last, copy logo file (handled differently XXX why?) # last, copy logo file (handled differently XXX why?)
if self.config.html_logo: if self.config.html_logo:
logobase = path.basename(self.config.html_logo) logobase = path.basename(self.config.html_logo)

View File

@ -35,7 +35,7 @@ from docutils.transforms.parts import ContentsFilter
from sphinx import addnodes from sphinx import addnodes
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \ from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
docname_join, FilenameUniqDict, url_re, clean_astext docname_join, FilenameUniqDict, url_re, clean_astext, compile_matchers
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.directives import additional_xref_types from sphinx.directives import additional_xref_types
@ -393,13 +393,15 @@ class BuildEnvironment:
""" """
Find all source files in the source dir and put them in self.found_docs. Find all source files in the source dir and put them in self.found_docs.
""" """
patterns = config.exclude_patterns[:] matchers = compile_matchers(
patterns += config.exclude_trees config.exclude_patterns[:] +
patterns += [d + config.source_suffix for d in config.unused_docs] config.exclude_trees +
patterns += ['**/' + d for d in config.exclude_dirnames] [d + config.source_suffix for d in config.unused_docs] +
patterns += ['**/_sources'] ['**/' + d for d in config.exclude_dirnames] +
['**/_sources']
)
self.found_docs = set(get_matching_docs( self.found_docs = set(get_matching_docs(
self.srcdir, config.source_suffix, exclude_patterns=patterns)) self.srcdir, config.source_suffix, exclude_matchers=matchers))
def get_outdated_files(self, config_changed): def get_outdated_files(self, config_changed):
""" """

View File

@ -24,6 +24,8 @@ import traceback
from os import path from os import path
import docutils import docutils
from docutils.utils import relative_path
import sphinx import sphinx
# Errnos that we need. # Errnos that we need.
@ -101,19 +103,16 @@ def walk(top, topdown=True, followlinks=False):
yield top, dirs, nondirs yield top, dirs, nondirs
def get_matching_files(dirname, exclude_patterns=()): def get_matching_files(dirname, exclude_matchers=()):
""" """
Get all file names in a directory, recursively. Get all file names in a directory, recursively.
Exclude files and dirs matching a pattern in *exclude_patterns*. Exclude files and dirs matching some matcher in *exclude_matchers*.
""" """
# dirname is a normalized absolute path. # dirname is a normalized absolute path.
dirname = path.normpath(path.abspath(dirname)) dirname = path.normpath(path.abspath(dirname))
dirlen = len(dirname) + 1 # exclude final os.path.sep dirlen = len(dirname) + 1 # exclude final os.path.sep
matchers = [re.compile(_translate_pattern(pat)).match
for pat in exclude_patterns]
for root, dirs, files in walk(dirname, followlinks=True): for root, dirs, files in walk(dirname, followlinks=True):
relativeroot = root[dirlen:] relativeroot = root[dirlen:]
@ -121,7 +120,7 @@ def get_matching_files(dirname, exclude_patterns=()):
for dn in dirs) for dn in dirs)
qfiles = enumerate(path.join(relativeroot, fn).replace(os.path.sep, SEP) qfiles = enumerate(path.join(relativeroot, fn).replace(os.path.sep, SEP)
for fn in files) for fn in files)
for matcher in matchers: for matcher in exclude_matchers:
qdirs = [entry for entry in qdirs if not matcher(entry[1])] qdirs = [entry for entry in qdirs if not matcher(entry[1])]
qfiles = [entry for entry in qfiles if not matcher(entry[1])] qfiles = [entry for entry in qfiles if not matcher(entry[1])]
@ -131,7 +130,7 @@ def get_matching_files(dirname, exclude_patterns=()):
yield filename yield filename
def get_matching_docs(dirname, suffix, exclude_patterns=()): def get_matching_docs(dirname, suffix, exclude_matchers=()):
""" """
Get all file names (without suffix) matching a suffix in a Get all file names (without suffix) matching a suffix in a
directory, recursively. directory, recursively.
@ -139,7 +138,7 @@ def get_matching_docs(dirname, suffix, exclude_patterns=()):
Exclude files and dirs matching a pattern in *exclude_patterns*. Exclude files and dirs matching a pattern in *exclude_patterns*.
""" """
suffixpattern = '*' + suffix suffixpattern = '*' + suffix
for filename in get_matching_files(dirname, exclude_patterns): for filename in get_matching_files(dirname, exclude_matchers):
if not fnmatch.fnmatch(filename, suffixpattern): if not fnmatch.fnmatch(filename, suffixpattern):
continue continue
yield filename[:-len(suffix)] yield filename[:-len(suffix)]
@ -280,6 +279,9 @@ def _translate_pattern(pat):
res += re.escape(c) res += re.escape(c)
return res + '$' return res + '$'
def compile_matchers(patterns):
return [re.compile(_translate_pattern(pat)).match for pat in patterns]
_pat_cache = {} _pat_cache = {}
@ -433,8 +435,12 @@ def copyfile(source, dest):
def copy_static_entry(source, targetdir, builder, context={}, def copy_static_entry(source, targetdir, builder, context={},
exclude=True, level=0): exclude_matchers=(), level=0):
# XXX: exclusion if exclude_matchers:
relpath = relative_path(builder.srcdir, source)
for matcher in exclude_matchers:
if matcher(relpath):
return
if path.isfile(source): if path.isfile(source):
target = path.join(targetdir, path.basename(source)) target = path.join(targetdir, path.basename(source))
if source.lower().endswith('_t') and builder.templates: if source.lower().endswith('_t') and builder.templates:
@ -452,7 +458,8 @@ def copy_static_entry(source, targetdir, builder, context={},
if entry.startswith('.'): if entry.startswith('.'):
continue continue
copy_static_entry(path.join(source, entry), targetdir, copy_static_entry(path.join(source, entry), targetdir,
builder, context, level=1) builder, context, level=1,
exclude_matchers=exclude_matchers)
else: else:
target = path.join(targetdir, path.basename(source)) target = path.join(targetdir, path.basename(source))
if path.exists(target): if path.exists(target):

View File

@ -178,7 +178,7 @@ def check_static_entries(outdir):
assert (staticdir / 'templated.css').isfile() assert (staticdir / 'templated.css').isfile()
assert (staticdir / 'templated.css').text().splitlines()[1] == __version__ assert (staticdir / 'templated.css').text().splitlines()[1] == __version__
# a file from _static, but matches exclude_patterns # a file from _static, but matches exclude_patterns
##assert not (staticdir / 'excluded.css').exists() assert not (staticdir / 'excluded.css').exists()
@gen_with_app(buildername='html', warning=html_warnfile, cleanenv=True, @gen_with_app(buildername='html', warning=html_warnfile, cleanenv=True,
confoverrides={'html_context.hckey_co': 'hcval_co'}, confoverrides={'html_context.hckey_co': 'hcval_co'},