diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst index c03a9d3..be697b0 100644 --- a/Doc/library/fnmatch.rst +++ b/Doc/library/fnmatch.rst @@ -71,6 +71,12 @@ patterns. Return the subset of the list of *names* that match *pattern*. It is the same as ``[n for n in names if fnmatch(n, pattern)]``, but implemented more efficiently. +.. function:: filter_false(names, pattern) + + Return the subset of the list of *names* that don't match *pattern*. It is the + same as ``[n for n in names if not fnmatch(n, pattern)]``, but implemented more + efficiently. + .. function:: translate(pattern) diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py index fd3b514..3a4b7ed 100644 --- a/Lib/fnmatch.py +++ b/Lib/fnmatch.py @@ -14,7 +14,7 @@ import posixpath import re import functools -__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] +__all__ = ["filter", "filter_false", "fnmatch", "fnmatchcase", "translate"] def fnmatch(name, pat): """Test whether FILENAME matches PATTERN. @@ -47,19 +47,23 @@ def _compile_pattern(pat): def filter(names, pat): """Return the subset of the list NAMES that match PAT.""" - result = [] pat = os.path.normcase(pat) match = _compile_pattern(pat) + return _filtered(names, match) + +def filter_false(names, pat): + """Return the subset of the list NAMES that don't match PAT.""" + pat = os.path.normcase(pat) + match = _compile_pattern(pat) + return _filtered(names, lambda name: match(name) is None) + +def _filtered(names, matcher): if os.path is posixpath: # normcase on posix is NOP. Optimize it away from the loop. - for name in names: - if match(name): - result.append(name) + return [name for name in names if matcher(name)] else: - for name in names: - if match(os.path.normcase(name)): - result.append(name) - return result + normcase = os.path.normcase + return [name for name in names if matcher(normcase(name))] def fnmatchcase(name, pat): """Test whether FILENAME matches PATTERN, including case. diff --git a/Lib/test/test_fnmatch.py b/Lib/test/test_fnmatch.py index fb74246..2e15ad3 100644 --- a/Lib/test/test_fnmatch.py +++ b/Lib/test/test_fnmatch.py @@ -2,7 +2,7 @@ import unittest -from fnmatch import fnmatch, fnmatchcase, translate, filter +from fnmatch import fnmatch, fnmatchcase, translate, filter, filter_false class FnmatchTestCase(unittest.TestCase): @@ -78,5 +78,11 @@ class FilterTestCase(unittest.TestCase): self.assertEqual(filter(['a', 'b'], 'a'), ['a']) +class FilterFalseTestCase(unittest.TestCase): + + def test_filter_false(self): + self.assertEqual(filter_false(['a', 'b'], 'a'), ['b']) + + if __name__ == "__main__": unittest.main()