diff --git a/sphinx_autobuild/filter.py b/sphinx_autobuild/filter.py index 456786f..407e844 100644 --- a/sphinx_autobuild/filter.py +++ b/sphinx_autobuild/filter.py @@ -3,6 +3,7 @@ import fnmatch import os import re +from glob import glob class IgnoreFilter: @@ -19,9 +20,28 @@ def __repr__(self): def __call__(self, path): """Determine if 'path' should be ignored.""" + # Return the full path so we make sure we handle relative paths OK + path_expanded = os.path.abspath(path) # Any regular pattern matches. for pattern in self.regular_patterns: - if path.startswith((pattern + os.sep, pattern + "/")): + # Expand the pattern into a list of files that match a glob + matched_files = set(map(os.path.abspath, glob(pattern, recursive=True))) + + if path_expanded in matched_files: + return True + + # If the parent of this path matches any of the glob matches, ignore it + if any(path_expanded.startswith(imatch) for imatch in matched_files): + return True + + # These two checks are for preserving old behavior. + # They might not be necessary but leaving here just in case. + # Neither depends on the files actually being on disk. + + if path.strip(os.path.sep).startswith(( + pattern.strip(os.path.sep) + os.path.sep, + pattern + "/", + )): return True if fnmatch.fnmatch(path, pattern): return True diff --git a/tests/test_ignore.py b/tests/test_ignore.py index fa6b0bd..2cdeafe 100644 --- a/tests/test_ignore.py +++ b/tests/test_ignore.py @@ -1,3 +1,5 @@ +from glob import glob + from sphinx_autobuild.filter import IgnoreFilter @@ -72,3 +74,25 @@ def test_multiple_both(): assert ignored("foo/random.txt") assert ignored("foo/module.pyc") assert ignored("bar/__pycache__/file.pyc") + + +def test_glob_expression(): + ignored = IgnoreFilter( + [ + # Glob for folder + "**/do_ignore", + # Glob for files + "**/*doignore*.*", + ], + [], + ) + # Root folder of our glob test files. Assume tests are run from project root. + for ifile in glob("tests/test_ignore_glob/**/*"): + # Convert to be relative to the tests directory since that mimics + # the user's behavior. + if "do_ignore" in ifile or "doignore" in ifile: + print(f"Should ignore: {ifile})") + assert ignored(ifile) + else: + print(f"Should NOT ignore: {ifile})") + assert not ignored(ifile) diff --git a/tests/test_ignore_glob/do_ignore/bar.txt b/tests/test_ignore_glob/do_ignore/bar.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_ignore/foo.txt b/tests/test_ignore_glob/do_ignore/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_ignore/nested/foo.txt b/tests/test_ignore_glob/do_ignore/nested/foo.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/1doignore.txt b/tests/test_ignore_glob/do_not_ignore/1doignore.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/1doignore1.txt b/tests/test_ignore_glob/do_not_ignore/1doignore1.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/doignore1.txt b/tests/test_ignore_glob/do_not_ignore/doignore1.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_ignore_glob/do_not_ignore/foo.txt b/tests/test_ignore_glob/do_not_ignore/foo.txt new file mode 100644 index 0000000..e69de29