14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao"""Pathname and path-related operations for the Macintosh.""" 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport os 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport warnings 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom stat import * 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport genericpath 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom genericpath import * 84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao__all__ = ["normcase","isabs","join","splitdrive","split","splitext", 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "basename","dirname","commonprefix","getsize","getmtime", 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "getatime","getctime", "islink","exists","lexists","isdir","isfile", 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "walk","expanduser","expandvars","normpath","abspath", 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "curdir","pardir","sep","pathsep","defpath","altsep","extsep", 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "devnull","realpath","supports_unicode_filenames"] 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# strings representing various path-related bits and pieces 174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaocurdir = ':' 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaopardir = '::' 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoextsep = '.' 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaosep = ':' 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaopathsep = '\n' 224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodefpath = ':' 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoaltsep = None 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodevnull = 'Dev:Null' 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here. 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef normcase(path): 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path.lower() 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef isabs(s): 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Return true if a path is absolute. 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao On the Mac, relative paths begin with a colon, 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao but as a special case, paths with no colons at all are also relative. 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Anything else is absolute (the string up to the first colon is the 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao volume name).""" 384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return ':' in s and s[0] != ':' 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef join(s, *p): 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = s 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for t in p: 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if (not s) or isabs(t): 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = t 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao continue 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if t[:1] == ':': 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao t = t[1:] 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if ':' not in path: 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = ':' + path 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if path[-1:] != ':': 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = path + ':' 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = path + t 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef split(s): 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Split a pathname into two parts: the directory leading up to the final 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao bit, and the basename (the filename, without colons, in that directory). 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao The result (s, t) is such that join(s, t) yields the original argument.""" 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if ':' not in s: return '', s 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao colon = 0 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for i in range(len(s)): 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if s[i] == ':': colon = i + 1 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path, file = s[:colon-1], s[colon:] 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if path and not ':' in path: 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = path + ':' 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path, file 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef splitext(p): 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return genericpath._splitext(p, sep, altsep, extsep) 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaosplitext.__doc__ = genericpath._splitext.__doc__ 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef splitdrive(p): 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Split a pathname into a drive specification and the rest of the 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path. Useful on DOS/Windows/NT; on the Mac, the drive is always 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao empty (don't use the volume name -- it doesn't have the same 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao syntactic and semantic oddities as DOS drive letters, such as there 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao being a separate current directory per drive).""" 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return '', p 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Short interfaces to split() 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef dirname(s): return split(s)[0] 904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef basename(s): return split(s)[1] 914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef ismount(s): 934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if not isabs(s): 944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return False 954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao components = split(s) 964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return len(components) == 2 and components[1] == '' 974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef islink(s): 994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Return true if the pathname refers to a symbolic link.""" 1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import Carbon.File 1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return Carbon.File.ResolveAliasFile(s, 0)[2] 1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except: 1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return False 1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any 1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# case. 1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef lexists(path): 1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Test whether a path exists. Returns True for broken symbolic links""" 1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao st = os.lstat(path) 1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except os.error: 1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return False 1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return True 1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef expandvars(path): 1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Dummy to retain interface-compatibility with other operating systems.""" 1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path 1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef expanduser(path): 1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Dummy to retain interface-compatibility with other operating systems.""" 1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path 1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass norm_error(Exception): 1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Path cannot be normalized""" 1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef normpath(s): 1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Normalize a pathname. Will return the same result for 1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao equivalent paths.""" 1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if ":" not in s: 1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return ":"+s 1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao comps = s.split(":") 1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = 1 1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao while i < len(comps)-1: 1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if comps[i] == "" and comps[i-1] != "": 1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if i > 1: 1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao del comps[i-1:i+1] 1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = i - 1 1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # best way to handle this is to raise an exception 1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise norm_error, 'Cannot use :: immediately after volume name' 1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = i + 1 1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao s = ":".join(comps) 1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # remove trailing ":" except for ":" and "Volume:" 1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s): 1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao s = s[:-1] 1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return s 1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef walk(top, func, arg): 1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Directory tree walk with callback function. 1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao For each directory in the directory tree rooted at top (including top 1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao itself, but excluding '.' and '..'), call func(arg, dirname, fnames). 1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao dirname is the name of the directory, and fnames a list of the names of 1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao the files and subdirectories in dirname (excluding '.' and '..'). func 1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao may modify the fnames list in-place (e.g. via del or slice assignment), 1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao and walk will only recurse into the subdirectories whose names remain in 1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao fnames; this can be used to implement a filter, or to impose a specific 1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao order of visiting. No semantics are defined for, or required of, arg, 1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao beyond that arg is always passed to func. It can be used, e.g., to pass 1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao a filename pattern, or a mutable object designed to accumulate 1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao statistics. Passing None for arg is common.""" 1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.", 1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao stacklevel=2) 1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao names = os.listdir(top) 1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except os.error: 1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao func(arg, top, names) 1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for name in names: 1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao name = join(top, name) 1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if isdir(name) and not islink(name): 1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao walk(name, func, arg) 1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef abspath(path): 1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Return an absolute path.""" 1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if not isabs(path): 1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if isinstance(path, unicode): 1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cwd = os.getcwdu() 1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cwd = os.getcwd() 1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = join(cwd, path) 1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return normpath(path) 1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# realpath is a no-op on systems without islink support 1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef realpath(path): 1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = abspath(path) 1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import Carbon.File 2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except ImportError: 2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path 2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if not path: 2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path 2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao components = path.split(':') 2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = components[0] + ':' 2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for c in components[1:]: 2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = join(path, c) 2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname() 2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except Carbon.File.Error: 2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return path 2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaosupports_unicode_filenames = True 216