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)' |
