Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(78)

Side by Side Diff: Lib/fnmatch.py

Issue 3055: combined patches from http://bugs.python.org/issue3187 (Closed) SVN Base: http://svn.python.org/view/*checkout*/python/branches/py3k/
Patch Set: Created 1 year, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file | Lib/glob.py » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.)
11 """ 11 """
12 12
13 import re 13 import re
14 import sys
14 15
15 __all__ = ["filter", "fnmatch","fnmatchcase","translate"] 16 __all__ = ["filter", "fnmatch","fnmatchcase","translate"]
16 17
17 _cache = {} 18 _cache = {}
18 19
19 def fnmatch(name, pat): 20 def fnmatch(name, pat):
20 """Test whether FILENAME matches PATTERN. 21 """Test whether FILENAME matches PATTERN.
21 22
22 Patterns are Unix shell style: 23 Patterns are Unix shell style:
23 24
24 * matches everything 25 * matches everything
25 ? matches any single character 26 ? matches any single character
26 [seq] matches any character in seq 27 [seq] matches any character in seq
27 [!seq] matches any char not in seq 28 [!seq] matches any char not in seq
28 29
29 An initial period in FILENAME is not special. 30 An initial period in FILENAME is not special.
30 Both FILENAME and PATTERN are first case-normalized 31 Both FILENAME and PATTERN are first case-normalized
31 if the operating system requires it. 32 if the operating system requires it.
32 If you don't want this, use fnmatchcase(FILENAME, PATTERN). 33 If you don't want this, use fnmatchcase(FILENAME, PATTERN).
33 """ 34 """
34 35
35 import os 36 import os
36 name = os.path.normcase(name) 37 name = os.path.normcase(name)
37 pat = os.path.normcase(pat) 38 pat = os.path.normcase(pat)
38 return fnmatchcase(name, pat) 39 return fnmatchcase(name, pat)
39 40
40 def filter(names, pat): 41 def filter(names, pat):
GvR 2008/08/22 19:04:51 I wonder if we shouldn't also support isinstance(p
41 """Return the subset of the list NAMES that match PAT""" 42 """Return the subset of the list NAMES that match PAT"""
42 import os,posixpath 43 import os,posixpath
43 result=[] 44 result=[]
44 pat=os.path.normcase(pat) 45 pat=os.path.normcase(pat)
45 if not pat in _cache: 46 if not pat in _cache:
46 res = translate(pat) 47 res = translate(pat)
47 _cache[pat] = re.compile(res) 48 _cache[pat] = re.compile(res)
49 else:
50 res = None
48 match=_cache[pat].match 51 match=_cache[pat].match
49 if os.path is posixpath: 52 match_bytes = None
50 # normcase on posix is NOP. Optimize it away from the loop. 53 for name in names:
GvR 2008/08/22 19:04:51 Why'd you get rid of this optimization?
51 for name in names: 54 if isinstance(name, bytes):
52 if match(name): 55 if not match_bytes:
56 # create match regex for bytes string
57 charset = sys.getfilesystemencoding()
58 pat = pat.encode(charset)
59 if not pat in _cache:
60 if res is None:
61 res = translate(pat)
62 res = res.encode(charset)
63 _cache[pat] = re.compile(res)
64 match_bytes = _cache[pat].match
65 if match_bytes(os.path.normcase(name)):
53 result.append(name) 66 result.append(name)
54 else: 67 elif match(os.path.normcase(name)):
55 for name in names:
56 if match(os.path.normcase(name)):
57 result.append(name) 68 result.append(name)
58 return result 69 return result
59 70
60 def fnmatchcase(name, pat): 71 def fnmatchcase(name, pat):
61 """Test whether FILENAME matches PATTERN, including case. 72 """Test whether FILENAME matches PATTERN, including case.
62 73
63 This is a version of fnmatch() which doesn't case-normalize 74 This is a version of fnmatch() which doesn't case-normalize
64 its arguments. 75 its arguments.
65 """ 76 """
66 77
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 stuff = pat[i:j].replace('\\','\\\\') 109 stuff = pat[i:j].replace('\\','\\\\')
99 i = j+1 110 i = j+1
100 if stuff[0] == '!': 111 if stuff[0] == '!':
101 stuff = '^' + stuff[1:] 112 stuff = '^' + stuff[1:]
102 elif stuff[0] == '^': 113 elif stuff[0] == '^':
103 stuff = '\\' + stuff 114 stuff = '\\' + stuff
104 res = '%s[%s]' % (res, stuff) 115 res = '%s[%s]' % (res, stuff)
105 else: 116 else:
106 res = res + re.escape(c) 117 res = res + re.escape(c)
107 return res + "$" 118 return res + "$"
OLDNEW
« no previous file | Lib/glob.py » ('j') | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld r497