Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/glob2/fnmatch.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 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 re | |
| 14 try: | |
| 15 from functools import lru_cache | |
| 16 except ImportError: | |
| 17 from .compat import lru_cache | |
| 18 | |
| 19 __all__ = ["filter", "fnmatch", "fnmatchcase", "translate"] | |
| 20 | |
| 21 | |
| 22 def _norm_paths(path, norm_paths, sep): | |
| 23 if norm_paths is None: | |
| 24 path = re.sub(r'\/', sep or os.sep, path) # cached internally | |
| 25 elif norm_paths: | |
| 26 path = os.path.normcase(path) | |
| 27 return path | |
| 28 | |
| 29 | |
| 30 def fnmatch(name, pat, norm_paths=True, case_sensitive=True, sep=None): | |
| 31 """Test whether FILENAME matches PATTERN. | |
| 32 | |
| 33 Patterns are Unix shell style: | |
| 34 | |
| 35 * matches everything | |
| 36 ? matches any single character | |
| 37 [seq] matches any character in seq | |
| 38 [!seq] matches any char not in seq | |
| 39 | |
| 40 An initial period in FILENAME is not special. | |
| 41 Both FILENAME and PATTERN are first case-normalized | |
| 42 if the operating system requires it. | |
| 43 If you don't want this, use fnmatchcase(FILENAME, PATTERN). | |
| 44 | |
| 45 :param slashes: | |
| 46 :param norm_paths: | |
| 47 A tri-state boolean: | |
| 48 when true, invokes `os.path,.normcase()` on both paths, | |
| 49 when `None`, just equalize slashes/backslashes to `os.sep`, | |
| 50 when false, does not touch paths at all. | |
| 51 | |
| 52 Note that a side-effect of `normcase()` on *Windows* is that | |
| 53 it converts to lower-case all matches of `?glob()` functions. | |
| 54 :param case_sensitive: | |
| 55 defines the case-sensitiviness of regex doing the matches | |
| 56 :param sep: | |
| 57 in case only slahes replaced, what sep-char to substitute with; | |
| 58 if false, `os.sep` is used. | |
| 59 | |
| 60 Notice that by default, `normcase()` causes insensitive matching | |
| 61 on *Windows*, regardless of `case_insensitive` param. | |
| 62 Set ``norm_paths=None, case_sensitive=False`` to preserve | |
| 63 verbatim mathces. | |
| 64 """ | |
| 65 name, pat = [_norm_paths(p, norm_paths, sep) | |
| 66 for p in (name, pat)] | |
| 67 | |
| 68 return fnmatchcase(name, pat, case_sensitive=case_sensitive) | |
| 69 | |
| 70 | |
| 71 @lru_cache(maxsize=256, typed=True) | |
| 72 def _compile_pattern(pat, case_sensitive): | |
| 73 if isinstance(pat, bytes): | |
| 74 pat_str = pat.decode('ISO-8859-1') | |
| 75 res_str = translate(pat_str) | |
| 76 res = res_str.encode('ISO-8859-1') | |
| 77 else: | |
| 78 res = translate(pat) | |
| 79 flags = 0 if case_sensitive else re.IGNORECASE | |
| 80 return re.compile(res, flags).match | |
| 81 | |
| 82 | |
| 83 def filter(names, pat, norm_paths=True, case_sensitive=True, sep=None): | |
| 84 """Return the subset of the list NAMES that match PAT.""" | |
| 85 result = [] | |
| 86 pat = _norm_paths(pat, norm_paths, sep) | |
| 87 match = _compile_pattern(pat, case_sensitive) | |
| 88 for name in names: | |
| 89 m = match(_norm_paths(name, norm_paths, sep)) | |
| 90 if m: | |
| 91 result.append((name, | |
| 92 tuple(_norm_paths(p, norm_paths, sep) for p in m.groups()))) | |
| 93 return result | |
| 94 | |
| 95 | |
| 96 def fnmatchcase(name, pat, case_sensitive=True): | |
| 97 """Test whether FILENAME matches PATTERN, including case. | |
| 98 | |
| 99 This is a version of fnmatch() which doesn't case-normalize | |
| 100 its arguments. | |
| 101 """ | |
| 102 match = _compile_pattern(pat, case_sensitive) | |
| 103 return match(name) is not None | |
| 104 | |
| 105 | |
| 106 def translate(pat): | |
| 107 """Translate a shell PATTERN to a regular expression. | |
| 108 | |
| 109 There is no way to quote meta-characters. | |
| 110 """ | |
| 111 | |
| 112 i, n = 0, len(pat) | |
| 113 res = '' | |
| 114 while i < n: | |
| 115 c = pat[i] | |
| 116 i = i+1 | |
| 117 if c == '*': | |
| 118 res = res + '(.*)' | |
| 119 elif c == '?': | |
| 120 res = res + '(.)' | |
| 121 elif c == '[': | |
| 122 j = i | |
| 123 if j < n and pat[j] == '!': | |
| 124 j = j+1 | |
| 125 if j < n and pat[j] == ']': | |
| 126 j = j+1 | |
| 127 while j < n and pat[j] != ']': | |
| 128 j = j+1 | |
| 129 if j >= n: | |
| 130 res = res + '\\[' | |
| 131 else: | |
| 132 stuff = pat[i:j].replace('\\','\\\\') | |
| 133 i = j+1 | |
| 134 if stuff[0] == '!': | |
| 135 stuff = '^' + stuff[1:] | |
| 136 elif stuff[0] == '^': | |
| 137 stuff = '\\' + stuff | |
| 138 res = '%s([%s])' % (res, stuff) | |
| 139 else: | |
| 140 res = res + re.escape(c) | |
| 141 return '(?ms)' + res + '\Z' |
