Mercurial > repos > bcclaywell > argo_navis
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)' |