Module lib.tools.fnmatch

Unix filename pattern matching. Extracted from cpython fnmatch.py

Expand source code
"""  Unix filename pattern matching.
Extracted from cpython fnmatch.py """
# pylint:disable=consider-using-f-string

import re

previous_pat = [None, None]
def fnmatch(name, pat):
        """ Compare filenames """
        if pat == "*":
                return True
        elif pat == "*.*":
                if name.find(".") != -1:
                        return True
                else:
                        return False
        else:
                global previous_pat
                if previous_pat[0] == pat:
                        res = previous_pat[1]
                else:
                        res = translate(pat)
                        previous_pat =[pat, res]
                return re.compile(res).match(name) is not None

def escape(pattern):
        """ Manage escape in pattern """
        result = ""
        for char in pattern:
                if char in '()[]{}?*+-|^$\\.&~# \t\n\r\v\f':
                        result += "\\"
                result += char
        return result

def translate(pat):
        """ Translate pattern """
        i, n = 0, len(pat)
        res = ''
        while i < n:
                c = pat[i]
                i = i+1
                if c == '*':
                        res = res + '.*'
                elif c == '?':
                        res = res + '.'
                elif c == '[':
                        j = i
                        if j < n and pat[j] == '!':
                                j = j+1
                        if j < n and pat[j] == ']':
                                j = j+1
                        while j < n and pat[j] != ']':
                                j = j+1
                        if j >= n:
                                res = res + '\\['
                        else:
                                stuff = pat[i:j]
                                if '--' not in stuff:
                                        stuff = stuff.replace('\\', r'\\')
                                else:
                                        chunks = []
                                        k = i+2 if pat[i] == '!' else i+1
                                        while True:
                                                k = pat.find('-', k, j)
                                                if k < 0:
                                                        break
                                                chunks.append(pat[i:k])
                                                i = k+1
                                                k = k+3
                                        chunks.append(pat[i:j])
                                        # Escape backslashes and hyphens for set difference (--).
                                        # Hyphens that create ranges shouldn't be escaped.
                                        stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-')
                                                                         for s in chunks)
                                # Escape set operations (&&, ~~ and ||).
                                stuff = re.sub(r'([&~|])', r'\\\1', stuff)
                                i = j+1
                                if stuff[0] == '!':
                                        stuff = '^' + stuff[1:]
                                elif stuff[0] in ('^', '['):
                                        stuff = '\\' + stuff
                                res = '%s[%s]' % (res, stuff)
                else:
                        res = res + escape(c)
        return r'^%s$' % res

Functions

def escape(pattern)

Manage escape in pattern

Expand source code
def escape(pattern):
        """ Manage escape in pattern """
        result = ""
        for char in pattern:
                if char in '()[]{}?*+-|^$\\.&~# \t\n\r\v\f':
                        result += "\\"
                result += char
        return result
def fnmatch(name, pat)

Compare filenames

Expand source code
def fnmatch(name, pat):
        """ Compare filenames """
        if pat == "*":
                return True
        elif pat == "*.*":
                if name.find(".") != -1:
                        return True
                else:
                        return False
        else:
                global previous_pat
                if previous_pat[0] == pat:
                        res = previous_pat[1]
                else:
                        res = translate(pat)
                        previous_pat =[pat, res]
                return re.compile(res).match(name) is not None
def translate(pat)

Translate pattern

Expand source code
def translate(pat):
        """ Translate pattern """
        i, n = 0, len(pat)
        res = ''
        while i < n:
                c = pat[i]
                i = i+1
                if c == '*':
                        res = res + '.*'
                elif c == '?':
                        res = res + '.'
                elif c == '[':
                        j = i
                        if j < n and pat[j] == '!':
                                j = j+1
                        if j < n and pat[j] == ']':
                                j = j+1
                        while j < n and pat[j] != ']':
                                j = j+1
                        if j >= n:
                                res = res + '\\['
                        else:
                                stuff = pat[i:j]
                                if '--' not in stuff:
                                        stuff = stuff.replace('\\', r'\\')
                                else:
                                        chunks = []
                                        k = i+2 if pat[i] == '!' else i+1
                                        while True:
                                                k = pat.find('-', k, j)
                                                if k < 0:
                                                        break
                                                chunks.append(pat[i:k])
                                                i = k+1
                                                k = k+3
                                        chunks.append(pat[i:j])
                                        # Escape backslashes and hyphens for set difference (--).
                                        # Hyphens that create ranges shouldn't be escaped.
                                        stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-')
                                                                         for s in chunks)
                                # Escape set operations (&&, ~~ and ||).
                                stuff = re.sub(r'([&~|])', r'\\\1', stuff)
                                i = j+1
                                if stuff[0] == '!':
                                        stuff = '^' + stuff[1:]
                                elif stuff[0] in ('^', '['):
                                        stuff = '\\' + stuff
                                res = '%s[%s]' % (res, stuff)
                else:
                        res = res + escape(c)
        return r'^%s$' % res