From 5cb64a7228d1c62be79378143c53beb3302e8067 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Thu, 7 Jan 2010 16:39:59 +0100 Subject: [PATCH] Apply static path exclusion patterns again. Refactor exclusion stuff a bit, so that matchers only have to be compiled once. --- sphinx/builders/html.py | 12 ++++++++---- sphinx/environment.py | 16 +++++++++------- sphinx/util/__init__.py | 29 ++++++++++++++++++----------- tests/test_build_html.py | 2 +- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 46ed69917..31af59033 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -29,7 +29,7 @@ from docutils.readers.doctree import Reader as DoctreeReader from sphinx import package_dir, __version__ 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.search import js_index from sphinx.theming import Theme @@ -562,16 +562,20 @@ class StandaloneHTMLBuilder(Builder): for themepath in self.theme.get_dirchain()[::-1]] for entry in themeentries: 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 staticentries = [path.join(self.confdir, spath) 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: if not path.exists(entry): self.warn('html_static_path entry %r does not exist' % entry) continue - copy_static_entry(entry, path.join(self.outdir, '_static'), - self, self.globalcontext) + copy_static_entry(entry, path.join(self.outdir, '_static'), self, + self.globalcontext, exclude_matchers=matchers) # last, copy logo file (handled differently XXX why?) if self.config.html_logo: logobase = path.basename(self.config.html_logo) diff --git a/sphinx/environment.py b/sphinx/environment.py index 781d8b5c7..1b89b8c06 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -35,7 +35,7 @@ from docutils.transforms.parts import ContentsFilter from sphinx import addnodes 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.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. """ - patterns = config.exclude_patterns[:] - patterns += config.exclude_trees - patterns += [d + config.source_suffix for d in config.unused_docs] - patterns += ['**/' + d for d in config.exclude_dirnames] - patterns += ['**/_sources'] + matchers = compile_matchers( + config.exclude_patterns[:] + + config.exclude_trees + + [d + config.source_suffix for d in config.unused_docs] + + ['**/' + d for d in config.exclude_dirnames] + + ['**/_sources'] + ) 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): """ diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 2dbec72fe..ab277f4a1 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -24,6 +24,8 @@ import traceback from os import path import docutils +from docutils.utils import relative_path + import sphinx # Errnos that we need. @@ -101,19 +103,16 @@ def walk(top, topdown=True, followlinks=False): 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. - 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 = path.normpath(path.abspath(dirname)) 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): relativeroot = root[dirlen:] @@ -121,7 +120,7 @@ def get_matching_files(dirname, exclude_patterns=()): for dn in dirs) qfiles = enumerate(path.join(relativeroot, fn).replace(os.path.sep, SEP) for fn in files) - for matcher in matchers: + for matcher in exclude_matchers: qdirs = [entry for entry in qdirs 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 -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 directory, recursively. @@ -139,7 +138,7 @@ def get_matching_docs(dirname, suffix, exclude_patterns=()): Exclude files and dirs matching a pattern in *exclude_patterns*. """ 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): continue yield filename[:-len(suffix)] @@ -280,6 +279,9 @@ def _translate_pattern(pat): res += re.escape(c) return res + '$' +def compile_matchers(patterns): + return [re.compile(_translate_pattern(pat)).match for pat in patterns] + _pat_cache = {} @@ -433,8 +435,12 @@ def copyfile(source, dest): def copy_static_entry(source, targetdir, builder, context={}, - exclude=True, level=0): - # XXX: exclusion + exclude_matchers=(), level=0): + if exclude_matchers: + relpath = relative_path(builder.srcdir, source) + for matcher in exclude_matchers: + if matcher(relpath): + return if path.isfile(source): target = path.join(targetdir, path.basename(source)) if source.lower().endswith('_t') and builder.templates: @@ -452,7 +458,8 @@ def copy_static_entry(source, targetdir, builder, context={}, if entry.startswith('.'): continue copy_static_entry(path.join(source, entry), targetdir, - builder, context, level=1) + builder, context, level=1, + exclude_matchers=exclude_matchers) else: target = path.join(targetdir, path.basename(source)) if path.exists(target): diff --git a/tests/test_build_html.py b/tests/test_build_html.py index f4a4aa21d..37d57dd5c 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -178,7 +178,7 @@ def check_static_entries(outdir): assert (staticdir / 'templated.css').isfile() assert (staticdir / 'templated.css').text().splitlines()[1] == __version__ # 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, confoverrides={'html_context.hckey_co': 'hcval_co'},