1b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Module 'ntpath' -- common operations on WinNT/Win95 pathnames 2b410d6e4ce58c177569d42b51772f7bb239a24a3darylm"""Common pathname manipulations, WindowsNT/95 version. 3b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 4b410d6e4ce58c177569d42b51772f7bb239a24a3darylmInstead of importing this module directly, import os and refer to this 5b410d6e4ce58c177569d42b51772f7bb239a24a3darylmmodule as os.path. 6b410d6e4ce58c177569d42b51772f7bb239a24a3darylm""" 7b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 8b410d6e4ce58c177569d42b51772f7bb239a24a3darylmimport os 9b410d6e4ce58c177569d42b51772f7bb239a24a3darylmimport sys 10b410d6e4ce58c177569d42b51772f7bb239a24a3darylmimport stat 11b410d6e4ce58c177569d42b51772f7bb239a24a3darylmimport genericpath 12b410d6e4ce58c177569d42b51772f7bb239a24a3darylmimport warnings 13b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 14b410d6e4ce58c177569d42b51772f7bb239a24a3darylmfrom genericpath import * 15b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 16b410d6e4ce58c177569d42b51772f7bb239a24a3darylm__all__ = ["normcase","isabs","join","splitdrive","split","splitext", 17b410d6e4ce58c177569d42b51772f7bb239a24a3darylm "basename","dirname","commonprefix","getsize","getmtime", 18b410d6e4ce58c177569d42b51772f7bb239a24a3darylm "getatime","getctime", "islink","exists","lexists","isdir","isfile", 19b410d6e4ce58c177569d42b51772f7bb239a24a3darylm "ismount","walk","expanduser","expandvars","normpath","abspath", 20b410d6e4ce58c177569d42b51772f7bb239a24a3darylm "splitunc","curdir","pardir","sep","pathsep","defpath","altsep", 21b410d6e4ce58c177569d42b51772f7bb239a24a3darylm "extsep","devnull","realpath","supports_unicode_filenames","relpath"] 22b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 23b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# strings representing various path-related bits and pieces 24b410d6e4ce58c177569d42b51772f7bb239a24a3darylmcurdir = '.' 25b410d6e4ce58c177569d42b51772f7bb239a24a3darylmpardir = '..' 26b410d6e4ce58c177569d42b51772f7bb239a24a3darylmextsep = '.' 27b410d6e4ce58c177569d42b51772f7bb239a24a3darylmsep = '\\' 28b410d6e4ce58c177569d42b51772f7bb239a24a3darylmpathsep = ';' 29b410d6e4ce58c177569d42b51772f7bb239a24a3darylmaltsep = '/' 30b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdefpath = '.;C:\\bin' 31b410d6e4ce58c177569d42b51772f7bb239a24a3darylmif 'ce' in sys.builtin_module_names: 32b410d6e4ce58c177569d42b51772f7bb239a24a3darylm defpath = '\\Windows' 33b410d6e4ce58c177569d42b51772f7bb239a24a3darylmelif 'os2' in sys.builtin_module_names: 34b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # OS/2 w/ VACPP 35b410d6e4ce58c177569d42b51772f7bb239a24a3darylm altsep = '/' 36b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdevnull = 'nul' 37b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 38b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Normalize the case of a pathname and map slashes to backslashes. 39b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Other normalizations (such as optimizing '../' away) are not done 40b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# (this is done by normpath). 41b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 42b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef normcase(s): 43b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Normalize case of pathname. 44b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 45b410d6e4ce58c177569d42b51772f7bb239a24a3darylm Makes all characters lowercase and all slashes into backslashes.""" 46b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return s.replace("/", "\\").lower() 47b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 48b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 49b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Return whether a path is absolute. 50b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Trivial in Posix, harder on the Mac or MS-DOS. 51b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# For DOS it is absolute if it starts with a slash or backslash (current 52b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# volume), or if a pathname after the volume letter and colon / UNC resource 53b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# starts with a slash or backslash. 54b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 55b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef isabs(s): 56b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Test whether a path is absolute""" 57b410d6e4ce58c177569d42b51772f7bb239a24a3darylm s = splitdrive(s)[1] 58b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return s != '' and s[:1] in '/\\' 59b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 60b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 61b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Join two (or more) paths. 62b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 63b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef join(a, *p): 64b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Join two or more pathname components, inserting "\\" as needed. 65b410d6e4ce58c177569d42b51772f7bb239a24a3darylm If any component is an absolute path, all previous path components 66b410d6e4ce58c177569d42b51772f7bb239a24a3darylm will be discarded.""" 67b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = a 68b410d6e4ce58c177569d42b51772f7bb239a24a3darylm for b in p: 69b410d6e4ce58c177569d42b51772f7bb239a24a3darylm b_wins = 0 # set to 1 iff b makes path irrelevant 70b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path == "": 71b410d6e4ce58c177569d42b51772f7bb239a24a3darylm b_wins = 1 72b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 73b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif isabs(b): 74b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # This probably wipes out path so far. However, it's more 75b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # complicated if path begins with a drive letter: 76b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # 1. join('c:', '/a') == 'c:/a' 77b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # 2. join('c:/', '/a') == 'c:/a' 78b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # But 79b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # 3. join('c:/a', '/b') == '/b' 80b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # 4. join('c:', 'd:/') = 'd:/' 81b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # 5. join('c:/', 'd:/') = 'd:/' 82b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path[1:2] != ":" or b[1:2] == ":": 83b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # Path doesn't start with a drive letter, or cases 4 and 5. 84b410d6e4ce58c177569d42b51772f7bb239a24a3darylm b_wins = 1 85b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 86b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # Else path has a drive letter, and b doesn't but is absolute. 87b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif len(path) > 3 or (len(path) == 3 and 88b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path[-1] not in "/\\"): 89b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # case 3 90b410d6e4ce58c177569d42b51772f7bb239a24a3darylm b_wins = 1 91b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 92b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if b_wins: 93b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = b 94b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 95b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # Join, and ensure there's a separator. 96b410d6e4ce58c177569d42b51772f7bb239a24a3darylm assert len(path) > 0 97b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path[-1] in "/\\": 98b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if b and b[0] in "/\\": 99b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path += b[1:] 100b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 101b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path += b 102b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif path[-1] == ":": 103b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path += b 104b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif b: 105b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if b[0] in "/\\": 106b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path += b 107b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 108b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path += "\\" + b 109b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 110b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # path is not empty and does not end with a backslash, 111b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # but b is empty; since, e.g., split('a/') produces 112b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # ('a', ''), it's best if join() adds a backslash in 113b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # this case. 114b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path += '\\' 115b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 116b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return path 117b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 118b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 119b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Split a path in a drive specification (a drive letter followed by a 120b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# colon) and the path specification. 121b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# It is always true that drivespec + pathspec == p 122b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef splitdrive(p): 123b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Split a pathname into drive and path specifiers. Returns a 2-tuple 124b410d6e4ce58c177569d42b51772f7bb239a24a3darylm"(drive,path)"; either part may be empty""" 125b410d6e4ce58c177569d42b51772f7bb239a24a3darylm pparts = p.split(':', 2) 126b410d6e4ce58c177569d42b51772f7bb239a24a3darylm numparts = len(pparts) 127b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if numparts == 2: 128b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return pparts[0] + ':', pparts[1] 129b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 130b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if numparts == 1: 131b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return '', pparts[0] 132b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return '', p 133b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 134b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 135b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Parse UNC paths 136b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef splitunc(p): 137b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Split a pathname into UNC mount point and relative path specifiers. 138b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 139b410d6e4ce58c177569d42b51772f7bb239a24a3darylm Return a 2-tuple (unc, rest); either part may be empty. 140b410d6e4ce58c177569d42b51772f7bb239a24a3darylm If unc is not empty, it has the form '//host/mount' (or similar 141b410d6e4ce58c177569d42b51772f7bb239a24a3darylm using backslashes). unc+rest is always the input path. 142b410d6e4ce58c177569d42b51772f7bb239a24a3darylm Paths containing drive letters never have an UNC part. 143b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """ 144b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if len(p.split(':', 2)) > 1: 145b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return '', p # Drive letter present 146b410d6e4ce58c177569d42b51772f7bb239a24a3darylm firstTwo = p[0:2] 147b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if firstTwo == '//' or firstTwo == '\\\\': 148b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # is a UNC path: 149b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter 150b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # \\machine\mountpoint\directories... 151b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # directory ^^^^^^^^^^^^^^^ 152b410d6e4ce58c177569d42b51772f7bb239a24a3darylm normp = normcase(p) 153b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = normp.find('\\', 2) 154b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if index == -1: 155b410d6e4ce58c177569d42b51772f7bb239a24a3darylm ##raise RuntimeError, 'illegal UNC path: "' + p + '"' 156b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return ("", p) 157b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = normp.find('\\', index + 1) 158b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if index == -1: 159b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = len(p) 160b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return p[:index], p[index:] 161b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return '', p 162b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 163b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 164b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Split a path in head (everything up to the last '/') and tail (the 165b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# rest). After the trailing '/' is stripped, the invariant 166b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# join(head, tail) == p holds. 167b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# The resulting head won't end in '/' unless it is the root. 168b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 169b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef split(p): 170b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Split a pathname. 171b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 172b410d6e4ce58c177569d42b51772f7bb239a24a3darylm Return tuple (head, tail) where tail is everything after the final slash. 173b410d6e4ce58c177569d42b51772f7bb239a24a3darylm Either part may be empty.""" 174b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 175b410d6e4ce58c177569d42b51772f7bb239a24a3darylm d, p = splitdrive(p) 176b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # set i to index beyond p's last slash 177b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i = len(p) 178b410d6e4ce58c177569d42b51772f7bb239a24a3darylm while i and p[i-1] not in '/\\': 179b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i = i - 1 180b410d6e4ce58c177569d42b51772f7bb239a24a3darylm head, tail = p[:i], p[i:] # now tail has no slashes 181b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # remove trailing slashes from head, unless it's all slashes 182b410d6e4ce58c177569d42b51772f7bb239a24a3darylm head2 = head 183b410d6e4ce58c177569d42b51772f7bb239a24a3darylm while head2 and head2[-1] in '/\\': 184b410d6e4ce58c177569d42b51772f7bb239a24a3darylm head2 = head2[:-1] 185b410d6e4ce58c177569d42b51772f7bb239a24a3darylm head = head2 or head 186b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return d + head, tail 187b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 188b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 189b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Split a path in root and extension. 190b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# The extension is everything starting at the last dot in the last 191b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# pathname component; the root is everything before that. 192b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# It is always true that root + ext == p. 193b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 194b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef splitext(p): 195b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return genericpath._splitext(p, sep, altsep, extsep) 196b410d6e4ce58c177569d42b51772f7bb239a24a3darylmsplitext.__doc__ = genericpath._splitext.__doc__ 197b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 198b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 199b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Return the tail (basename) part of a path. 200b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 201b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef basename(p): 202b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Returns the final component of a pathname""" 203b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return split(p)[1] 204b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 205b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 206b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Return the head (dirname) part of a path. 207b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 208b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef dirname(p): 209b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Returns the directory component of a pathname""" 210b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return split(p)[0] 211b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 212b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Is a path a symbolic link? 213b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# This will always return false on systems where posix.lstat doesn't exist. 214b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 215b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef islink(path): 216b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Test for symbolic link. 217b410d6e4ce58c177569d42b51772f7bb239a24a3darylm On WindowsNT/95 and OS/2 always returns false 218b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """ 219b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return False 220b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 221b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# alias exists to lexists 222b410d6e4ce58c177569d42b51772f7bb239a24a3darylmlexists = exists 223b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 224b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Is a path a mount point? Either a root (with or without drive letter) 225b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# or an UNC path with at most a / or \ after the mount point. 226b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 227b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef ismount(path): 228b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Test whether a path is a mount point (defined as root of drive)""" 229b410d6e4ce58c177569d42b51772f7bb239a24a3darylm unc, rest = splitunc(path) 230b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if unc: 231b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return rest in ("", "/", "\\") 232b410d6e4ce58c177569d42b51772f7bb239a24a3darylm p = splitdrive(path)[1] 233b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return len(p) == 1 and p[0] in '/\\' 234b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 235b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 236b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Directory tree walk. 237b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# For each directory under top (including top itself, but excluding 238b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# '.' and '..'), func(arg, dirname, filenames) is called, where 239b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# dirname is the name of the directory and filenames is the list 240b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# of files (and subdirectories etc.) in the directory. 241b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# The func may modify the filenames list, to implement a filter, 242b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# or to impose a different order of visiting. 243b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 244b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef walk(top, func, arg): 245b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Directory tree walk with callback function. 246b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 247b410d6e4ce58c177569d42b51772f7bb239a24a3darylm For each directory in the directory tree rooted at top (including top 248b410d6e4ce58c177569d42b51772f7bb239a24a3darylm itself, but excluding '.' and '..'), call func(arg, dirname, fnames). 249b410d6e4ce58c177569d42b51772f7bb239a24a3darylm dirname is the name of the directory, and fnames a list of the names of 250b410d6e4ce58c177569d42b51772f7bb239a24a3darylm the files and subdirectories in dirname (excluding '.' and '..'). func 251b410d6e4ce58c177569d42b51772f7bb239a24a3darylm may modify the fnames list in-place (e.g. via del or slice assignment), 252b410d6e4ce58c177569d42b51772f7bb239a24a3darylm and walk will only recurse into the subdirectories whose names remain in 253b410d6e4ce58c177569d42b51772f7bb239a24a3darylm fnames; this can be used to implement a filter, or to impose a specific 254b410d6e4ce58c177569d42b51772f7bb239a24a3darylm order of visiting. No semantics are defined for, or required of, arg, 255b410d6e4ce58c177569d42b51772f7bb239a24a3darylm beyond that arg is always passed to func. It can be used, e.g., to pass 256b410d6e4ce58c177569d42b51772f7bb239a24a3darylm a filename pattern, or a mutable object designed to accumulate 257b410d6e4ce58c177569d42b51772f7bb239a24a3darylm statistics. Passing None for arg is common.""" 258b410d6e4ce58c177569d42b51772f7bb239a24a3darylm warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.", 259b410d6e4ce58c177569d42b51772f7bb239a24a3darylm stacklevel=2) 260b410d6e4ce58c177569d42b51772f7bb239a24a3darylm try: 261b410d6e4ce58c177569d42b51772f7bb239a24a3darylm names = os.listdir(top) 262b410d6e4ce58c177569d42b51772f7bb239a24a3darylm except os.error: 263b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return 264b410d6e4ce58c177569d42b51772f7bb239a24a3darylm func(arg, top, names) 265b410d6e4ce58c177569d42b51772f7bb239a24a3darylm for name in names: 266b410d6e4ce58c177569d42b51772f7bb239a24a3darylm name = join(top, name) 267b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if isdir(name): 268b410d6e4ce58c177569d42b51772f7bb239a24a3darylm walk(name, func, arg) 269b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 270b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 271b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Expand paths beginning with '~' or '~user'. 272b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# '~' means $HOME; '~user' means that user's home directory. 273b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# If the path doesn't begin with '~', or if the user or $HOME is unknown, 274b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# the path is returned unchanged (leaving error reporting to whatever 275b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# function is called with the expanded path as argument). 276b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# See also module 'glob' for expansion of *, ? and [...] in pathnames. 277b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# (A function should also be defined to do full *sh-style environment 278b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# variable expansion.) 279b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 280b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef expanduser(path): 281b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Expand ~ and ~user constructs. 282b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 283b410d6e4ce58c177569d42b51772f7bb239a24a3darylm If user or $HOME is unknown, do nothing.""" 284b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path[:1] != '~': 285b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return path 286b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i, n = 1, len(path) 287b410d6e4ce58c177569d42b51772f7bb239a24a3darylm while i < n and path[i] not in '/\\': 288b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i = i + 1 289b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 290b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if 'HOME' in os.environ: 291b410d6e4ce58c177569d42b51772f7bb239a24a3darylm userhome = os.environ['HOME'] 292b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif 'USERPROFILE' in os.environ: 293b410d6e4ce58c177569d42b51772f7bb239a24a3darylm userhome = os.environ['USERPROFILE'] 294b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif not 'HOMEPATH' in os.environ: 295b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return path 296b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 297b410d6e4ce58c177569d42b51772f7bb239a24a3darylm try: 298b410d6e4ce58c177569d42b51772f7bb239a24a3darylm drive = os.environ['HOMEDRIVE'] 299b410d6e4ce58c177569d42b51772f7bb239a24a3darylm except KeyError: 300b410d6e4ce58c177569d42b51772f7bb239a24a3darylm drive = '' 301b410d6e4ce58c177569d42b51772f7bb239a24a3darylm userhome = join(drive, os.environ['HOMEPATH']) 302b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 303b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if i != 1: #~user 304b410d6e4ce58c177569d42b51772f7bb239a24a3darylm userhome = join(dirname(userhome), path[1:i]) 305b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 306b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return userhome + path[i:] 307b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 308b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 309b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Expand paths containing shell variable substitutions. 310b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# The following rules apply: 311b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# - no expansion within single quotes 312b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# - '$$' is translated into '$' 313b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2% 314b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# - ${varname} is accepted. 315b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# - $varname is accepted. 316b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# - %varname% is accepted. 317b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# - varnames can be made out of letters, digits and the characters '_-' 318b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# (though is not verified in the ${varname} and %varname% cases) 319b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# XXX With COMMAND.COM you can use any characters in a variable name, 320b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# XXX except '^|<>='. 321b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 322b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef expandvars(path): 323b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Expand shell variables of the forms $var, ${var} and %var%. 324b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 325b410d6e4ce58c177569d42b51772f7bb239a24a3darylm Unknown variables are left unchanged.""" 326b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if '$' not in path and '%' not in path: 327b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return path 328b410d6e4ce58c177569d42b51772f7bb239a24a3darylm import string 329b410d6e4ce58c177569d42b51772f7bb239a24a3darylm varchars = string.ascii_letters + string.digits + '_-' 330b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = '' 331b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = 0 332b410d6e4ce58c177569d42b51772f7bb239a24a3darylm pathlen = len(path) 333b410d6e4ce58c177569d42b51772f7bb239a24a3darylm while index < pathlen: 334b410d6e4ce58c177569d42b51772f7bb239a24a3darylm c = path[index] 335b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if c == '\'': # no expansion within single quotes 336b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = path[index + 1:] 337b410d6e4ce58c177569d42b51772f7bb239a24a3darylm pathlen = len(path) 338b410d6e4ce58c177569d42b51772f7bb239a24a3darylm try: 339b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = path.index('\'') 340b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + '\'' + path[:index + 1] 341b410d6e4ce58c177569d42b51772f7bb239a24a3darylm except ValueError: 342b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + path 343b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = pathlen - 1 344b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif c == '%': # variable or '%' 345b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path[index + 1:index + 2] == '%': 346b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + c 347b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = index + 1 348b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 349b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = path[index+1:] 350b410d6e4ce58c177569d42b51772f7bb239a24a3darylm pathlen = len(path) 351b410d6e4ce58c177569d42b51772f7bb239a24a3darylm try: 352b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = path.index('%') 353b410d6e4ce58c177569d42b51772f7bb239a24a3darylm except ValueError: 354b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + '%' + path 355b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = pathlen - 1 356b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 357b410d6e4ce58c177569d42b51772f7bb239a24a3darylm var = path[:index] 358b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if var in os.environ: 359b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + os.environ[var] 360b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 361b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + '%' + var + '%' 362b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif c == '$': # variable or '$$' 363b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path[index + 1:index + 2] == '$': 364b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + c 365b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = index + 1 366b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif path[index + 1:index + 2] == '{': 367b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = path[index+2:] 368b410d6e4ce58c177569d42b51772f7bb239a24a3darylm pathlen = len(path) 369b410d6e4ce58c177569d42b51772f7bb239a24a3darylm try: 370b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = path.index('}') 371b410d6e4ce58c177569d42b51772f7bb239a24a3darylm var = path[:index] 372b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if var in os.environ: 373b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + os.environ[var] 374b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 375b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + '${' + var + '}' 376b410d6e4ce58c177569d42b51772f7bb239a24a3darylm except ValueError: 377b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + '${' + path 378b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = pathlen - 1 379b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 380b410d6e4ce58c177569d42b51772f7bb239a24a3darylm var = '' 381b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = index + 1 382b410d6e4ce58c177569d42b51772f7bb239a24a3darylm c = path[index:index + 1] 383b410d6e4ce58c177569d42b51772f7bb239a24a3darylm while c != '' and c in varchars: 384b410d6e4ce58c177569d42b51772f7bb239a24a3darylm var = var + c 385b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = index + 1 386b410d6e4ce58c177569d42b51772f7bb239a24a3darylm c = path[index:index + 1] 387b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if var in os.environ: 388b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + os.environ[var] 389b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 390b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + '$' + var 391b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if c != '': 392b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = index - 1 393b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 394b410d6e4ce58c177569d42b51772f7bb239a24a3darylm res = res + c 395b410d6e4ce58c177569d42b51772f7bb239a24a3darylm index = index + 1 396b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return res 397b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 398b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 399b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B. 400b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Previously, this function also truncated pathnames to 8+3 format, 401b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# but as this module is called "ntpath", that's obviously wrong! 402b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 403b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef normpath(path): 404b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Normalize path, eliminating double slashes, etc.""" 405b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # Preserve unicode (if path is unicode) 406b410d6e4ce58c177569d42b51772f7bb239a24a3darylm backslash, dot = (u'\\', u'.') if isinstance(path, unicode) else ('\\', '.') 407b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path.startswith(('\\\\.\\', '\\\\?\\')): 408b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # in the case of paths with these prefixes: 409b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # \\.\ -> device names 410b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # \\?\ -> literal paths 411b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # do not do any normalization, but return the path unchanged 412b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return path 413b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = path.replace("/", "\\") 414b410d6e4ce58c177569d42b51772f7bb239a24a3darylm prefix, path = splitdrive(path) 415b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # We need to be careful here. If the prefix is empty, and the path starts 416b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # with a backslash, it could either be an absolute path on the current 417b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It 418b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # is therefore imperative NOT to collapse multiple backslashes blindly in 419b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # that case. 420b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # The code below preserves multiple backslashes when there is no drive 421b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # letter. This means that the invalid filename \\\a\b is preserved 422b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # unchanged, where a\\\b is normalised to a\b. It's not clear that there 423b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # is any better behaviour for such edge cases. 424b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if prefix == '': 425b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # No drive letter - preserve initial backslashes 426b410d6e4ce58c177569d42b51772f7bb239a24a3darylm while path[:1] == "\\": 427b410d6e4ce58c177569d42b51772f7bb239a24a3darylm prefix = prefix + backslash 428b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = path[1:] 429b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 430b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # We have a drive letter - collapse initial backslashes 431b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path.startswith("\\"): 432b410d6e4ce58c177569d42b51772f7bb239a24a3darylm prefix = prefix + backslash 433b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = path.lstrip("\\") 434b410d6e4ce58c177569d42b51772f7bb239a24a3darylm comps = path.split("\\") 435b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i = 0 436b410d6e4ce58c177569d42b51772f7bb239a24a3darylm while i < len(comps): 437b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if comps[i] in ('.', ''): 438b410d6e4ce58c177569d42b51772f7bb239a24a3darylm del comps[i] 439b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif comps[i] == '..': 440b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if i > 0 and comps[i-1] != '..': 441b410d6e4ce58c177569d42b51772f7bb239a24a3darylm del comps[i-1:i+1] 442b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i -= 1 443b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif i == 0 and prefix.endswith("\\"): 444b410d6e4ce58c177569d42b51772f7bb239a24a3darylm del comps[i] 445b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 446b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i += 1 447b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 448b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i += 1 449b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # If the path is now empty, substitute '.' 450b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if not prefix and not comps: 451b410d6e4ce58c177569d42b51772f7bb239a24a3darylm comps.append(dot) 452b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return prefix + backslash.join(comps) 453b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 454b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 455b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Return an absolute path. 456b410d6e4ce58c177569d42b51772f7bb239a24a3darylmtry: 457b410d6e4ce58c177569d42b51772f7bb239a24a3darylm from nt import _getfullpathname 458b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 459b410d6e4ce58c177569d42b51772f7bb239a24a3darylmexcept ImportError: # not running on Windows - mock up something sensible 460b410d6e4ce58c177569d42b51772f7bb239a24a3darylm def abspath(path): 461b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Return the absolute version of a path.""" 462b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if not isabs(path): 463b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if isinstance(path, unicode): 464b410d6e4ce58c177569d42b51772f7bb239a24a3darylm cwd = os.getcwdu() 465b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 466b410d6e4ce58c177569d42b51772f7bb239a24a3darylm cwd = os.getcwd() 467b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = join(cwd, path) 468b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return normpath(path) 469b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 470b410d6e4ce58c177569d42b51772f7bb239a24a3darylmelse: # use native Windows method on Windows 471b410d6e4ce58c177569d42b51772f7bb239a24a3darylm def abspath(path): 472b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Return the absolute version of a path.""" 473b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 474b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path: # Empty path must return current working directory. 475b410d6e4ce58c177569d42b51772f7bb239a24a3darylm try: 476b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = _getfullpathname(path) 477b410d6e4ce58c177569d42b51772f7bb239a24a3darylm except WindowsError: 478b410d6e4ce58c177569d42b51772f7bb239a24a3darylm pass # Bad path - return unchanged. 479b410d6e4ce58c177569d42b51772f7bb239a24a3darylm elif isinstance(path, unicode): 480b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = os.getcwdu() 481b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 482b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path = os.getcwd() 483b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return normpath(path) 484b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 485b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# realpath is a no-op on systems without islink support 486b410d6e4ce58c177569d42b51772f7bb239a24a3darylmrealpath = abspath 487b410d6e4ce58c177569d42b51772f7bb239a24a3darylm# Win9x family and earlier have no Unicode filename support. 488b410d6e4ce58c177569d42b51772f7bb239a24a3darylmsupports_unicode_filenames = (hasattr(sys, "getwindowsversion") and 489b410d6e4ce58c177569d42b51772f7bb239a24a3darylm sys.getwindowsversion()[3] >= 2) 490b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 491b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef _abspath_split(path): 492b410d6e4ce58c177569d42b51772f7bb239a24a3darylm abs = abspath(normpath(path)) 493b410d6e4ce58c177569d42b51772f7bb239a24a3darylm prefix, rest = splitunc(abs) 494b410d6e4ce58c177569d42b51772f7bb239a24a3darylm is_unc = bool(prefix) 495b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if not is_unc: 496b410d6e4ce58c177569d42b51772f7bb239a24a3darylm prefix, rest = splitdrive(abs) 497b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return is_unc, prefix, [x for x in rest.split(sep) if x] 498b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 499b410d6e4ce58c177569d42b51772f7bb239a24a3darylmdef relpath(path, start=curdir): 500b410d6e4ce58c177569d42b51772f7bb239a24a3darylm """Return a relative version of a path""" 501b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 502b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if not path: 503b410d6e4ce58c177569d42b51772f7bb239a24a3darylm raise ValueError("no path specified") 504b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 505b410d6e4ce58c177569d42b51772f7bb239a24a3darylm start_is_unc, start_prefix, start_list = _abspath_split(start) 506b410d6e4ce58c177569d42b51772f7bb239a24a3darylm path_is_unc, path_prefix, path_list = _abspath_split(path) 507b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 508b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path_is_unc ^ start_is_unc: 509b410d6e4ce58c177569d42b51772f7bb239a24a3darylm raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)" 510b410d6e4ce58c177569d42b51772f7bb239a24a3darylm % (path, start)) 511b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path_prefix.lower() != start_prefix.lower(): 512b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if path_is_unc: 513b410d6e4ce58c177569d42b51772f7bb239a24a3darylm raise ValueError("path is on UNC root %s, start on UNC root %s" 514b410d6e4ce58c177569d42b51772f7bb239a24a3darylm % (path_prefix, start_prefix)) 515b410d6e4ce58c177569d42b51772f7bb239a24a3darylm else: 516b410d6e4ce58c177569d42b51772f7bb239a24a3darylm raise ValueError("path is on drive %s, start on drive %s" 517b410d6e4ce58c177569d42b51772f7bb239a24a3darylm % (path_prefix, start_prefix)) 518b410d6e4ce58c177569d42b51772f7bb239a24a3darylm # Work out how much of the filepath is shared by start and path. 519b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i = 0 520b410d6e4ce58c177569d42b51772f7bb239a24a3darylm for e1, e2 in zip(start_list, path_list): 521b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if e1.lower() != e2.lower(): 522b410d6e4ce58c177569d42b51772f7bb239a24a3darylm break 523b410d6e4ce58c177569d42b51772f7bb239a24a3darylm i += 1 524b410d6e4ce58c177569d42b51772f7bb239a24a3darylm 525b410d6e4ce58c177569d42b51772f7bb239a24a3darylm rel_list = [pardir] * (len(start_list)-i) + path_list[i:] 526b410d6e4ce58c177569d42b51772f7bb239a24a3darylm if not rel_list: 527b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return curdir 528b410d6e4ce58c177569d42b51772f7bb239a24a3darylm return join(*rel_list) 529