diff -r 40a1652349e9 Doc/library/fnmatch.rst --- a/Doc/library/fnmatch.rst Sun Oct 14 22:16:27 2012 +0200 +++ b/Doc/library/fnmatch.rst Sun Oct 14 23:02:18 2012 +0200 @@ -28,6 +28,8 @@ +------------+------------------------------------+ | ``[!seq]`` | matches any character not in *seq* | +------------+------------------------------------+ +| ``\`` | escapes the following char | ++------------+------------------------------------+ .. index:: module: glob diff -r 40a1652349e9 Lib/fnmatch.py --- a/Lib/fnmatch.py Sun Oct 14 22:16:27 2012 +0200 +++ b/Lib/fnmatch.py Sun Oct 14 23:02:18 2012 +0200 @@ -16,6 +16,7 @@ __all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] + def fnmatch(name, pat): """Test whether FILENAME matches PATTERN. @@ -25,6 +26,7 @@ ? matches any single character [seq] matches any character in seq [!seq] matches any char not in seq + \ escapes the following char An initial period in FILENAME is not special. Both FILENAME and PATTERN are first case-normalized @@ -81,21 +83,25 @@ res = '' while i < n: c = pat[i] - i = i+1 - if c == '*': - res = res + '.*' + i += 1 + + if c == '\\': + res += re.escape(pat[i]) + i += 1 + elif c == '*': + res += '.*' elif c == '?': - res = res + '.' + res += '.' elif c == '[': j = i if j < n and pat[j] == '!': - j = j+1 + j += 1 if j < n and pat[j] == ']': - j = j+1 + j += 1 while j < n and pat[j] != ']': - j = j+1 + j += 1 if j >= n: - res = res + '\\[' + res += '\\[' else: stuff = pat[i:j].replace('\\','\\\\') i = j+1 @@ -105,5 +111,5 @@ stuff = '\\' + stuff res = '%s[%s]' % (res, stuff) else: - res = res + re.escape(c) + res += re.escape(c) return res + '\Z(?ms)' diff -r 40a1652349e9 Lib/glob.py --- a/Lib/glob.py Sun Oct 14 22:16:27 2012 +0200 +++ b/Lib/glob.py Sun Oct 14 23:02:18 2012 +0200 @@ -26,25 +26,25 @@ return dirname, basename = os.path.split(pathname) if not dirname: - yield from glob1(None, basename) + yield from _glob_pattern(None, basename) return if has_magic(dirname): dirs = iglob(dirname) else: dirs = [dirname] if has_magic(basename): - glob_in_dir = glob1 + glob_in_dir = _glob_pattern else: - glob_in_dir = glob0 + glob_in_dir = _glob_literal for dirname in dirs: for name in glob_in_dir(dirname, basename): yield os.path.join(dirname, name) -# These 2 helper functions non-recursively glob inside a literal directory. -# They return a list of basenames. `glob1` accepts a pattern while `glob0` -# takes a literal basename (so it only has to check for its existence). +# These 2 helper functions non-recursively glob inside a literal directory and +# return a list of basenames. -def glob1(dirname, pattern): +def _glob_pattern(dirname, pattern): + """Return a list of basenames from the given pattern.""" if not dirname: if isinstance(pattern, bytes): dirname = bytes(os.curdir, 'ASCII') @@ -58,7 +58,9 @@ names = [x for x in names if x[0] != '.'] return fnmatch.filter(names, pattern) -def glob0(dirname, basename): +def _glob_literal(dirname, basename): + """Check for the existence of basename, and eventually return [basename]. + If basename was not found, return an empty list.""" if basename == '': # `os.path.split()` returns an empty basename for paths ending with a # directory separator. 'q*x/' should match only directories. diff -r 40a1652349e9 Lib/test/test_fnmatch.py --- a/Lib/test/test_fnmatch.py Sun Oct 14 22:16:27 2012 +0200 +++ b/Lib/test/test_fnmatch.py Sun Oct 14 23:02:18 2012 +0200 @@ -60,8 +60,6 @@ self.check_match(b'test\xff', b'te*\xff') self.check_match(b'foo\nbar', b'foo*') -class TranslateTestCase(unittest.TestCase): - def test_translate(self): self.assertEqual(translate('*'), '.*\Z(?ms)') self.assertEqual(translate('?'), '.\Z(?ms)') @@ -71,18 +69,17 @@ self.assertEqual(translate('[!x]'), '[^x]\Z(?ms)') self.assertEqual(translate('[^x]'), '[\\^x]\Z(?ms)') self.assertEqual(translate('[x'), '\\[x\Z(?ms)') - - -class FilterTestCase(unittest.TestCase): + # special chars preceeded by a backslash are escaped + self.assertEqual(translate('\[foo\]'), '\[foo\]\Z(?ms)') + self.assertEqual(translate(r'\\spam and ch\eese\* *'), + '\\\\spam\ and\ cheese\*\ .*\Z(?ms)') def test_filter(self): self.assertEqual(filter(['a', 'b'], 'a'), ['a']) def test_main(): - support.run_unittest(FnmatchTestCase, - TranslateTestCase, - FilterTestCase) + support.run_unittest(FnmatchTestCase) if __name__ == "__main__":