comparison venv/lib/python2.7/site-packages/glob2/fnmatch.py @ 0:d67268158946 draft

planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
author bcclaywell
date Mon, 12 Oct 2015 17:43:33 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d67268158946
1 """Filename matching with shell patterns.
2
3 fnmatch(FILENAME, PATTERN) matches according to the local convention.
4 fnmatchcase(FILENAME, PATTERN) always takes case in account.
5
6 The functions operate by translating the pattern into a regular
7 expression. They cache the compiled regular expressions for speed.
8
9 The function translate(PATTERN) returns a regular expression
10 corresponding to PATTERN. (It does not compile it.)
11 """
12 import os
13 import posixpath
14 import re
15 try:
16 from functools import lru_cache
17 except ImportError:
18 from .compat import lru_cache
19
20 __all__ = ["filter", "fnmatch", "fnmatchcase", "translate"]
21
22 def fnmatch(name, pat):
23 """Test whether FILENAME matches PATTERN.
24
25 Patterns are Unix shell style:
26
27 * matches everything
28 ? matches any single character
29 [seq] matches any character in seq
30 [!seq] matches any char not in seq
31
32 An initial period in FILENAME is not special.
33 Both FILENAME and PATTERN are first case-normalized
34 if the operating system requires it.
35 If you don't want this, use fnmatchcase(FILENAME, PATTERN).
36 """
37 name = os.path.normcase(name)
38 pat = os.path.normcase(pat)
39 return fnmatchcase(name, pat)
40
41 lru_cache(maxsize=256, typed=True)
42 def _compile_pattern(pat):
43 if isinstance(pat, bytes):
44 pat_str = pat.decode('ISO-8859-1')
45 res_str = translate(pat_str)
46 res = res_str.encode('ISO-8859-1')
47 else:
48 res = translate(pat)
49 return re.compile(res).match
50
51 def filter(names, pat):
52 """Return the subset of the list NAMES that match PAT."""
53 result = []
54 pat = os.path.normcase(pat)
55 match = _compile_pattern(pat)
56 if os.path is posixpath:
57 # normcase on posix is NOP. Optimize it away from the loop.
58 for name in names:
59 m = match(name)
60 if m:
61 result.append((name, m.groups()))
62 else:
63 for name in names:
64 m = match(os.path.normcase(name))
65 if m:
66 result.append((name, m.groups()))
67 return result
68
69 def fnmatchcase(name, pat):
70 """Test whether FILENAME matches PATTERN, including case.
71
72 This is a version of fnmatch() which doesn't case-normalize
73 its arguments.
74 """
75 match = _compile_pattern(pat)
76 return match(name) is not None
77
78
79 def translate(pat):
80 """Translate a shell PATTERN to a regular expression.
81
82 There is no way to quote meta-characters.
83 """
84
85 i, n = 0, len(pat)
86 res = ''
87 while i < n:
88 c = pat[i]
89 i = i+1
90 if c == '*':
91 res = res + '(.*)'
92 elif c == '?':
93 res = res + '(.)'
94 elif c == '[':
95 j = i
96 if j < n and pat[j] == '!':
97 j = j+1
98 if j < n and pat[j] == ']':
99 j = j+1
100 while j < n and pat[j] != ']':
101 j = j+1
102 if j >= n:
103 res = res + '\\['
104 else:
105 stuff = pat[i:j].replace('\\','\\\\')
106 i = j+1
107 if stuff[0] == '!':
108 stuff = '^' + stuff[1:]
109 elif stuff[0] == '^':
110 stuff = '\\' + stuff
111 res = '%s([%s])' % (res, stuff)
112 else:
113 res = res + re.escape(c)
114 return res + '\Z(?ms)'