+++ /dev/null
-"""Filename matching with shell patterns.\r
-\r
-fnmatch(FILENAME, PATTERN) matches according to the local convention.\r
-fnmatchcase(FILENAME, PATTERN) always takes case in account.\r
-\r
-The functions operate by translating the pattern into a regular\r
-expression. They cache the compiled regular expressions for speed.\r
-\r
-The function translate(PATTERN) returns a regular expression\r
-corresponding to PATTERN. (It does not compile it.)\r
-"""\r
-\r
-import re\r
-\r
-__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"]\r
-\r
-_cache = {}\r
-_MAXCACHE = 100\r
-\r
-def _purge():\r
- """Clear the pattern cache"""\r
- _cache.clear()\r
-\r
-def fnmatch(name, pat):\r
- """Test whether FILENAME matches PATTERN.\r
-\r
- Patterns are Unix shell style:\r
-\r
- * matches everything\r
- ? matches any single character\r
- [seq] matches any character in seq\r
- [!seq] matches any char not in seq\r
-\r
- An initial period in FILENAME is not special.\r
- Both FILENAME and PATTERN are first case-normalized\r
- if the operating system requires it.\r
- If you don't want this, use fnmatchcase(FILENAME, PATTERN).\r
- """\r
-\r
- import os\r
- name = os.path.normcase(name)\r
- pat = os.path.normcase(pat)\r
- return fnmatchcase(name, pat)\r
-\r
-def filter(names, pat):\r
- """Return the subset of the list NAMES that match PAT"""\r
- import os,posixpath\r
- result=[]\r
- pat=os.path.normcase(pat)\r
- try:\r
- re_pat = _cache[pat]\r
- except KeyError:\r
- res = translate(pat)\r
- if len(_cache) >= _MAXCACHE:\r
- _cache.clear()\r
- _cache[pat] = re_pat = re.compile(res)\r
- match = re_pat.match\r
- if os.path is posixpath:\r
- # normcase on posix is NOP. Optimize it away from the loop.\r
- for name in names:\r
- if match(name):\r
- result.append(name)\r
- else:\r
- for name in names:\r
- if match(os.path.normcase(name)):\r
- result.append(name)\r
- return result\r
-\r
-def fnmatchcase(name, pat):\r
- """Test whether FILENAME matches PATTERN, including case.\r
-\r
- This is a version of fnmatch() which doesn't case-normalize\r
- its arguments.\r
- """\r
-\r
- try:\r
- re_pat = _cache[pat]\r
- except KeyError:\r
- res = translate(pat)\r
- if len(_cache) >= _MAXCACHE:\r
- _cache.clear()\r
- _cache[pat] = re_pat = re.compile(res)\r
- return re_pat.match(name) is not None\r
-\r
-def translate(pat):\r
- """Translate a shell PATTERN to a regular expression.\r
-\r
- There is no way to quote meta-characters.\r
- """\r
-\r
- i, n = 0, len(pat)\r
- res = ''\r
- while i < n:\r
- c = pat[i]\r
- i = i+1\r
- if c == '*':\r
- res = res + '.*'\r
- elif c == '?':\r
- res = res + '.'\r
- elif c == '[':\r
- j = i\r
- if j < n and pat[j] == '!':\r
- j = j+1\r
- if j < n and pat[j] == ']':\r
- j = j+1\r
- while j < n and pat[j] != ']':\r
- j = j+1\r
- if j >= n:\r
- res = res + '\\['\r
- else:\r
- stuff = pat[i:j].replace('\\','\\\\')\r
- i = j+1\r
- if stuff[0] == '!':\r
- stuff = '^' + stuff[1:]\r
- elif stuff[0] == '^':\r
- stuff = '\\' + stuff\r
- res = '%s[%s]' % (res, stuff)\r
- else:\r
- res = res + re.escape(c)\r
- return res + '\Z(?ms)'\r