1*cda5da8dSAndroid Build Coastguard Worker"""Filename globbing utility.""" 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard Workerimport contextlib 4*cda5da8dSAndroid Build Coastguard Workerimport os 5*cda5da8dSAndroid Build Coastguard Workerimport re 6*cda5da8dSAndroid Build Coastguard Workerimport fnmatch 7*cda5da8dSAndroid Build Coastguard Workerimport itertools 8*cda5da8dSAndroid Build Coastguard Workerimport stat 9*cda5da8dSAndroid Build Coastguard Workerimport sys 10*cda5da8dSAndroid Build Coastguard Worker 11*cda5da8dSAndroid Build Coastguard Worker__all__ = ["glob", "iglob", "escape"] 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Workerdef glob(pathname, *, root_dir=None, dir_fd=None, recursive=False, 14*cda5da8dSAndroid Build Coastguard Worker include_hidden=False): 15*cda5da8dSAndroid Build Coastguard Worker """Return a list of paths matching a pathname pattern. 16*cda5da8dSAndroid Build Coastguard Worker 17*cda5da8dSAndroid Build Coastguard Worker The pattern may contain simple shell-style wildcards a la 18*cda5da8dSAndroid Build Coastguard Worker fnmatch. Unlike fnmatch, filenames starting with a 19*cda5da8dSAndroid Build Coastguard Worker dot are special cases that are not matched by '*' and '?' 20*cda5da8dSAndroid Build Coastguard Worker patterns by default. 21*cda5da8dSAndroid Build Coastguard Worker 22*cda5da8dSAndroid Build Coastguard Worker If `include_hidden` is true, the patterns '*', '?', '**' will match hidden 23*cda5da8dSAndroid Build Coastguard Worker directories. 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard Worker If `recursive` is true, the pattern '**' will match any files and 26*cda5da8dSAndroid Build Coastguard Worker zero or more directories and subdirectories. 27*cda5da8dSAndroid Build Coastguard Worker """ 28*cda5da8dSAndroid Build Coastguard Worker return list(iglob(pathname, root_dir=root_dir, dir_fd=dir_fd, recursive=recursive, 29*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden)) 30*cda5da8dSAndroid Build Coastguard Worker 31*cda5da8dSAndroid Build Coastguard Workerdef iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False, 32*cda5da8dSAndroid Build Coastguard Worker include_hidden=False): 33*cda5da8dSAndroid Build Coastguard Worker """Return an iterator which yields the paths matching a pathname pattern. 34*cda5da8dSAndroid Build Coastguard Worker 35*cda5da8dSAndroid Build Coastguard Worker The pattern may contain simple shell-style wildcards a la 36*cda5da8dSAndroid Build Coastguard Worker fnmatch. However, unlike fnmatch, filenames starting with a 37*cda5da8dSAndroid Build Coastguard Worker dot are special cases that are not matched by '*' and '?' 38*cda5da8dSAndroid Build Coastguard Worker patterns. 39*cda5da8dSAndroid Build Coastguard Worker 40*cda5da8dSAndroid Build Coastguard Worker If recursive is true, the pattern '**' will match any files and 41*cda5da8dSAndroid Build Coastguard Worker zero or more directories and subdirectories. 42*cda5da8dSAndroid Build Coastguard Worker """ 43*cda5da8dSAndroid Build Coastguard Worker sys.audit("glob.glob", pathname, recursive) 44*cda5da8dSAndroid Build Coastguard Worker sys.audit("glob.glob/2", pathname, recursive, root_dir, dir_fd) 45*cda5da8dSAndroid Build Coastguard Worker if root_dir is not None: 46*cda5da8dSAndroid Build Coastguard Worker root_dir = os.fspath(root_dir) 47*cda5da8dSAndroid Build Coastguard Worker else: 48*cda5da8dSAndroid Build Coastguard Worker root_dir = pathname[:0] 49*cda5da8dSAndroid Build Coastguard Worker it = _iglob(pathname, root_dir, dir_fd, recursive, False, 50*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden) 51*cda5da8dSAndroid Build Coastguard Worker if not pathname or recursive and _isrecursive(pathname[:2]): 52*cda5da8dSAndroid Build Coastguard Worker try: 53*cda5da8dSAndroid Build Coastguard Worker s = next(it) # skip empty string 54*cda5da8dSAndroid Build Coastguard Worker if s: 55*cda5da8dSAndroid Build Coastguard Worker it = itertools.chain((s,), it) 56*cda5da8dSAndroid Build Coastguard Worker except StopIteration: 57*cda5da8dSAndroid Build Coastguard Worker pass 58*cda5da8dSAndroid Build Coastguard Worker return it 59*cda5da8dSAndroid Build Coastguard Worker 60*cda5da8dSAndroid Build Coastguard Workerdef _iglob(pathname, root_dir, dir_fd, recursive, dironly, 61*cda5da8dSAndroid Build Coastguard Worker include_hidden=False): 62*cda5da8dSAndroid Build Coastguard Worker dirname, basename = os.path.split(pathname) 63*cda5da8dSAndroid Build Coastguard Worker if not has_magic(pathname): 64*cda5da8dSAndroid Build Coastguard Worker assert not dironly 65*cda5da8dSAndroid Build Coastguard Worker if basename: 66*cda5da8dSAndroid Build Coastguard Worker if _lexists(_join(root_dir, pathname), dir_fd): 67*cda5da8dSAndroid Build Coastguard Worker yield pathname 68*cda5da8dSAndroid Build Coastguard Worker else: 69*cda5da8dSAndroid Build Coastguard Worker # Patterns ending with a slash should match only directories 70*cda5da8dSAndroid Build Coastguard Worker if _isdir(_join(root_dir, dirname), dir_fd): 71*cda5da8dSAndroid Build Coastguard Worker yield pathname 72*cda5da8dSAndroid Build Coastguard Worker return 73*cda5da8dSAndroid Build Coastguard Worker if not dirname: 74*cda5da8dSAndroid Build Coastguard Worker if recursive and _isrecursive(basename): 75*cda5da8dSAndroid Build Coastguard Worker yield from _glob2(root_dir, basename, dir_fd, dironly, 76*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden) 77*cda5da8dSAndroid Build Coastguard Worker else: 78*cda5da8dSAndroid Build Coastguard Worker yield from _glob1(root_dir, basename, dir_fd, dironly, 79*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden) 80*cda5da8dSAndroid Build Coastguard Worker return 81*cda5da8dSAndroid Build Coastguard Worker # `os.path.split()` returns the argument itself as a dirname if it is a 82*cda5da8dSAndroid Build Coastguard Worker # drive or UNC path. Prevent an infinite recursion if a drive or UNC path 83*cda5da8dSAndroid Build Coastguard Worker # contains magic characters (i.e. r'\\?\C:'). 84*cda5da8dSAndroid Build Coastguard Worker if dirname != pathname and has_magic(dirname): 85*cda5da8dSAndroid Build Coastguard Worker dirs = _iglob(dirname, root_dir, dir_fd, recursive, True, 86*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden) 87*cda5da8dSAndroid Build Coastguard Worker else: 88*cda5da8dSAndroid Build Coastguard Worker dirs = [dirname] 89*cda5da8dSAndroid Build Coastguard Worker if has_magic(basename): 90*cda5da8dSAndroid Build Coastguard Worker if recursive and _isrecursive(basename): 91*cda5da8dSAndroid Build Coastguard Worker glob_in_dir = _glob2 92*cda5da8dSAndroid Build Coastguard Worker else: 93*cda5da8dSAndroid Build Coastguard Worker glob_in_dir = _glob1 94*cda5da8dSAndroid Build Coastguard Worker else: 95*cda5da8dSAndroid Build Coastguard Worker glob_in_dir = _glob0 96*cda5da8dSAndroid Build Coastguard Worker for dirname in dirs: 97*cda5da8dSAndroid Build Coastguard Worker for name in glob_in_dir(_join(root_dir, dirname), basename, dir_fd, dironly, 98*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden): 99*cda5da8dSAndroid Build Coastguard Worker yield os.path.join(dirname, name) 100*cda5da8dSAndroid Build Coastguard Worker 101*cda5da8dSAndroid Build Coastguard Worker# These 2 helper functions non-recursively glob inside a literal directory. 102*cda5da8dSAndroid Build Coastguard Worker# They return a list of basenames. _glob1 accepts a pattern while _glob0 103*cda5da8dSAndroid Build Coastguard Worker# takes a literal basename (so it only has to check for its existence). 104*cda5da8dSAndroid Build Coastguard Worker 105*cda5da8dSAndroid Build Coastguard Workerdef _glob1(dirname, pattern, dir_fd, dironly, include_hidden=False): 106*cda5da8dSAndroid Build Coastguard Worker names = _listdir(dirname, dir_fd, dironly) 107*cda5da8dSAndroid Build Coastguard Worker if include_hidden or not _ishidden(pattern): 108*cda5da8dSAndroid Build Coastguard Worker names = (x for x in names if include_hidden or not _ishidden(x)) 109*cda5da8dSAndroid Build Coastguard Worker return fnmatch.filter(names, pattern) 110*cda5da8dSAndroid Build Coastguard Worker 111*cda5da8dSAndroid Build Coastguard Workerdef _glob0(dirname, basename, dir_fd, dironly, include_hidden=False): 112*cda5da8dSAndroid Build Coastguard Worker if basename: 113*cda5da8dSAndroid Build Coastguard Worker if _lexists(_join(dirname, basename), dir_fd): 114*cda5da8dSAndroid Build Coastguard Worker return [basename] 115*cda5da8dSAndroid Build Coastguard Worker else: 116*cda5da8dSAndroid Build Coastguard Worker # `os.path.split()` returns an empty basename for paths ending with a 117*cda5da8dSAndroid Build Coastguard Worker # directory separator. 'q*x/' should match only directories. 118*cda5da8dSAndroid Build Coastguard Worker if _isdir(dirname, dir_fd): 119*cda5da8dSAndroid Build Coastguard Worker return [basename] 120*cda5da8dSAndroid Build Coastguard Worker return [] 121*cda5da8dSAndroid Build Coastguard Worker 122*cda5da8dSAndroid Build Coastguard Worker# Following functions are not public but can be used by third-party code. 123*cda5da8dSAndroid Build Coastguard Worker 124*cda5da8dSAndroid Build Coastguard Workerdef glob0(dirname, pattern): 125*cda5da8dSAndroid Build Coastguard Worker return _glob0(dirname, pattern, None, False) 126*cda5da8dSAndroid Build Coastguard Worker 127*cda5da8dSAndroid Build Coastguard Workerdef glob1(dirname, pattern): 128*cda5da8dSAndroid Build Coastguard Worker return _glob1(dirname, pattern, None, False) 129*cda5da8dSAndroid Build Coastguard Worker 130*cda5da8dSAndroid Build Coastguard Worker# This helper function recursively yields relative pathnames inside a literal 131*cda5da8dSAndroid Build Coastguard Worker# directory. 132*cda5da8dSAndroid Build Coastguard Worker 133*cda5da8dSAndroid Build Coastguard Workerdef _glob2(dirname, pattern, dir_fd, dironly, include_hidden=False): 134*cda5da8dSAndroid Build Coastguard Worker assert _isrecursive(pattern) 135*cda5da8dSAndroid Build Coastguard Worker yield pattern[:0] 136*cda5da8dSAndroid Build Coastguard Worker yield from _rlistdir(dirname, dir_fd, dironly, 137*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden) 138*cda5da8dSAndroid Build Coastguard Worker 139*cda5da8dSAndroid Build Coastguard Worker# If dironly is false, yields all file names inside a directory. 140*cda5da8dSAndroid Build Coastguard Worker# If dironly is true, yields only directory names. 141*cda5da8dSAndroid Build Coastguard Workerdef _iterdir(dirname, dir_fd, dironly): 142*cda5da8dSAndroid Build Coastguard Worker try: 143*cda5da8dSAndroid Build Coastguard Worker fd = None 144*cda5da8dSAndroid Build Coastguard Worker fsencode = None 145*cda5da8dSAndroid Build Coastguard Worker if dir_fd is not None: 146*cda5da8dSAndroid Build Coastguard Worker if dirname: 147*cda5da8dSAndroid Build Coastguard Worker fd = arg = os.open(dirname, _dir_open_flags, dir_fd=dir_fd) 148*cda5da8dSAndroid Build Coastguard Worker else: 149*cda5da8dSAndroid Build Coastguard Worker arg = dir_fd 150*cda5da8dSAndroid Build Coastguard Worker if isinstance(dirname, bytes): 151*cda5da8dSAndroid Build Coastguard Worker fsencode = os.fsencode 152*cda5da8dSAndroid Build Coastguard Worker elif dirname: 153*cda5da8dSAndroid Build Coastguard Worker arg = dirname 154*cda5da8dSAndroid Build Coastguard Worker elif isinstance(dirname, bytes): 155*cda5da8dSAndroid Build Coastguard Worker arg = bytes(os.curdir, 'ASCII') 156*cda5da8dSAndroid Build Coastguard Worker else: 157*cda5da8dSAndroid Build Coastguard Worker arg = os.curdir 158*cda5da8dSAndroid Build Coastguard Worker try: 159*cda5da8dSAndroid Build Coastguard Worker with os.scandir(arg) as it: 160*cda5da8dSAndroid Build Coastguard Worker for entry in it: 161*cda5da8dSAndroid Build Coastguard Worker try: 162*cda5da8dSAndroid Build Coastguard Worker if not dironly or entry.is_dir(): 163*cda5da8dSAndroid Build Coastguard Worker if fsencode is not None: 164*cda5da8dSAndroid Build Coastguard Worker yield fsencode(entry.name) 165*cda5da8dSAndroid Build Coastguard Worker else: 166*cda5da8dSAndroid Build Coastguard Worker yield entry.name 167*cda5da8dSAndroid Build Coastguard Worker except OSError: 168*cda5da8dSAndroid Build Coastguard Worker pass 169*cda5da8dSAndroid Build Coastguard Worker finally: 170*cda5da8dSAndroid Build Coastguard Worker if fd is not None: 171*cda5da8dSAndroid Build Coastguard Worker os.close(fd) 172*cda5da8dSAndroid Build Coastguard Worker except OSError: 173*cda5da8dSAndroid Build Coastguard Worker return 174*cda5da8dSAndroid Build Coastguard Worker 175*cda5da8dSAndroid Build Coastguard Workerdef _listdir(dirname, dir_fd, dironly): 176*cda5da8dSAndroid Build Coastguard Worker with contextlib.closing(_iterdir(dirname, dir_fd, dironly)) as it: 177*cda5da8dSAndroid Build Coastguard Worker return list(it) 178*cda5da8dSAndroid Build Coastguard Worker 179*cda5da8dSAndroid Build Coastguard Worker# Recursively yields relative pathnames inside a literal directory. 180*cda5da8dSAndroid Build Coastguard Workerdef _rlistdir(dirname, dir_fd, dironly, include_hidden=False): 181*cda5da8dSAndroid Build Coastguard Worker names = _listdir(dirname, dir_fd, dironly) 182*cda5da8dSAndroid Build Coastguard Worker for x in names: 183*cda5da8dSAndroid Build Coastguard Worker if include_hidden or not _ishidden(x): 184*cda5da8dSAndroid Build Coastguard Worker yield x 185*cda5da8dSAndroid Build Coastguard Worker path = _join(dirname, x) if dirname else x 186*cda5da8dSAndroid Build Coastguard Worker for y in _rlistdir(path, dir_fd, dironly, 187*cda5da8dSAndroid Build Coastguard Worker include_hidden=include_hidden): 188*cda5da8dSAndroid Build Coastguard Worker yield _join(x, y) 189*cda5da8dSAndroid Build Coastguard Worker 190*cda5da8dSAndroid Build Coastguard Worker 191*cda5da8dSAndroid Build Coastguard Workerdef _lexists(pathname, dir_fd): 192*cda5da8dSAndroid Build Coastguard Worker # Same as os.path.lexists(), but with dir_fd 193*cda5da8dSAndroid Build Coastguard Worker if dir_fd is None: 194*cda5da8dSAndroid Build Coastguard Worker return os.path.lexists(pathname) 195*cda5da8dSAndroid Build Coastguard Worker try: 196*cda5da8dSAndroid Build Coastguard Worker os.lstat(pathname, dir_fd=dir_fd) 197*cda5da8dSAndroid Build Coastguard Worker except (OSError, ValueError): 198*cda5da8dSAndroid Build Coastguard Worker return False 199*cda5da8dSAndroid Build Coastguard Worker else: 200*cda5da8dSAndroid Build Coastguard Worker return True 201*cda5da8dSAndroid Build Coastguard Worker 202*cda5da8dSAndroid Build Coastguard Workerdef _isdir(pathname, dir_fd): 203*cda5da8dSAndroid Build Coastguard Worker # Same as os.path.isdir(), but with dir_fd 204*cda5da8dSAndroid Build Coastguard Worker if dir_fd is None: 205*cda5da8dSAndroid Build Coastguard Worker return os.path.isdir(pathname) 206*cda5da8dSAndroid Build Coastguard Worker try: 207*cda5da8dSAndroid Build Coastguard Worker st = os.stat(pathname, dir_fd=dir_fd) 208*cda5da8dSAndroid Build Coastguard Worker except (OSError, ValueError): 209*cda5da8dSAndroid Build Coastguard Worker return False 210*cda5da8dSAndroid Build Coastguard Worker else: 211*cda5da8dSAndroid Build Coastguard Worker return stat.S_ISDIR(st.st_mode) 212*cda5da8dSAndroid Build Coastguard Worker 213*cda5da8dSAndroid Build Coastguard Workerdef _join(dirname, basename): 214*cda5da8dSAndroid Build Coastguard Worker # It is common if dirname or basename is empty 215*cda5da8dSAndroid Build Coastguard Worker if not dirname or not basename: 216*cda5da8dSAndroid Build Coastguard Worker return dirname or basename 217*cda5da8dSAndroid Build Coastguard Worker return os.path.join(dirname, basename) 218*cda5da8dSAndroid Build Coastguard Worker 219*cda5da8dSAndroid Build Coastguard Workermagic_check = re.compile('([*?[])') 220*cda5da8dSAndroid Build Coastguard Workermagic_check_bytes = re.compile(b'([*?[])') 221*cda5da8dSAndroid Build Coastguard Worker 222*cda5da8dSAndroid Build Coastguard Workerdef has_magic(s): 223*cda5da8dSAndroid Build Coastguard Worker if isinstance(s, bytes): 224*cda5da8dSAndroid Build Coastguard Worker match = magic_check_bytes.search(s) 225*cda5da8dSAndroid Build Coastguard Worker else: 226*cda5da8dSAndroid Build Coastguard Worker match = magic_check.search(s) 227*cda5da8dSAndroid Build Coastguard Worker return match is not None 228*cda5da8dSAndroid Build Coastguard Worker 229*cda5da8dSAndroid Build Coastguard Workerdef _ishidden(path): 230*cda5da8dSAndroid Build Coastguard Worker return path[0] in ('.', b'.'[0]) 231*cda5da8dSAndroid Build Coastguard Worker 232*cda5da8dSAndroid Build Coastguard Workerdef _isrecursive(pattern): 233*cda5da8dSAndroid Build Coastguard Worker if isinstance(pattern, bytes): 234*cda5da8dSAndroid Build Coastguard Worker return pattern == b'**' 235*cda5da8dSAndroid Build Coastguard Worker else: 236*cda5da8dSAndroid Build Coastguard Worker return pattern == '**' 237*cda5da8dSAndroid Build Coastguard Worker 238*cda5da8dSAndroid Build Coastguard Workerdef escape(pathname): 239*cda5da8dSAndroid Build Coastguard Worker """Escape all special characters. 240*cda5da8dSAndroid Build Coastguard Worker """ 241*cda5da8dSAndroid Build Coastguard Worker # Escaping is done by wrapping any of "*?[" between square brackets. 242*cda5da8dSAndroid Build Coastguard Worker # Metacharacters do not work in the drive part and shouldn't be escaped. 243*cda5da8dSAndroid Build Coastguard Worker drive, pathname = os.path.splitdrive(pathname) 244*cda5da8dSAndroid Build Coastguard Worker if isinstance(pathname, bytes): 245*cda5da8dSAndroid Build Coastguard Worker pathname = magic_check_bytes.sub(br'[\1]', pathname) 246*cda5da8dSAndroid Build Coastguard Worker else: 247*cda5da8dSAndroid Build Coastguard Worker pathname = magic_check.sub(r'[\1]', pathname) 248*cda5da8dSAndroid Build Coastguard Worker return drive + pathname 249*cda5da8dSAndroid Build Coastguard Worker 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker_dir_open_flags = os.O_RDONLY | getattr(os, 'O_DIRECTORY', 0) 252