blob: 38e6eaeda9163c71388c1bb7a12889eb7bef9701 [file] [log] [blame]
Guido van Rossum54f22ed2000-02-04 15:10:34 +00001"""Pathname and path-related operations for the Macintosh."""
Guido van Rossum217a5fa1990-12-26 15:40:07 +00002
Guido van Rossum5c1d2291998-03-03 21:49:01 +00003import os
Benjamin Peterson0893a0a2008-05-09 00:27:01 +00004import warnings
Guido van Rossum217a5fa1990-12-26 15:40:07 +00005from stat import *
Martin v. Löwis05c075d2007-03-07 11:04:33 +00006import genericpath
Jack Diederich7b604642006-08-26 18:42:06 +00007from genericpath import *
Guido van Rossum217a5fa1990-12-26 15:40:07 +00008
Skip Montanaro17ab1232001-01-24 06:27:27 +00009__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
10 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +000011 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
Mark Hammond8696ebc2002-10-08 02:44:31 +000012 "walk","expanduser","expandvars","normpath","abspath",
Skip Montanaro117910d2003-02-14 19:35:31 +000013 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000014 "devnull","realpath","supports_unicode_filenames"]
Guido van Rossumb5e05e91991-01-01 18:10:40 +000015
Skip Montanaro117910d2003-02-14 19:35:31 +000016# strings representing various path-related bits and pieces
17curdir = ':'
18pardir = '::'
19extsep = '.'
20sep = ':'
21pathsep = '\n'
22defpath = ':'
23altsep = None
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000024devnull = 'Dev:Null'
Skip Montanaro117910d2003-02-14 19:35:31 +000025
Fred Drakeb4e460a2000-09-28 16:25:20 +000026# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
Guido van Rossum599f2ed1992-01-14 18:28:18 +000027
Fred Drakeb4e460a2000-09-28 16:25:20 +000028def normcase(path):
29 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000030
31
Guido van Rossum217a5fa1990-12-26 15:40:07 +000032def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000033 """Return true if a path is absolute.
34 On the Mac, relative paths begin with a colon,
35 but as a special case, paths with no colons at all are also relative.
36 Anything else is absolute (the string up to the first colon is the
37 volume name)."""
38
Fred Drake8152d322000-12-12 23:20:45 +000039 return ':' in s and s[0] != ':'
Guido van Rossum217a5fa1990-12-26 15:40:07 +000040
Guido van Rossumb5e05e91991-01-01 18:10:40 +000041
Barry Warsaw384d2491997-02-18 21:53:25 +000042def join(s, *p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000043 path = s
44 for t in p:
45 if (not s) or isabs(t):
46 path = t
47 continue
48 if t[:1] == ':':
49 t = t[1:]
50 if ':' not in path:
51 path = ':' + path
Fred Drake8152d322000-12-12 23:20:45 +000052 if path[-1:] != ':':
Guido van Rossum54f22ed2000-02-04 15:10:34 +000053 path = path + ':'
54 path = path + t
55 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000056
Guido van Rossumb5e05e91991-01-01 18:10:40 +000057
Guido van Rossumb5e05e91991-01-01 18:10:40 +000058def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000059 """Split a pathname into two parts: the directory leading up to the final
60 bit, and the basename (the filename, without colons, in that directory).
61 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000062
Guido van Rossum54f22ed2000-02-04 15:10:34 +000063 if ':' not in s: return '', s
64 colon = 0
65 for i in range(len(s)):
Fred Drakeb4e460a2000-09-28 16:25:20 +000066 if s[i] == ':': colon = i + 1
Guido van Rossum54f22ed2000-02-04 15:10:34 +000067 path, file = s[:colon-1], s[colon:]
68 if path and not ':' in path:
69 path = path + ':'
70 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000071
Guido van Rossuma48bf791996-07-23 02:28:32 +000072
73def splitext(p):
Martin v. Löwis05c075d2007-03-07 11:04:33 +000074 return genericpath._splitext(p, sep, altsep, extsep)
75splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum0ec31261995-08-10 18:09:16 +000076
77def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000078 """Split a pathname into a drive specification and the rest of the
79 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
80 empty (don't use the volume name -- it doesn't have the same
81 syntactic and semantic oddities as DOS drive letters, such as there
82 being a separate current directory per drive)."""
83
84 return '', p
Guido van Rossum0ec31261995-08-10 18:09:16 +000085
86
Guido van Rossumc629d341992-11-05 10:43:02 +000087# Short interfaces to split()
88
89def dirname(s): return split(s)[0]
90def basename(s): return split(s)[1]
91
Jack Jansen791f7d42003-01-15 22:45:48 +000092def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +000093 if not isabs(s):
94 return False
95 components = split(s)
96 return len(components) == 2 and components[1] == ''
Guido van Rossumc629d341992-11-05 10:43:02 +000097
Guido van Rossum7e4b2de1995-01-27 02:41:45 +000098def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +000099 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000100
Jack Jansen992d58b2002-04-22 13:55:43 +0000101 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000102 import Carbon.File
103 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000104 except:
105 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000106
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000107# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
108# case.
109
110def lexists(path):
111 """Test whether a path exists. Returns True for broken symbolic links"""
112
113 try:
114 st = os.lstat(path)
115 except os.error:
116 return False
117 return True
118
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000119def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000120 """Dummy to retain interface-compatibility with other operating systems."""
121 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000122
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000123
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000124def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000125 """Dummy to retain interface-compatibility with other operating systems."""
126 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000127
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000128class norm_error(Exception):
129 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000130
131def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000132 """Normalize a pathname. Will return the same result for
133 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000134
Jack Jansen2fc01092000-08-06 21:18:35 +0000135 if ":" not in s:
136 return ":"+s
137
Fred Drakeb4e460a2000-09-28 16:25:20 +0000138 comps = s.split(":")
Jack Jansen2fc01092000-08-06 21:18:35 +0000139 i = 1
140 while i < len(comps)-1:
141 if comps[i] == "" and comps[i-1] != "":
142 if i > 1:
143 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000144 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000145 else:
146 # best way to handle this is to raise an exception
Greg Ward034cbf12001-08-08 20:55:10 +0000147 raise norm_error, 'Cannot use :: immediately after volume name'
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000148 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000149 i = i + 1
150
Fred Drakeb4e460a2000-09-28 16:25:20 +0000151 s = ":".join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000152
153 # remove trailing ":" except for ":" and "Volume:"
154 if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
155 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000156 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000157
Jack Jansena68bfe21995-08-07 14:09:27 +0000158
159def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000160 """Directory tree walk with callback function.
161
162 For each directory in the directory tree rooted at top (including top
163 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
164 dirname is the name of the directory, and fnames a list of the names of
165 the files and subdirectories in dirname (excluding '.' and '..'). func
166 may modify the fnames list in-place (e.g. via del or slice assignment),
167 and walk will only recurse into the subdirectories whose names remain in
168 fnames; this can be used to implement a filter, or to impose a specific
169 order of visiting. No semantics are defined for, or required of, arg,
170 beyond that arg is always passed to func. It can be used, e.g., to pass
171 a filename pattern, or a mutable object designed to accumulate
172 statistics. Passing None for arg is common."""
Benjamin Peterson0893a0a2008-05-09 00:27:01 +0000173 warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.")
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000174 try:
175 names = os.listdir(top)
176 except os.error:
177 return
178 func(arg, top, names)
179 for name in names:
180 name = join(top, name)
Jack Jansen992d58b2002-04-22 13:55:43 +0000181 if isdir(name) and not islink(name):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000182 walk(name, func, arg)
Guido van Rossume294cf61999-01-29 18:05:18 +0000183
184
Guido van Rossume294cf61999-01-29 18:05:18 +0000185def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000186 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000187 if not isabs(path):
188 path = join(os.getcwd(), path)
189 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000190
191# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000192def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000193 path = abspath(path)
194 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000195 import Carbon.File
Tim Peters8ac14952002-05-23 15:15:30 +0000196 except ImportError:
197 return path
198 if not path:
199 return path
200 components = path.split(':')
201 path = components[0] + ':'
202 for c in components[1:]:
203 path = join(path, c)
Jack Jansen98fc6832003-02-27 23:18:46 +0000204 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
Tim Peters8ac14952002-05-23 15:15:30 +0000205 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000206
207supports_unicode_filenames = False