]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | import re |
2 | ||
3 | ||
4 | def translate(pattern): | |
5 | r""" | |
6 | Given a glob pattern, produce a regex that matches it. | |
7 | ||
8 | >>> translate('*.txt') | |
9 | '[^/]*\\.txt' | |
10 | >>> translate('a?txt') | |
11 | 'a[^/]txt' | |
12 | >>> translate('**/*') | |
13 | '.*/[^/]*' | |
14 | """ | |
15 | return ''.join(map(replace, separate(pattern))) | |
16 | ||
17 | ||
18 | def separate(pattern): | |
19 | """ | |
20 | Separate out character sets to avoid translating their contents. | |
21 | ||
22 | >>> [m.group(0) for m in separate('*.txt')] | |
23 | ['*.txt'] | |
24 | >>> [m.group(0) for m in separate('a[?]txt')] | |
25 | ['a', '[?]', 'txt'] | |
26 | """ | |
27 | return re.finditer(r'([^\[]+)|(?P<set>[\[].*?[\]])|([\[][^\]]*$)', pattern) | |
28 | ||
29 | ||
30 | def replace(match): | |
31 | """ | |
32 | Perform the replacements for a match from :func:`separate`. | |
33 | """ | |
34 | ||
35 | return match.group('set') or ( | |
36 | re.escape(match.group(0)) | |
37 | .replace('\\*\\*', r'.*') | |
38 | .replace('\\*', r'[^/]*') | |
39 | .replace('\\?', r'[^/]') | |
40 | ) |