Add new universal config value `exclude_patterns`, with glob-style exclude patterns.

This makes the old ``unused_docs``, ``exclude_trees`` and ``exclude_dirnames`` obsolete.
This commit is contained in:
Georg Brandl
2010-01-06 15:48:39 +01:00
parent c3c3f739af
commit ab7ac64e1a
10 changed files with 99 additions and 40 deletions

View File

@@ -1,6 +1,10 @@
Release 1.0 (in development)
============================
* The new universal config value ``exclude_patterns`` makes the
old ``unused_docs``, ``exclude_trees`` and ``exclude_dirnames``
obsolete.
* Remove the deprecated ``exclude_dirs`` config value.
* #129: Wrap toctrees in a div tag with class ``toctree-wrapper``

View File

@@ -18,6 +18,8 @@ source_suffix = '.rst'
# The master toctree document.
master_doc = 'contents'
exclude_patterns = ['_build']
# General substitutions.
project = 'Sphinx'
copyright = '2007-2010, Georg Brandl'

View File

@@ -87,12 +87,37 @@ General configuration
The document name of the "master" document, that is, the document that
contains the root :dir:`toctree` directive. Default is ``'contents'``.
.. confval:: exclude_patterns
A list of glob-style patterns that should be excluded when looking for source
files. [#]_ They are matched against the source file names relative to the
source directory, using slashes as directory separators on all platforms.
Example patterns:
- ``'library/xml.rst'`` -- ignores the ``library/xml.rst`` file (replaces
entry in :confval:`unused_docs`
- ``'library/xml'`` -- ignores the ``library/xml`` directory (replaces entry
in :confval:`exclude_trees`)
- ``'library/xml*'`` -- ignores all files and directories starting with
``library/xml``
- ``'**/.svn'`` -- ignores all ``.svn`` directories (replaces entry in
:confval:`exclude_dirnames`)
:confval:`exclude_patterns` is also consulted when looking for static files
in :confval:`html_static_path`.
.. versionadded:: 1.0
.. confval:: unused_docs
A list of document names that are present, but not currently included in the
toctree. Use this setting to suppress the warning that is normally emitted
in that case.
.. deprecated:: 1.0
Use :confval:`exclude_patterns` instead.
.. confval:: exclude_trees
A list of directory paths, relative to the source directory, that are to be
@@ -101,6 +126,9 @@ General configuration
.. versionadded:: 0.4
.. deprecated:: 1.0
Use :confval:`exclude_patterns` instead.
.. confval:: exclude_dirnames
A list of directory names that are to be excluded from any recursive
@@ -110,6 +138,9 @@ General configuration
.. versionadded:: 0.5
.. deprecated:: 1.0
Use :confval:`exclude_patterns` instead.
.. confval:: locale_dirs
.. versionadded:: 0.5
@@ -797,3 +828,11 @@ These options influence LaTeX output.
.. deprecated:: 0.5
Use the ``'pointsize'`` key in the :confval:`latex_elements` value.
.. rubric:: Footnotes
.. [#] A note on available globbing syntax: you can use the standard shell
constructs ``*``, ``?``, ``[...]`` and ``[!...]`` with the feature that
these all don't match slashes. A double star ``**`` can be used to match
any sequence of characters *including* slashes.

View File

@@ -38,6 +38,8 @@ class Config(object):
master_doc = ('contents', 'env'),
source_suffix = ('.rst', 'env'),
source_encoding = ('utf-8-sig', 'env'),
exclude_patterns = ([], 'env'),
# the next three are all deprecated now
unused_docs = ([], 'env'),
exclude_trees = ([], 'env'),
exclude_dirnames = ([], 'env'),

View File

@@ -393,12 +393,13 @@ class BuildEnvironment:
"""
Find all source files in the source dir and put them in self.found_docs.
"""
exclude_trees = [d.replace(SEP, path.sep) for d in config.exclude_trees]
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']
self.found_docs = set(get_matching_docs(
self.srcdir, config.source_suffix,
exclude_docs=set(config.unused_docs),
exclude_trees=exclude_trees,
exclude_dirnames=['_sources'] + config.exclude_dirnames))
self.srcdir, config.source_suffix, exclude_patterns=patterns))
def get_outdated_files(self, config_changed):
"""

View File

@@ -84,12 +84,9 @@ release = '%(release_str)s'
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%%B %%d, %%Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = [%(exclude_trees)s]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = [%(exclude_patterns)s]
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
@@ -743,10 +740,10 @@ directly.'''
mkdir_p(srcdir)
if d['sep']:
builddir = path.join(d['path'], 'build')
d['exclude_trees'] = ''
d['exclude_patterns'] = ''
else:
builddir = path.join(srcdir, d['dot'] + 'build')
d['exclude_trees'] = repr(d['dot'] + 'build')
d['exclude_patterns'] = repr(d['dot'] + 'build')
mkdir_p(builddir)
mkdir_p(path.join(srcdir, d['dot'] + 'templates'))
mkdir_p(path.join(srcdir, d['dot'] + 'static'))

View File

@@ -101,38 +101,48 @@ def walk(top, topdown=True, followlinks=False):
yield top, dirs, nondirs
def get_matching_docs(dirname, suffix, exclude_docs=(), exclude_dirs=(),
exclude_trees=(), exclude_dirnames=()):
def get_matching_files(dirname, exclude_patterns=()):
"""
Get all file names in a directory, recursively.
Exclude files and dirs matching a pattern in *exclude_patterns*.
"""
# 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:]
qdirs = enumerate(path.join(relativeroot, dir).replace(os.path.sep, SEP)
for dir in dirs)
qfiles = enumerate(path.join(relativeroot, file).replace(os.path.sep, SEP)
for file in files)
for matcher in matchers:
qdirs = [entry for entry in qdirs if not matcher(entry[1])]
qfiles = [entry for entry in qfiles if not matcher(entry[1])]
dirs[:] = sorted(dirs[i] for (i, _) in qdirs)
for i, filename in sorted(qfiles):
yield filename
def get_matching_docs(dirname, suffix, exclude_patterns=()):
"""
Get all file names (without suffix) matching a suffix in a
directory, recursively.
Exclude docs in *exclude_docs*, exclude dirs in *exclude_dirs*,
prune dirs in *exclude_trees*, prune dirnames in *exclude_dirnames*.
Exclude files and dirs matching a pattern in *exclude_patterns*.
"""
pattern = '*' + suffix
# dirname is a normalized absolute path.
dirname = path.normpath(path.abspath(dirname))
dirlen = len(dirname) + 1 # exclude slash
for root, dirs, files in walk(dirname, followlinks=True):
if root[dirlen:] in exclude_dirs:
suffixpattern = '*' + suffix
for filename in get_matching_files(dirname, exclude_patterns):
if not fnmatch.fnmatch(filename, suffixpattern):
continue
if root[dirlen:] in exclude_trees:
del dirs[:]
continue
dirs.sort()
files.sort()
for prunedir in exclude_dirnames:
if prunedir in dirs:
dirs.remove(prunedir)
for sfile in files:
if not fnmatch.fnmatch(sfile, pattern):
continue
qualified_name = path.join(root[dirlen:], sfile[:-len(suffix)])
qualified_name = qualified_name.replace(os.path.sep, SEP)
if qualified_name in exclude_docs:
continue
yield qualified_name
yield filename[:-len(suffix)]
def mtimes_of_files(dirnames, suffix):

View File

@@ -22,7 +22,7 @@ version = '0.6'
release = '0.6alpha1'
today_fmt = '%B %d, %Y'
#unused_docs = []
exclude_trees = ['_build']
exclude_patterns = ['_build', '**/excluded.*']
keep_warnings = True
pygments_style = 'sphinx'

View File

@@ -0,0 +1,2 @@
Excluded file -- should *not* be read as source
-----------------------------------------------

View File

@@ -43,6 +43,8 @@ def test_first_update():
for docname in it: # the generator does all the work
docnames.add(docname)
assert docnames == env.found_docs == set(env.all_docs)
# test if exclude_patterns works ok
assert 'subdir/excluded' not in env.found_docs
def test_images():
assert warning_emitted('images.txt', 'image file not readable: foo.png')