| OLD | NEW |
| 1 """Filename matching with shell patterns. | 1 """Filename matching with shell patterns. |
| 2 | 2 |
| 3 fnmatch(FILENAME, PATTERN) matches according to the local convention. | 3 fnmatch(FILENAME, PATTERN) matches according to the local convention. |
| 4 fnmatchcase(FILENAME, PATTERN) always takes case in account. | 4 fnmatchcase(FILENAME, PATTERN) always takes case in account. |
| 5 | 5 |
| 6 The functions operate by translating the pattern into a regular | 6 The functions operate by translating the pattern into a regular |
| 7 expression. They cache the compiled regular expressions for speed. | 7 expression. They cache the compiled regular expressions for speed. |
| 8 | 8 |
| 9 The function translate(PATTERN) returns a regular expression | 9 The function translate(PATTERN) returns a regular expression |
| 10 corresponding to PATTERN. (It does not compile it.) | 10 corresponding to PATTERN. (It does not compile it.) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 An initial period in FILENAME is not special. | 29 An initial period in FILENAME is not special. |
| 30 Both FILENAME and PATTERN are first case-normalized | 30 Both FILENAME and PATTERN are first case-normalized |
| 31 if the operating system requires it. | 31 if the operating system requires it. |
| 32 If you don't want this, use fnmatchcase(FILENAME, PATTERN). | 32 If you don't want this, use fnmatchcase(FILENAME, PATTERN). |
| 33 """ | 33 """ |
| 34 | 34 |
| 35 import os | 35 import os |
| 36 name = os.path.normcase(name) | 36 name = os.path.normcase(name) |
| 37 pat = os.path.normcase(pat) | 37 pat = os.path.normcase(pat) |
| 38 return fnmatchcase(name, pat) | 38 return fnmatchcase(name, pat) |
| 39 |
| 40 def _compile_pattern(pat): |
| 41 if not pat in _cache: |
| 42 if isinstance(pat, bytes): |
| 43 pat_str = str(pat, 'ISO-8859-1') |
| 44 res_str = translate(pat_str) |
| 45 res = res_str.encode('ISO-8859-1') |
| 46 else: |
| 47 res = translate(pat) |
| 48 _cache[pat] = re.compile(res) |
| 49 return _cache[pat].match |
| 39 | 50 |
| 40 def filter(names, pat): | 51 def filter(names, pat): |
| 41 """Return the subset of the list NAMES that match PAT""" | 52 """Return the subset of the list NAMES that match PAT""" |
| 42 import os,posixpath | 53 import os,posixpath |
| 43 result=[] | 54 result=[] |
| 44 pat=os.path.normcase(pat) | 55 pat=os.path.normcase(pat) |
| 45 if not pat in _cache: | 56 match = _compile_pattern(pat) |
| 46 res = translate(pat) | |
| 47 _cache[pat] = re.compile(res) | |
| 48 match=_cache[pat].match | |
| 49 if os.path is posixpath: | 57 if os.path is posixpath: |
| 50 # normcase on posix is NOP. Optimize it away from the loop. | 58 # normcase on posix is NOP. Optimize it away from the loop. |
| 51 for name in names: | 59 for name in names: |
| 52 if match(name): | 60 if match(name): |
| 53 result.append(name) | 61 result.append(name) |
| 54 else: | 62 else: |
| 55 for name in names: | 63 for name in names: |
| 56 if match(os.path.normcase(name)): | 64 if match(os.path.normcase(name)): |
| 57 result.append(name) | 65 result.append(name) |
| 58 return result | 66 return result |
| 59 | 67 |
| 60 def fnmatchcase(name, pat): | 68 def fnmatchcase(name, pat): |
| 61 """Test whether FILENAME matches PATTERN, including case. | 69 """Test whether FILENAME matches PATTERN, including case. |
| 62 | 70 |
| 63 This is a version of fnmatch() which doesn't case-normalize | 71 This is a version of fnmatch() which doesn't case-normalize |
| 64 its arguments. | 72 its arguments. |
| 65 """ | 73 """ |
| 66 | 74 |
| 67 if not pat in _cache: | 75 match = _compile_pattern(pat) |
| 68 res = translate(pat) | 76 return match(name) is not None |
| 69 _cache[pat] = re.compile(res) | |
| 70 return _cache[pat].match(name) is not None | |
| 71 | 77 |
| 72 def translate(pat): | 78 def translate(pat): |
| 73 """Translate a shell PATTERN to a regular expression. | 79 """Translate a shell PATTERN to a regular expression. |
| 74 | 80 |
| 75 There is no way to quote meta-characters. | 81 There is no way to quote meta-characters. |
| 76 """ | 82 """ |
| 77 | 83 |
| 78 i, n = 0, len(pat) | 84 i, n = 0, len(pat) |
| 79 res = '' | 85 res = '' |
| 80 while i < n: | 86 while i < n: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 98 stuff = pat[i:j].replace('\\','\\\\') | 104 stuff = pat[i:j].replace('\\','\\\\') |
| 99 i = j+1 | 105 i = j+1 |
| 100 if stuff[0] == '!': | 106 if stuff[0] == '!': |
| 101 stuff = '^' + stuff[1:] | 107 stuff = '^' + stuff[1:] |
| 102 elif stuff[0] == '^': | 108 elif stuff[0] == '^': |
| 103 stuff = '\\' + stuff | 109 stuff = '\\' + stuff |
| 104 res = '%s[%s]' % (res, stuff) | 110 res = '%s[%s]' % (res, stuff) |
| 105 else: | 111 else: |
| 106 res = res + re.escape(c) | 112 res = res + re.escape(c) |
| 107 return res + "$" | 113 return res + "$" |
| OLD | NEW |