1*cda5da8dSAndroid Build Coastguard Worker"""Common operations on Posix pathnames. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerInstead of importing this module directly, import os and refer to 4*cda5da8dSAndroid Build Coastguard Workerthis module as os.path. The "os.path" name is an alias for this 5*cda5da8dSAndroid Build Coastguard Workermodule on Posix systems; on other systems (e.g. Windows), 6*cda5da8dSAndroid Build Coastguard Workeros.path provides the same operations in a manner specific to that 7*cda5da8dSAndroid Build Coastguard Workerplatform, and is an alias to another module (e.g. ntpath). 8*cda5da8dSAndroid Build Coastguard Worker 9*cda5da8dSAndroid Build Coastguard WorkerSome of this can actually be useful on non-Posix systems too, e.g. 10*cda5da8dSAndroid Build Coastguard Workerfor manipulation of the pathname component of URLs. 11*cda5da8dSAndroid Build Coastguard Worker""" 12*cda5da8dSAndroid Build Coastguard Worker 13*cda5da8dSAndroid Build Coastguard Worker# Strings representing various path-related bits and pieces. 14*cda5da8dSAndroid Build Coastguard Worker# These are primarily for export; internally, they are hardcoded. 15*cda5da8dSAndroid Build Coastguard Worker# Should be set before imports for resolving cyclic dependency. 16*cda5da8dSAndroid Build Coastguard Workercurdir = '.' 17*cda5da8dSAndroid Build Coastguard Workerpardir = '..' 18*cda5da8dSAndroid Build Coastguard Workerextsep = '.' 19*cda5da8dSAndroid Build Coastguard Workersep = '/' 20*cda5da8dSAndroid Build Coastguard Workerpathsep = ':' 21*cda5da8dSAndroid Build Coastguard Workerdefpath = '/bin:/usr/bin' 22*cda5da8dSAndroid Build Coastguard Workeraltsep = None 23*cda5da8dSAndroid Build Coastguard Workerdevnull = '/dev/null' 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard Workerimport os 26*cda5da8dSAndroid Build Coastguard Workerimport sys 27*cda5da8dSAndroid Build Coastguard Workerimport stat 28*cda5da8dSAndroid Build Coastguard Workerimport genericpath 29*cda5da8dSAndroid Build Coastguard Workerfrom genericpath import * 30*cda5da8dSAndroid Build Coastguard Worker 31*cda5da8dSAndroid Build Coastguard Worker__all__ = ["normcase","isabs","join","splitdrive","split","splitext", 32*cda5da8dSAndroid Build Coastguard Worker "basename","dirname","commonprefix","getsize","getmtime", 33*cda5da8dSAndroid Build Coastguard Worker "getatime","getctime","islink","exists","lexists","isdir","isfile", 34*cda5da8dSAndroid Build Coastguard Worker "ismount", "expanduser","expandvars","normpath","abspath", 35*cda5da8dSAndroid Build Coastguard Worker "samefile","sameopenfile","samestat", 36*cda5da8dSAndroid Build Coastguard Worker "curdir","pardir","sep","pathsep","defpath","altsep","extsep", 37*cda5da8dSAndroid Build Coastguard Worker "devnull","realpath","supports_unicode_filenames","relpath", 38*cda5da8dSAndroid Build Coastguard Worker "commonpath"] 39*cda5da8dSAndroid Build Coastguard Worker 40*cda5da8dSAndroid Build Coastguard Worker 41*cda5da8dSAndroid Build Coastguard Workerdef _get_sep(path): 42*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 43*cda5da8dSAndroid Build Coastguard Worker return b'/' 44*cda5da8dSAndroid Build Coastguard Worker else: 45*cda5da8dSAndroid Build Coastguard Worker return '/' 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard Worker# Normalize the case of a pathname. Trivial in Posix, string.lower on Mac. 48*cda5da8dSAndroid Build Coastguard Worker# On MS-DOS this may also turn slashes into backslashes; however, other 49*cda5da8dSAndroid Build Coastguard Worker# normalizations (such as optimizing '../' away) are not allowed 50*cda5da8dSAndroid Build Coastguard Worker# (another function should be defined to do that). 51*cda5da8dSAndroid Build Coastguard Worker 52*cda5da8dSAndroid Build Coastguard Workerdef normcase(s): 53*cda5da8dSAndroid Build Coastguard Worker """Normalize case of pathname. Has no effect under Posix""" 54*cda5da8dSAndroid Build Coastguard Worker return os.fspath(s) 55*cda5da8dSAndroid Build Coastguard Worker 56*cda5da8dSAndroid Build Coastguard Worker 57*cda5da8dSAndroid Build Coastguard Worker# Return whether a path is absolute. 58*cda5da8dSAndroid Build Coastguard Worker# Trivial in Posix, harder on the Mac or MS-DOS. 59*cda5da8dSAndroid Build Coastguard Worker 60*cda5da8dSAndroid Build Coastguard Workerdef isabs(s): 61*cda5da8dSAndroid Build Coastguard Worker """Test whether a path is absolute""" 62*cda5da8dSAndroid Build Coastguard Worker s = os.fspath(s) 63*cda5da8dSAndroid Build Coastguard Worker sep = _get_sep(s) 64*cda5da8dSAndroid Build Coastguard Worker return s.startswith(sep) 65*cda5da8dSAndroid Build Coastguard Worker 66*cda5da8dSAndroid Build Coastguard Worker 67*cda5da8dSAndroid Build Coastguard Worker# Join pathnames. 68*cda5da8dSAndroid Build Coastguard Worker# Ignore the previous parts if a part is absolute. 69*cda5da8dSAndroid Build Coastguard Worker# Insert a '/' unless the first part is empty or already ends in '/'. 70*cda5da8dSAndroid Build Coastguard Worker 71*cda5da8dSAndroid Build Coastguard Workerdef join(a, *p): 72*cda5da8dSAndroid Build Coastguard Worker """Join two or more pathname components, inserting '/' as needed. 73*cda5da8dSAndroid Build Coastguard Worker If any component is an absolute path, all previous path components 74*cda5da8dSAndroid Build Coastguard Worker will be discarded. An empty last part will result in a path that 75*cda5da8dSAndroid Build Coastguard Worker ends with a separator.""" 76*cda5da8dSAndroid Build Coastguard Worker a = os.fspath(a) 77*cda5da8dSAndroid Build Coastguard Worker sep = _get_sep(a) 78*cda5da8dSAndroid Build Coastguard Worker path = a 79*cda5da8dSAndroid Build Coastguard Worker try: 80*cda5da8dSAndroid Build Coastguard Worker if not p: 81*cda5da8dSAndroid Build Coastguard Worker path[:0] + sep #23780: Ensure compatible data type even if p is null. 82*cda5da8dSAndroid Build Coastguard Worker for b in map(os.fspath, p): 83*cda5da8dSAndroid Build Coastguard Worker if b.startswith(sep): 84*cda5da8dSAndroid Build Coastguard Worker path = b 85*cda5da8dSAndroid Build Coastguard Worker elif not path or path.endswith(sep): 86*cda5da8dSAndroid Build Coastguard Worker path += b 87*cda5da8dSAndroid Build Coastguard Worker else: 88*cda5da8dSAndroid Build Coastguard Worker path += sep + b 89*cda5da8dSAndroid Build Coastguard Worker except (TypeError, AttributeError, BytesWarning): 90*cda5da8dSAndroid Build Coastguard Worker genericpath._check_arg_types('join', a, *p) 91*cda5da8dSAndroid Build Coastguard Worker raise 92*cda5da8dSAndroid Build Coastguard Worker return path 93*cda5da8dSAndroid Build Coastguard Worker 94*cda5da8dSAndroid Build Coastguard Worker 95*cda5da8dSAndroid Build Coastguard Worker# Split a path in head (everything up to the last '/') and tail (the 96*cda5da8dSAndroid Build Coastguard Worker# rest). If the path ends in '/', tail will be empty. If there is no 97*cda5da8dSAndroid Build Coastguard Worker# '/' in the path, head will be empty. 98*cda5da8dSAndroid Build Coastguard Worker# Trailing '/'es are stripped from head unless it is the root. 99*cda5da8dSAndroid Build Coastguard Worker 100*cda5da8dSAndroid Build Coastguard Workerdef split(p): 101*cda5da8dSAndroid Build Coastguard Worker """Split a pathname. Returns tuple "(head, tail)" where "tail" is 102*cda5da8dSAndroid Build Coastguard Worker everything after the final slash. Either part may be empty.""" 103*cda5da8dSAndroid Build Coastguard Worker p = os.fspath(p) 104*cda5da8dSAndroid Build Coastguard Worker sep = _get_sep(p) 105*cda5da8dSAndroid Build Coastguard Worker i = p.rfind(sep) + 1 106*cda5da8dSAndroid Build Coastguard Worker head, tail = p[:i], p[i:] 107*cda5da8dSAndroid Build Coastguard Worker if head and head != sep*len(head): 108*cda5da8dSAndroid Build Coastguard Worker head = head.rstrip(sep) 109*cda5da8dSAndroid Build Coastguard Worker return head, tail 110*cda5da8dSAndroid Build Coastguard Worker 111*cda5da8dSAndroid Build Coastguard Worker 112*cda5da8dSAndroid Build Coastguard Worker# Split a path in root and extension. 113*cda5da8dSAndroid Build Coastguard Worker# The extension is everything starting at the last dot in the last 114*cda5da8dSAndroid Build Coastguard Worker# pathname component; the root is everything before that. 115*cda5da8dSAndroid Build Coastguard Worker# It is always true that root + ext == p. 116*cda5da8dSAndroid Build Coastguard Worker 117*cda5da8dSAndroid Build Coastguard Workerdef splitext(p): 118*cda5da8dSAndroid Build Coastguard Worker p = os.fspath(p) 119*cda5da8dSAndroid Build Coastguard Worker if isinstance(p, bytes): 120*cda5da8dSAndroid Build Coastguard Worker sep = b'/' 121*cda5da8dSAndroid Build Coastguard Worker extsep = b'.' 122*cda5da8dSAndroid Build Coastguard Worker else: 123*cda5da8dSAndroid Build Coastguard Worker sep = '/' 124*cda5da8dSAndroid Build Coastguard Worker extsep = '.' 125*cda5da8dSAndroid Build Coastguard Worker return genericpath._splitext(p, sep, None, extsep) 126*cda5da8dSAndroid Build Coastguard Workersplitext.__doc__ = genericpath._splitext.__doc__ 127*cda5da8dSAndroid Build Coastguard Worker 128*cda5da8dSAndroid Build Coastguard Worker# Split a pathname into a drive specification and the rest of the 129*cda5da8dSAndroid Build Coastguard Worker# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty. 130*cda5da8dSAndroid Build Coastguard Worker 131*cda5da8dSAndroid Build Coastguard Workerdef splitdrive(p): 132*cda5da8dSAndroid Build Coastguard Worker """Split a pathname into drive and path. On Posix, drive is always 133*cda5da8dSAndroid Build Coastguard Worker empty.""" 134*cda5da8dSAndroid Build Coastguard Worker p = os.fspath(p) 135*cda5da8dSAndroid Build Coastguard Worker return p[:0], p 136*cda5da8dSAndroid Build Coastguard Worker 137*cda5da8dSAndroid Build Coastguard Worker 138*cda5da8dSAndroid Build Coastguard Worker# Return the tail (basename) part of a path, same as split(path)[1]. 139*cda5da8dSAndroid Build Coastguard Worker 140*cda5da8dSAndroid Build Coastguard Workerdef basename(p): 141*cda5da8dSAndroid Build Coastguard Worker """Returns the final component of a pathname""" 142*cda5da8dSAndroid Build Coastguard Worker p = os.fspath(p) 143*cda5da8dSAndroid Build Coastguard Worker sep = _get_sep(p) 144*cda5da8dSAndroid Build Coastguard Worker i = p.rfind(sep) + 1 145*cda5da8dSAndroid Build Coastguard Worker return p[i:] 146*cda5da8dSAndroid Build Coastguard Worker 147*cda5da8dSAndroid Build Coastguard Worker 148*cda5da8dSAndroid Build Coastguard Worker# Return the head (dirname) part of a path, same as split(path)[0]. 149*cda5da8dSAndroid Build Coastguard Worker 150*cda5da8dSAndroid Build Coastguard Workerdef dirname(p): 151*cda5da8dSAndroid Build Coastguard Worker """Returns the directory component of a pathname""" 152*cda5da8dSAndroid Build Coastguard Worker p = os.fspath(p) 153*cda5da8dSAndroid Build Coastguard Worker sep = _get_sep(p) 154*cda5da8dSAndroid Build Coastguard Worker i = p.rfind(sep) + 1 155*cda5da8dSAndroid Build Coastguard Worker head = p[:i] 156*cda5da8dSAndroid Build Coastguard Worker if head and head != sep*len(head): 157*cda5da8dSAndroid Build Coastguard Worker head = head.rstrip(sep) 158*cda5da8dSAndroid Build Coastguard Worker return head 159*cda5da8dSAndroid Build Coastguard Worker 160*cda5da8dSAndroid Build Coastguard Worker 161*cda5da8dSAndroid Build Coastguard Worker# Is a path a symbolic link? 162*cda5da8dSAndroid Build Coastguard Worker# This will always return false on systems where os.lstat doesn't exist. 163*cda5da8dSAndroid Build Coastguard Worker 164*cda5da8dSAndroid Build Coastguard Workerdef islink(path): 165*cda5da8dSAndroid Build Coastguard Worker """Test whether a path is a symbolic link""" 166*cda5da8dSAndroid Build Coastguard Worker try: 167*cda5da8dSAndroid Build Coastguard Worker st = os.lstat(path) 168*cda5da8dSAndroid Build Coastguard Worker except (OSError, ValueError, AttributeError): 169*cda5da8dSAndroid Build Coastguard Worker return False 170*cda5da8dSAndroid Build Coastguard Worker return stat.S_ISLNK(st.st_mode) 171*cda5da8dSAndroid Build Coastguard Worker 172*cda5da8dSAndroid Build Coastguard Worker# Being true for dangling symbolic links is also useful. 173*cda5da8dSAndroid Build Coastguard Worker 174*cda5da8dSAndroid Build Coastguard Workerdef lexists(path): 175*cda5da8dSAndroid Build Coastguard Worker """Test whether a path exists. Returns True for broken symbolic links""" 176*cda5da8dSAndroid Build Coastguard Worker try: 177*cda5da8dSAndroid Build Coastguard Worker os.lstat(path) 178*cda5da8dSAndroid Build Coastguard Worker except (OSError, ValueError): 179*cda5da8dSAndroid Build Coastguard Worker return False 180*cda5da8dSAndroid Build Coastguard Worker return True 181*cda5da8dSAndroid Build Coastguard Worker 182*cda5da8dSAndroid Build Coastguard Worker 183*cda5da8dSAndroid Build Coastguard Worker# Is a path a mount point? 184*cda5da8dSAndroid Build Coastguard Worker# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?) 185*cda5da8dSAndroid Build Coastguard Worker 186*cda5da8dSAndroid Build Coastguard Workerdef ismount(path): 187*cda5da8dSAndroid Build Coastguard Worker """Test whether a path is a mount point""" 188*cda5da8dSAndroid Build Coastguard Worker try: 189*cda5da8dSAndroid Build Coastguard Worker s1 = os.lstat(path) 190*cda5da8dSAndroid Build Coastguard Worker except (OSError, ValueError): 191*cda5da8dSAndroid Build Coastguard Worker # It doesn't exist -- so not a mount point. :-) 192*cda5da8dSAndroid Build Coastguard Worker return False 193*cda5da8dSAndroid Build Coastguard Worker else: 194*cda5da8dSAndroid Build Coastguard Worker # A symlink can never be a mount point 195*cda5da8dSAndroid Build Coastguard Worker if stat.S_ISLNK(s1.st_mode): 196*cda5da8dSAndroid Build Coastguard Worker return False 197*cda5da8dSAndroid Build Coastguard Worker 198*cda5da8dSAndroid Build Coastguard Worker path = os.fspath(path) 199*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 200*cda5da8dSAndroid Build Coastguard Worker parent = join(path, b'..') 201*cda5da8dSAndroid Build Coastguard Worker else: 202*cda5da8dSAndroid Build Coastguard Worker parent = join(path, '..') 203*cda5da8dSAndroid Build Coastguard Worker parent = realpath(parent) 204*cda5da8dSAndroid Build Coastguard Worker try: 205*cda5da8dSAndroid Build Coastguard Worker s2 = os.lstat(parent) 206*cda5da8dSAndroid Build Coastguard Worker except (OSError, ValueError): 207*cda5da8dSAndroid Build Coastguard Worker return False 208*cda5da8dSAndroid Build Coastguard Worker 209*cda5da8dSAndroid Build Coastguard Worker dev1 = s1.st_dev 210*cda5da8dSAndroid Build Coastguard Worker dev2 = s2.st_dev 211*cda5da8dSAndroid Build Coastguard Worker if dev1 != dev2: 212*cda5da8dSAndroid Build Coastguard Worker return True # path/.. on a different device as path 213*cda5da8dSAndroid Build Coastguard Worker ino1 = s1.st_ino 214*cda5da8dSAndroid Build Coastguard Worker ino2 = s2.st_ino 215*cda5da8dSAndroid Build Coastguard Worker if ino1 == ino2: 216*cda5da8dSAndroid Build Coastguard Worker return True # path/.. is the same i-node as path 217*cda5da8dSAndroid Build Coastguard Worker return False 218*cda5da8dSAndroid Build Coastguard Worker 219*cda5da8dSAndroid Build Coastguard Worker 220*cda5da8dSAndroid Build Coastguard Worker# Expand paths beginning with '~' or '~user'. 221*cda5da8dSAndroid Build Coastguard Worker# '~' means $HOME; '~user' means that user's home directory. 222*cda5da8dSAndroid Build Coastguard Worker# If the path doesn't begin with '~', or if the user or $HOME is unknown, 223*cda5da8dSAndroid Build Coastguard Worker# the path is returned unchanged (leaving error reporting to whatever 224*cda5da8dSAndroid Build Coastguard Worker# function is called with the expanded path as argument). 225*cda5da8dSAndroid Build Coastguard Worker# See also module 'glob' for expansion of *, ? and [...] in pathnames. 226*cda5da8dSAndroid Build Coastguard Worker# (A function should also be defined to do full *sh-style environment 227*cda5da8dSAndroid Build Coastguard Worker# variable expansion.) 228*cda5da8dSAndroid Build Coastguard Worker 229*cda5da8dSAndroid Build Coastguard Workerdef expanduser(path): 230*cda5da8dSAndroid Build Coastguard Worker """Expand ~ and ~user constructions. If user or $HOME is unknown, 231*cda5da8dSAndroid Build Coastguard Worker do nothing.""" 232*cda5da8dSAndroid Build Coastguard Worker path = os.fspath(path) 233*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 234*cda5da8dSAndroid Build Coastguard Worker tilde = b'~' 235*cda5da8dSAndroid Build Coastguard Worker else: 236*cda5da8dSAndroid Build Coastguard Worker tilde = '~' 237*cda5da8dSAndroid Build Coastguard Worker if not path.startswith(tilde): 238*cda5da8dSAndroid Build Coastguard Worker return path 239*cda5da8dSAndroid Build Coastguard Worker sep = _get_sep(path) 240*cda5da8dSAndroid Build Coastguard Worker i = path.find(sep, 1) 241*cda5da8dSAndroid Build Coastguard Worker if i < 0: 242*cda5da8dSAndroid Build Coastguard Worker i = len(path) 243*cda5da8dSAndroid Build Coastguard Worker if i == 1: 244*cda5da8dSAndroid Build Coastguard Worker if 'HOME' not in os.environ: 245*cda5da8dSAndroid Build Coastguard Worker try: 246*cda5da8dSAndroid Build Coastguard Worker import pwd 247*cda5da8dSAndroid Build Coastguard Worker except ImportError: 248*cda5da8dSAndroid Build Coastguard Worker # pwd module unavailable, return path unchanged 249*cda5da8dSAndroid Build Coastguard Worker return path 250*cda5da8dSAndroid Build Coastguard Worker try: 251*cda5da8dSAndroid Build Coastguard Worker userhome = pwd.getpwuid(os.getuid()).pw_dir 252*cda5da8dSAndroid Build Coastguard Worker except KeyError: 253*cda5da8dSAndroid Build Coastguard Worker # bpo-10496: if the current user identifier doesn't exist in the 254*cda5da8dSAndroid Build Coastguard Worker # password database, return the path unchanged 255*cda5da8dSAndroid Build Coastguard Worker return path 256*cda5da8dSAndroid Build Coastguard Worker else: 257*cda5da8dSAndroid Build Coastguard Worker userhome = os.environ['HOME'] 258*cda5da8dSAndroid Build Coastguard Worker else: 259*cda5da8dSAndroid Build Coastguard Worker try: 260*cda5da8dSAndroid Build Coastguard Worker import pwd 261*cda5da8dSAndroid Build Coastguard Worker except ImportError: 262*cda5da8dSAndroid Build Coastguard Worker # pwd module unavailable, return path unchanged 263*cda5da8dSAndroid Build Coastguard Worker return path 264*cda5da8dSAndroid Build Coastguard Worker name = path[1:i] 265*cda5da8dSAndroid Build Coastguard Worker if isinstance(name, bytes): 266*cda5da8dSAndroid Build Coastguard Worker name = str(name, 'ASCII') 267*cda5da8dSAndroid Build Coastguard Worker try: 268*cda5da8dSAndroid Build Coastguard Worker pwent = pwd.getpwnam(name) 269*cda5da8dSAndroid Build Coastguard Worker except KeyError: 270*cda5da8dSAndroid Build Coastguard Worker # bpo-10496: if the user name from the path doesn't exist in the 271*cda5da8dSAndroid Build Coastguard Worker # password database, return the path unchanged 272*cda5da8dSAndroid Build Coastguard Worker return path 273*cda5da8dSAndroid Build Coastguard Worker userhome = pwent.pw_dir 274*cda5da8dSAndroid Build Coastguard Worker # if no user home, return the path unchanged on VxWorks 275*cda5da8dSAndroid Build Coastguard Worker if userhome is None and sys.platform == "vxworks": 276*cda5da8dSAndroid Build Coastguard Worker return path 277*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 278*cda5da8dSAndroid Build Coastguard Worker userhome = os.fsencode(userhome) 279*cda5da8dSAndroid Build Coastguard Worker root = b'/' 280*cda5da8dSAndroid Build Coastguard Worker else: 281*cda5da8dSAndroid Build Coastguard Worker root = '/' 282*cda5da8dSAndroid Build Coastguard Worker userhome = userhome.rstrip(root) 283*cda5da8dSAndroid Build Coastguard Worker return (userhome + path[i:]) or root 284*cda5da8dSAndroid Build Coastguard Worker 285*cda5da8dSAndroid Build Coastguard Worker 286*cda5da8dSAndroid Build Coastguard Worker# Expand paths containing shell variable substitutions. 287*cda5da8dSAndroid Build Coastguard Worker# This expands the forms $variable and ${variable} only. 288*cda5da8dSAndroid Build Coastguard Worker# Non-existent variables are left unchanged. 289*cda5da8dSAndroid Build Coastguard Worker 290*cda5da8dSAndroid Build Coastguard Worker_varprog = None 291*cda5da8dSAndroid Build Coastguard Worker_varprogb = None 292*cda5da8dSAndroid Build Coastguard Worker 293*cda5da8dSAndroid Build Coastguard Workerdef expandvars(path): 294*cda5da8dSAndroid Build Coastguard Worker """Expand shell variables of form $var and ${var}. Unknown variables 295*cda5da8dSAndroid Build Coastguard Worker are left unchanged.""" 296*cda5da8dSAndroid Build Coastguard Worker path = os.fspath(path) 297*cda5da8dSAndroid Build Coastguard Worker global _varprog, _varprogb 298*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 299*cda5da8dSAndroid Build Coastguard Worker if b'$' not in path: 300*cda5da8dSAndroid Build Coastguard Worker return path 301*cda5da8dSAndroid Build Coastguard Worker if not _varprogb: 302*cda5da8dSAndroid Build Coastguard Worker import re 303*cda5da8dSAndroid Build Coastguard Worker _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII) 304*cda5da8dSAndroid Build Coastguard Worker search = _varprogb.search 305*cda5da8dSAndroid Build Coastguard Worker start = b'{' 306*cda5da8dSAndroid Build Coastguard Worker end = b'}' 307*cda5da8dSAndroid Build Coastguard Worker environ = getattr(os, 'environb', None) 308*cda5da8dSAndroid Build Coastguard Worker else: 309*cda5da8dSAndroid Build Coastguard Worker if '$' not in path: 310*cda5da8dSAndroid Build Coastguard Worker return path 311*cda5da8dSAndroid Build Coastguard Worker if not _varprog: 312*cda5da8dSAndroid Build Coastguard Worker import re 313*cda5da8dSAndroid Build Coastguard Worker _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII) 314*cda5da8dSAndroid Build Coastguard Worker search = _varprog.search 315*cda5da8dSAndroid Build Coastguard Worker start = '{' 316*cda5da8dSAndroid Build Coastguard Worker end = '}' 317*cda5da8dSAndroid Build Coastguard Worker environ = os.environ 318*cda5da8dSAndroid Build Coastguard Worker i = 0 319*cda5da8dSAndroid Build Coastguard Worker while True: 320*cda5da8dSAndroid Build Coastguard Worker m = search(path, i) 321*cda5da8dSAndroid Build Coastguard Worker if not m: 322*cda5da8dSAndroid Build Coastguard Worker break 323*cda5da8dSAndroid Build Coastguard Worker i, j = m.span(0) 324*cda5da8dSAndroid Build Coastguard Worker name = m.group(1) 325*cda5da8dSAndroid Build Coastguard Worker if name.startswith(start) and name.endswith(end): 326*cda5da8dSAndroid Build Coastguard Worker name = name[1:-1] 327*cda5da8dSAndroid Build Coastguard Worker try: 328*cda5da8dSAndroid Build Coastguard Worker if environ is None: 329*cda5da8dSAndroid Build Coastguard Worker value = os.fsencode(os.environ[os.fsdecode(name)]) 330*cda5da8dSAndroid Build Coastguard Worker else: 331*cda5da8dSAndroid Build Coastguard Worker value = environ[name] 332*cda5da8dSAndroid Build Coastguard Worker except KeyError: 333*cda5da8dSAndroid Build Coastguard Worker i = j 334*cda5da8dSAndroid Build Coastguard Worker else: 335*cda5da8dSAndroid Build Coastguard Worker tail = path[j:] 336*cda5da8dSAndroid Build Coastguard Worker path = path[:i] + value 337*cda5da8dSAndroid Build Coastguard Worker i = len(path) 338*cda5da8dSAndroid Build Coastguard Worker path += tail 339*cda5da8dSAndroid Build Coastguard Worker return path 340*cda5da8dSAndroid Build Coastguard Worker 341*cda5da8dSAndroid Build Coastguard Worker 342*cda5da8dSAndroid Build Coastguard Worker# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. 343*cda5da8dSAndroid Build Coastguard Worker# It should be understood that this may change the meaning of the path 344*cda5da8dSAndroid Build Coastguard Worker# if it contains symbolic links! 345*cda5da8dSAndroid Build Coastguard Worker 346*cda5da8dSAndroid Build Coastguard Workertry: 347*cda5da8dSAndroid Build Coastguard Worker from posix import _path_normpath 348*cda5da8dSAndroid Build Coastguard Worker 349*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 350*cda5da8dSAndroid Build Coastguard Worker def normpath(path): 351*cda5da8dSAndroid Build Coastguard Worker """Normalize path, eliminating double slashes, etc.""" 352*cda5da8dSAndroid Build Coastguard Worker path = os.fspath(path) 353*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 354*cda5da8dSAndroid Build Coastguard Worker sep = b'/' 355*cda5da8dSAndroid Build Coastguard Worker empty = b'' 356*cda5da8dSAndroid Build Coastguard Worker dot = b'.' 357*cda5da8dSAndroid Build Coastguard Worker dotdot = b'..' 358*cda5da8dSAndroid Build Coastguard Worker else: 359*cda5da8dSAndroid Build Coastguard Worker sep = '/' 360*cda5da8dSAndroid Build Coastguard Worker empty = '' 361*cda5da8dSAndroid Build Coastguard Worker dot = '.' 362*cda5da8dSAndroid Build Coastguard Worker dotdot = '..' 363*cda5da8dSAndroid Build Coastguard Worker if path == empty: 364*cda5da8dSAndroid Build Coastguard Worker return dot 365*cda5da8dSAndroid Build Coastguard Worker initial_slashes = path.startswith(sep) 366*cda5da8dSAndroid Build Coastguard Worker # POSIX allows one or two initial slashes, but treats three or more 367*cda5da8dSAndroid Build Coastguard Worker # as single slash. 368*cda5da8dSAndroid Build Coastguard Worker # (see https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13) 369*cda5da8dSAndroid Build Coastguard Worker if (initial_slashes and 370*cda5da8dSAndroid Build Coastguard Worker path.startswith(sep*2) and not path.startswith(sep*3)): 371*cda5da8dSAndroid Build Coastguard Worker initial_slashes = 2 372*cda5da8dSAndroid Build Coastguard Worker comps = path.split(sep) 373*cda5da8dSAndroid Build Coastguard Worker new_comps = [] 374*cda5da8dSAndroid Build Coastguard Worker for comp in comps: 375*cda5da8dSAndroid Build Coastguard Worker if comp in (empty, dot): 376*cda5da8dSAndroid Build Coastguard Worker continue 377*cda5da8dSAndroid Build Coastguard Worker if (comp != dotdot or (not initial_slashes and not new_comps) or 378*cda5da8dSAndroid Build Coastguard Worker (new_comps and new_comps[-1] == dotdot)): 379*cda5da8dSAndroid Build Coastguard Worker new_comps.append(comp) 380*cda5da8dSAndroid Build Coastguard Worker elif new_comps: 381*cda5da8dSAndroid Build Coastguard Worker new_comps.pop() 382*cda5da8dSAndroid Build Coastguard Worker comps = new_comps 383*cda5da8dSAndroid Build Coastguard Worker path = sep.join(comps) 384*cda5da8dSAndroid Build Coastguard Worker if initial_slashes: 385*cda5da8dSAndroid Build Coastguard Worker path = sep*initial_slashes + path 386*cda5da8dSAndroid Build Coastguard Worker return path or dot 387*cda5da8dSAndroid Build Coastguard Worker 388*cda5da8dSAndroid Build Coastguard Workerelse: 389*cda5da8dSAndroid Build Coastguard Worker def normpath(path): 390*cda5da8dSAndroid Build Coastguard Worker """Normalize path, eliminating double slashes, etc.""" 391*cda5da8dSAndroid Build Coastguard Worker path = os.fspath(path) 392*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 393*cda5da8dSAndroid Build Coastguard Worker return os.fsencode(_path_normpath(os.fsdecode(path))) or b"." 394*cda5da8dSAndroid Build Coastguard Worker return _path_normpath(path) or "." 395*cda5da8dSAndroid Build Coastguard Worker 396*cda5da8dSAndroid Build Coastguard Worker 397*cda5da8dSAndroid Build Coastguard Workerdef abspath(path): 398*cda5da8dSAndroid Build Coastguard Worker """Return an absolute path.""" 399*cda5da8dSAndroid Build Coastguard Worker path = os.fspath(path) 400*cda5da8dSAndroid Build Coastguard Worker if not isabs(path): 401*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 402*cda5da8dSAndroid Build Coastguard Worker cwd = os.getcwdb() 403*cda5da8dSAndroid Build Coastguard Worker else: 404*cda5da8dSAndroid Build Coastguard Worker cwd = os.getcwd() 405*cda5da8dSAndroid Build Coastguard Worker path = join(cwd, path) 406*cda5da8dSAndroid Build Coastguard Worker return normpath(path) 407*cda5da8dSAndroid Build Coastguard Worker 408*cda5da8dSAndroid Build Coastguard Worker 409*cda5da8dSAndroid Build Coastguard Worker# Return a canonical path (i.e. the absolute location of a file on the 410*cda5da8dSAndroid Build Coastguard Worker# filesystem). 411*cda5da8dSAndroid Build Coastguard Worker 412*cda5da8dSAndroid Build Coastguard Workerdef realpath(filename, *, strict=False): 413*cda5da8dSAndroid Build Coastguard Worker """Return the canonical path of the specified filename, eliminating any 414*cda5da8dSAndroid Build Coastguard Workersymbolic links encountered in the path.""" 415*cda5da8dSAndroid Build Coastguard Worker filename = os.fspath(filename) 416*cda5da8dSAndroid Build Coastguard Worker path, ok = _joinrealpath(filename[:0], filename, strict, {}) 417*cda5da8dSAndroid Build Coastguard Worker return abspath(path) 418*cda5da8dSAndroid Build Coastguard Worker 419*cda5da8dSAndroid Build Coastguard Worker# Join two paths, normalizing and eliminating any symbolic links 420*cda5da8dSAndroid Build Coastguard Worker# encountered in the second path. 421*cda5da8dSAndroid Build Coastguard Workerdef _joinrealpath(path, rest, strict, seen): 422*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 423*cda5da8dSAndroid Build Coastguard Worker sep = b'/' 424*cda5da8dSAndroid Build Coastguard Worker curdir = b'.' 425*cda5da8dSAndroid Build Coastguard Worker pardir = b'..' 426*cda5da8dSAndroid Build Coastguard Worker else: 427*cda5da8dSAndroid Build Coastguard Worker sep = '/' 428*cda5da8dSAndroid Build Coastguard Worker curdir = '.' 429*cda5da8dSAndroid Build Coastguard Worker pardir = '..' 430*cda5da8dSAndroid Build Coastguard Worker 431*cda5da8dSAndroid Build Coastguard Worker if isabs(rest): 432*cda5da8dSAndroid Build Coastguard Worker rest = rest[1:] 433*cda5da8dSAndroid Build Coastguard Worker path = sep 434*cda5da8dSAndroid Build Coastguard Worker 435*cda5da8dSAndroid Build Coastguard Worker while rest: 436*cda5da8dSAndroid Build Coastguard Worker name, _, rest = rest.partition(sep) 437*cda5da8dSAndroid Build Coastguard Worker if not name or name == curdir: 438*cda5da8dSAndroid Build Coastguard Worker # current dir 439*cda5da8dSAndroid Build Coastguard Worker continue 440*cda5da8dSAndroid Build Coastguard Worker if name == pardir: 441*cda5da8dSAndroid Build Coastguard Worker # parent dir 442*cda5da8dSAndroid Build Coastguard Worker if path: 443*cda5da8dSAndroid Build Coastguard Worker path, name = split(path) 444*cda5da8dSAndroid Build Coastguard Worker if name == pardir: 445*cda5da8dSAndroid Build Coastguard Worker path = join(path, pardir, pardir) 446*cda5da8dSAndroid Build Coastguard Worker else: 447*cda5da8dSAndroid Build Coastguard Worker path = pardir 448*cda5da8dSAndroid Build Coastguard Worker continue 449*cda5da8dSAndroid Build Coastguard Worker newpath = join(path, name) 450*cda5da8dSAndroid Build Coastguard Worker try: 451*cda5da8dSAndroid Build Coastguard Worker st = os.lstat(newpath) 452*cda5da8dSAndroid Build Coastguard Worker except OSError: 453*cda5da8dSAndroid Build Coastguard Worker if strict: 454*cda5da8dSAndroid Build Coastguard Worker raise 455*cda5da8dSAndroid Build Coastguard Worker is_link = False 456*cda5da8dSAndroid Build Coastguard Worker else: 457*cda5da8dSAndroid Build Coastguard Worker is_link = stat.S_ISLNK(st.st_mode) 458*cda5da8dSAndroid Build Coastguard Worker if not is_link: 459*cda5da8dSAndroid Build Coastguard Worker path = newpath 460*cda5da8dSAndroid Build Coastguard Worker continue 461*cda5da8dSAndroid Build Coastguard Worker # Resolve the symbolic link 462*cda5da8dSAndroid Build Coastguard Worker if newpath in seen: 463*cda5da8dSAndroid Build Coastguard Worker # Already seen this path 464*cda5da8dSAndroid Build Coastguard Worker path = seen[newpath] 465*cda5da8dSAndroid Build Coastguard Worker if path is not None: 466*cda5da8dSAndroid Build Coastguard Worker # use cached value 467*cda5da8dSAndroid Build Coastguard Worker continue 468*cda5da8dSAndroid Build Coastguard Worker # The symlink is not resolved, so we must have a symlink loop. 469*cda5da8dSAndroid Build Coastguard Worker if strict: 470*cda5da8dSAndroid Build Coastguard Worker # Raise OSError(errno.ELOOP) 471*cda5da8dSAndroid Build Coastguard Worker os.stat(newpath) 472*cda5da8dSAndroid Build Coastguard Worker else: 473*cda5da8dSAndroid Build Coastguard Worker # Return already resolved part + rest of the path unchanged. 474*cda5da8dSAndroid Build Coastguard Worker return join(newpath, rest), False 475*cda5da8dSAndroid Build Coastguard Worker seen[newpath] = None # not resolved symlink 476*cda5da8dSAndroid Build Coastguard Worker path, ok = _joinrealpath(path, os.readlink(newpath), strict, seen) 477*cda5da8dSAndroid Build Coastguard Worker if not ok: 478*cda5da8dSAndroid Build Coastguard Worker return join(path, rest), False 479*cda5da8dSAndroid Build Coastguard Worker seen[newpath] = path # resolved symlink 480*cda5da8dSAndroid Build Coastguard Worker 481*cda5da8dSAndroid Build Coastguard Worker return path, True 482*cda5da8dSAndroid Build Coastguard Worker 483*cda5da8dSAndroid Build Coastguard Worker 484*cda5da8dSAndroid Build Coastguard Workersupports_unicode_filenames = (sys.platform == 'darwin') 485*cda5da8dSAndroid Build Coastguard Worker 486*cda5da8dSAndroid Build Coastguard Workerdef relpath(path, start=None): 487*cda5da8dSAndroid Build Coastguard Worker """Return a relative version of a path""" 488*cda5da8dSAndroid Build Coastguard Worker 489*cda5da8dSAndroid Build Coastguard Worker if not path: 490*cda5da8dSAndroid Build Coastguard Worker raise ValueError("no path specified") 491*cda5da8dSAndroid Build Coastguard Worker 492*cda5da8dSAndroid Build Coastguard Worker path = os.fspath(path) 493*cda5da8dSAndroid Build Coastguard Worker if isinstance(path, bytes): 494*cda5da8dSAndroid Build Coastguard Worker curdir = b'.' 495*cda5da8dSAndroid Build Coastguard Worker sep = b'/' 496*cda5da8dSAndroid Build Coastguard Worker pardir = b'..' 497*cda5da8dSAndroid Build Coastguard Worker else: 498*cda5da8dSAndroid Build Coastguard Worker curdir = '.' 499*cda5da8dSAndroid Build Coastguard Worker sep = '/' 500*cda5da8dSAndroid Build Coastguard Worker pardir = '..' 501*cda5da8dSAndroid Build Coastguard Worker 502*cda5da8dSAndroid Build Coastguard Worker if start is None: 503*cda5da8dSAndroid Build Coastguard Worker start = curdir 504*cda5da8dSAndroid Build Coastguard Worker else: 505*cda5da8dSAndroid Build Coastguard Worker start = os.fspath(start) 506*cda5da8dSAndroid Build Coastguard Worker 507*cda5da8dSAndroid Build Coastguard Worker try: 508*cda5da8dSAndroid Build Coastguard Worker start_list = [x for x in abspath(start).split(sep) if x] 509*cda5da8dSAndroid Build Coastguard Worker path_list = [x for x in abspath(path).split(sep) if x] 510*cda5da8dSAndroid Build Coastguard Worker # Work out how much of the filepath is shared by start and path. 511*cda5da8dSAndroid Build Coastguard Worker i = len(commonprefix([start_list, path_list])) 512*cda5da8dSAndroid Build Coastguard Worker 513*cda5da8dSAndroid Build Coastguard Worker rel_list = [pardir] * (len(start_list)-i) + path_list[i:] 514*cda5da8dSAndroid Build Coastguard Worker if not rel_list: 515*cda5da8dSAndroid Build Coastguard Worker return curdir 516*cda5da8dSAndroid Build Coastguard Worker return join(*rel_list) 517*cda5da8dSAndroid Build Coastguard Worker except (TypeError, AttributeError, BytesWarning, DeprecationWarning): 518*cda5da8dSAndroid Build Coastguard Worker genericpath._check_arg_types('relpath', path, start) 519*cda5da8dSAndroid Build Coastguard Worker raise 520*cda5da8dSAndroid Build Coastguard Worker 521*cda5da8dSAndroid Build Coastguard Worker 522*cda5da8dSAndroid Build Coastguard Worker# Return the longest common sub-path of the sequence of paths given as input. 523*cda5da8dSAndroid Build Coastguard Worker# The paths are not normalized before comparing them (this is the 524*cda5da8dSAndroid Build Coastguard Worker# responsibility of the caller). Any trailing separator is stripped from the 525*cda5da8dSAndroid Build Coastguard Worker# returned path. 526*cda5da8dSAndroid Build Coastguard Worker 527*cda5da8dSAndroid Build Coastguard Workerdef commonpath(paths): 528*cda5da8dSAndroid Build Coastguard Worker """Given a sequence of path names, returns the longest common sub-path.""" 529*cda5da8dSAndroid Build Coastguard Worker 530*cda5da8dSAndroid Build Coastguard Worker if not paths: 531*cda5da8dSAndroid Build Coastguard Worker raise ValueError('commonpath() arg is an empty sequence') 532*cda5da8dSAndroid Build Coastguard Worker 533*cda5da8dSAndroid Build Coastguard Worker paths = tuple(map(os.fspath, paths)) 534*cda5da8dSAndroid Build Coastguard Worker if isinstance(paths[0], bytes): 535*cda5da8dSAndroid Build Coastguard Worker sep = b'/' 536*cda5da8dSAndroid Build Coastguard Worker curdir = b'.' 537*cda5da8dSAndroid Build Coastguard Worker else: 538*cda5da8dSAndroid Build Coastguard Worker sep = '/' 539*cda5da8dSAndroid Build Coastguard Worker curdir = '.' 540*cda5da8dSAndroid Build Coastguard Worker 541*cda5da8dSAndroid Build Coastguard Worker try: 542*cda5da8dSAndroid Build Coastguard Worker split_paths = [path.split(sep) for path in paths] 543*cda5da8dSAndroid Build Coastguard Worker 544*cda5da8dSAndroid Build Coastguard Worker try: 545*cda5da8dSAndroid Build Coastguard Worker isabs, = set(p[:1] == sep for p in paths) 546*cda5da8dSAndroid Build Coastguard Worker except ValueError: 547*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Can't mix absolute and relative paths") from None 548*cda5da8dSAndroid Build Coastguard Worker 549*cda5da8dSAndroid Build Coastguard Worker split_paths = [[c for c in s if c and c != curdir] for s in split_paths] 550*cda5da8dSAndroid Build Coastguard Worker s1 = min(split_paths) 551*cda5da8dSAndroid Build Coastguard Worker s2 = max(split_paths) 552*cda5da8dSAndroid Build Coastguard Worker common = s1 553*cda5da8dSAndroid Build Coastguard Worker for i, c in enumerate(s1): 554*cda5da8dSAndroid Build Coastguard Worker if c != s2[i]: 555*cda5da8dSAndroid Build Coastguard Worker common = s1[:i] 556*cda5da8dSAndroid Build Coastguard Worker break 557*cda5da8dSAndroid Build Coastguard Worker 558*cda5da8dSAndroid Build Coastguard Worker prefix = sep if isabs else sep[:0] 559*cda5da8dSAndroid Build Coastguard Worker return prefix + sep.join(common) 560*cda5da8dSAndroid Build Coastguard Worker except (TypeError, AttributeError): 561*cda5da8dSAndroid Build Coastguard Worker genericpath._check_arg_types('commonpath', *paths) 562*cda5da8dSAndroid Build Coastguard Worker raise 563