PageRenderTime 295ms CodeModel.GetById 140ms app.highlight 10ms RepoModel.GetById 142ms app.codeStats 0ms

/Lib/fnmatch.py

http://unladen-swallow.googlecode.com/
Python | 107 lines | 72 code | 4 blank | 31 comment | 0 complexity | 16984fd2319d814a98fc6a5e9a6b370e MD5 | raw file
  1"""Filename matching with shell patterns.
  2
  3fnmatch(FILENAME, PATTERN) matches according to the local convention.
  4fnmatchcase(FILENAME, PATTERN) always takes case in account.
  5
  6The functions operate by translating the pattern into a regular
  7expression.  They cache the compiled regular expressions for speed.
  8
  9The function translate(PATTERN) returns a regular expression
 10corresponding to PATTERN.  (It does not compile it.)
 11"""
 12
 13import re
 14
 15__all__ = ["filter", "fnmatch","fnmatchcase","translate"]
 16
 17_cache = {}
 18
 19def fnmatch(name, pat):
 20    """Test whether FILENAME matches PATTERN.
 21
 22    Patterns are Unix shell style:
 23
 24    *       matches everything
 25    ?       matches any single character
 26    [seq]   matches any character in seq
 27    [!seq]  matches any char not in seq
 28
 29    An initial period in FILENAME is not special.
 30    Both FILENAME and PATTERN are first case-normalized
 31    if the operating system requires it.
 32    If you don't want this, use fnmatchcase(FILENAME, PATTERN).
 33    """
 34
 35    import os
 36    name = os.path.normcase(name)
 37    pat = os.path.normcase(pat)
 38    return fnmatchcase(name, pat)
 39
 40def filter(names, pat):
 41    """Return the subset of the list NAMES that match PAT"""
 42    import os,posixpath
 43    result=[]
 44    pat=os.path.normcase(pat)
 45    if not pat in _cache:
 46        res = translate(pat)
 47        _cache[pat] = re.compile(res)
 48    match=_cache[pat].match
 49    if os.path is posixpath:
 50        # normcase on posix is NOP. Optimize it away from the loop.
 51        for name in names:
 52            if match(name):
 53                result.append(name)
 54    else:
 55        for name in names:
 56            if match(os.path.normcase(name)):
 57                result.append(name)
 58    return result
 59
 60def fnmatchcase(name, pat):
 61    """Test whether FILENAME matches PATTERN, including case.
 62
 63    This is a version of fnmatch() which doesn't case-normalize
 64    its arguments.
 65    """
 66
 67    if not pat in _cache:
 68        res = translate(pat)
 69        _cache[pat] = re.compile(res)
 70    return _cache[pat].match(name) is not None
 71
 72def translate(pat):
 73    """Translate a shell PATTERN to a regular expression.
 74
 75    There is no way to quote meta-characters.
 76    """
 77
 78    i, n = 0, len(pat)
 79    res = ''
 80    while i < n:
 81        c = pat[i]
 82        i = i+1
 83        if c == '*':
 84            res = res + '.*'
 85        elif c == '?':
 86            res = res + '.'
 87        elif c == '[':
 88            j = i
 89            if j < n and pat[j] == '!':
 90                j = j+1
 91            if j < n and pat[j] == ']':
 92                j = j+1
 93            while j < n and pat[j] != ']':
 94                j = j+1
 95            if j >= n:
 96                res = res + '\\['
 97            else:
 98                stuff = pat[i:j].replace('\\','\\\\')
 99                i = j+1
100                if stuff[0] == '!':
101                    stuff = '^' + stuff[1:]
102                elif stuff[0] == '^':
103                    stuff = '\\' + stuff
104                res = '%s[%s]' % (res, stuff)
105        else:
106            res = res + re.escape(c)
107    return res + "$"