"""Filename matching with shell patterns.fnmatch(FILENAME, PATTERN) matches according to the local convention.fnmatchcase(FILENAME, PATTERN) always takes case in account.The functions operate by translating the pattern into a regularexpression. They cache the compiled regular expressions for speed.The function translate(PATTERN) returns a regular expressioncorresponding to PATTERN. (It does not compile it.)"""importre__all__=["filter","fnmatch","fnmatchcase","translate"]_cache={}# Maps text patterns to compiled regexen._cacheb={}# Ditto for bytes patterns.deffnmatch(name,pat):"""Test whether FILENAME matches PATTERN. Patterns are Unix shell style: * matches everything ? matches any single character [seq] matches any character in seq [!seq] matches any char not in seq An initial period in FILENAME is not special. Both FILENAME and PATTERN are first case-normalized if the operating system requires it. If you don't want this, use fnmatchcase(FILENAME, PATTERN). """importosname=os.path.normcase(name)pat=os.path.normcase(pat)returnfnmatchcase(name,pat)def_compile_pattern(pat):cache=_cachebifisinstance(pat,bytes)else_cacheregex=cache.get(pat)ifregexisNone:ifisinstance(pat,bytes):pat_str=str(pat,'ISO-8859-1')res_str=translate(pat_str)res=bytes(res_str,'ISO-8859-1')else:res=translate(pat)cache[pat]=regex=re.compile(res)returnregex.matchdeffilter(names,pat):"""Return the subset of the list NAMES that match PAT"""importos,posixpathresult=[]pat=os.path.normcase(pat)match=_compile_pattern(pat)ifos.pathisposixpath:# normcase on posix is NOP. Optimize it away from the loop.fornameinnames:ifmatch(name):result.append(name)else:fornameinnames:ifmatch(os.path.normcase(name)):result.append(name)returnresultdeffnmatchcase(name,pat):"""Test whether FILENAME matches PATTERN, including case. This is a version of fnmatch() which doesn't case-normalize its arguments. """match=_compile_pattern(pat)returnmatch(name)isnotNonedeftranslate(pat):"""Translate a shell PATTERN to a regular expression. There is no way to quote meta-characters. """i,n=0,len(pat)res=''whilei<n:c=pat[i]i=i+1ifc=='*':res=res+'.*'elifc=='?':res=res+'.'elifc=='[':j=iifj<nandpat[j]=='!':j=j+1ifj<nandpat[j]==']':j=j+1whilej<nandpat[j]!=']':j=j+1ifj>=n:res=res+'\\['else:stuff=pat[i:j].replace('\\','\\\\')i=j+1ifstuff[0]=='!':stuff='^'+stuff[1:]elifstuff[0]=='^':stuff='\\'+stuffres='%s[%s]'%(res,stuff)else:res=res+re.escape(c)returnres+"$"