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