blob: f50f66072d9a4f23d8a6103c93363a4270dadad9 [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
Guido van Rossum217a5fa1990-12-26 15:40:07 +00004from stat import *
5
Skip Montanaro17ab1232001-01-24 06:27:27 +00006__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
7 "basename","dirname","commonprefix","getsize","getmtime",
Martin v. Löwis96a60e42002-12-31 13:11:54 +00008 "getatime","getctime", "islink","exists","isdir","isfile",
Mark Hammond8696ebc2002-10-08 02:44:31 +00009 "walk","expanduser","expandvars","normpath","abspath",
Skip Montanaro117910d2003-02-14 19:35:31 +000010 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000011 "devnull","realpath","supports_unicode_filenames"]
Guido van Rossumb5e05e91991-01-01 18:10:40 +000012
Skip Montanaro117910d2003-02-14 19:35:31 +000013# strings representing various path-related bits and pieces
14curdir = ':'
15pardir = '::'
16extsep = '.'
17sep = ':'
18pathsep = '\n'
19defpath = ':'
20altsep = None
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000021devnull = 'Dev:Null'
Skip Montanaro117910d2003-02-14 19:35:31 +000022
Fred Drakeb4e460a2000-09-28 16:25:20 +000023# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
Guido van Rossum599f2ed1992-01-14 18:28:18 +000024
Fred Drakeb4e460a2000-09-28 16:25:20 +000025def normcase(path):
26 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000027
28
Guido van Rossum217a5fa1990-12-26 15:40:07 +000029def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000030 """Return true if a path is absolute.
31 On the Mac, relative paths begin with a colon,
32 but as a special case, paths with no colons at all are also relative.
33 Anything else is absolute (the string up to the first colon is the
34 volume name)."""
35
Fred Drake8152d322000-12-12 23:20:45 +000036 return ':' in s and s[0] != ':'
Guido van Rossum217a5fa1990-12-26 15:40:07 +000037
Guido van Rossumb5e05e91991-01-01 18:10:40 +000038
Barry Warsaw384d2491997-02-18 21:53:25 +000039def join(s, *p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000040 path = s
41 for t in p:
42 if (not s) or isabs(t):
43 path = t
44 continue
45 if t[:1] == ':':
46 t = t[1:]
47 if ':' not in path:
48 path = ':' + path
Fred Drake8152d322000-12-12 23:20:45 +000049 if path[-1:] != ':':
Guido van Rossum54f22ed2000-02-04 15:10:34 +000050 path = path + ':'
51 path = path + t
52 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000053
Guido van Rossumb5e05e91991-01-01 18:10:40 +000054
Guido van Rossumb5e05e91991-01-01 18:10:40 +000055def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000056 """Split a pathname into two parts: the directory leading up to the final
57 bit, and the basename (the filename, without colons, in that directory).
58 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000059
Guido van Rossum54f22ed2000-02-04 15:10:34 +000060 if ':' not in s: return '', s
61 colon = 0
62 for i in range(len(s)):
Fred Drakeb4e460a2000-09-28 16:25:20 +000063 if s[i] == ':': colon = i + 1
Guido van Rossum54f22ed2000-02-04 15:10:34 +000064 path, file = s[:colon-1], s[colon:]
65 if path and not ':' in path:
66 path = path + ':'
67 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000068
Guido van Rossuma48bf791996-07-23 02:28:32 +000069
70def splitext(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000071 """Split a path into root and extension.
72 The extension is everything starting at the last dot in the last
73 pathname component; the root is everything before that.
74 It is always true that root + ext == p."""
Guido van Rossuma48bf791996-07-23 02:28:32 +000075
Martin v. Löwisde333792002-12-12 20:30:20 +000076 i = p.rfind('.')
77 if i<=p.rfind(':'):
78 return p, ''
79 else:
80 return p[:i], p[i:]
Guido van Rossuma48bf791996-07-23 02:28:32 +000081
Guido van Rossum0ec31261995-08-10 18:09:16 +000082
83def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000084 """Split a pathname into a drive specification and the rest of the
85 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
86 empty (don't use the volume name -- it doesn't have the same
87 syntactic and semantic oddities as DOS drive letters, such as there
88 being a separate current directory per drive)."""
89
90 return '', p
Guido van Rossum0ec31261995-08-10 18:09:16 +000091
92
Guido van Rossumc629d341992-11-05 10:43:02 +000093# Short interfaces to split()
94
95def dirname(s): return split(s)[0]
96def basename(s): return split(s)[1]
97
Jack Jansen791f7d42003-01-15 22:45:48 +000098def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +000099 if not isabs(s):
100 return False
101 components = split(s)
102 return len(components) == 2 and components[1] == ''
Guido van Rossumc629d341992-11-05 10:43:02 +0000103
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000104def isdir(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000105 """Return true if the pathname refers to an existing directory."""
106
107 try:
108 st = os.stat(s)
109 except os.error:
110 return 0
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000111 return S_ISDIR(st.st_mode)
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000112
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000113
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000114# Get size, mtime, atime of files.
115
116def getsize(filename):
117 """Return the size of a file, reported by os.stat()."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000118 return os.stat(filename).st_size
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000119
120def getmtime(filename):
121 """Return the last modification time of a file, reported by os.stat()."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000122 return os.stat(filename).st_mtime
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000123
124def getatime(filename):
125 """Return the last access time of a file, reported by os.stat()."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000126 return os.stat(filename).st_atime
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000127
128
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000129def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000130 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000131
Jack Jansen992d58b2002-04-22 13:55:43 +0000132 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000133 import Carbon.File
134 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000135 except:
136 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000137
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000138
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000139def isfile(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000140 """Return true if the pathname refers to an existing regular file."""
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000141
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000142 try:
143 st = os.stat(s)
144 except os.error:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000145 return False
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000146 return S_ISREG(st.st_mode)
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000147
Martin v. Löwis96a60e42002-12-31 13:11:54 +0000148def getctime(filename):
149 """Return the creation time of a file, reported by os.stat()."""
150 return os.stat(filename).st_ctime
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000151
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000152def exists(s):
Johannes Gijsbersd2a1aa42004-08-30 13:39:50 +0000153 """Test whether a path exists. Returns False for broken symbolic links"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000154
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000155 try:
156 st = os.stat(s)
157 except os.error:
Tim Petersbc0e9102002-04-04 22:55:58 +0000158 return False
159 return True
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000160
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000161# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
162# case.
163
164def lexists(path):
165 """Test whether a path exists. Returns True for broken symbolic links"""
166
167 try:
168 st = os.lstat(path)
169 except os.error:
170 return False
171 return True
172
Jack Jansen03c06ee2000-08-23 09:13:40 +0000173# Return the longest prefix of all list elements.
174
175def commonprefix(m):
176 "Given a list of pathnames, returns the longest common leading component"
177 if not m: return ''
178 prefix = m[0]
179 for item in m:
180 for i in range(len(prefix)):
Fred Drake8152d322000-12-12 23:20:45 +0000181 if prefix[:i+1] != item[:i+1]:
Jack Jansen03c06ee2000-08-23 09:13:40 +0000182 prefix = prefix[:i]
183 if i == 0: return ''
184 break
185 return prefix
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000186
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000187def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000188 """Dummy to retain interface-compatibility with other operating systems."""
189 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000190
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000191
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000192def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000193 """Dummy to retain interface-compatibility with other operating systems."""
194 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000195
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000196class norm_error(Exception):
197 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000198
199def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000200 """Normalize a pathname. Will return the same result for
201 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000202
Jack Jansen2fc01092000-08-06 21:18:35 +0000203 if ":" not in s:
204 return ":"+s
205
Fred Drakeb4e460a2000-09-28 16:25:20 +0000206 comps = s.split(":")
Jack Jansen2fc01092000-08-06 21:18:35 +0000207 i = 1
208 while i < len(comps)-1:
209 if comps[i] == "" and comps[i-1] != "":
210 if i > 1:
211 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000212 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000213 else:
214 # best way to handle this is to raise an exception
Greg Ward034cbf12001-08-08 20:55:10 +0000215 raise norm_error, 'Cannot use :: immediately after volume name'
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000216 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000217 i = i + 1
218
Fred Drakeb4e460a2000-09-28 16:25:20 +0000219 s = ":".join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000220
221 # remove trailing ":" except for ":" and "Volume:"
222 if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
223 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000224 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000225
Jack Jansena68bfe21995-08-07 14:09:27 +0000226
227def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000228 """Directory tree walk with callback function.
229
230 For each directory in the directory tree rooted at top (including top
231 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
232 dirname is the name of the directory, and fnames a list of the names of
233 the files and subdirectories in dirname (excluding '.' and '..'). func
234 may modify the fnames list in-place (e.g. via del or slice assignment),
235 and walk will only recurse into the subdirectories whose names remain in
236 fnames; this can be used to implement a filter, or to impose a specific
237 order of visiting. No semantics are defined for, or required of, arg,
238 beyond that arg is always passed to func. It can be used, e.g., to pass
239 a filename pattern, or a mutable object designed to accumulate
240 statistics. Passing None for arg is common."""
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000241
242 try:
243 names = os.listdir(top)
244 except os.error:
245 return
246 func(arg, top, names)
247 for name in names:
248 name = join(top, name)
Jack Jansen992d58b2002-04-22 13:55:43 +0000249 if isdir(name) and not islink(name):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000250 walk(name, func, arg)
Guido van Rossume294cf61999-01-29 18:05:18 +0000251
252
Guido van Rossume294cf61999-01-29 18:05:18 +0000253def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000254 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000255 if not isabs(path):
256 path = join(os.getcwd(), path)
257 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000258
259# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000260def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000261 path = abspath(path)
262 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000263 import Carbon.File
Tim Peters8ac14952002-05-23 15:15:30 +0000264 except ImportError:
265 return path
266 if not path:
267 return path
268 components = path.split(':')
269 path = components[0] + ':'
270 for c in components[1:]:
271 path = join(path, c)
Jack Jansen98fc6832003-02-27 23:18:46 +0000272 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
Tim Peters8ac14952002-05-23 15:15:30 +0000273 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000274
275supports_unicode_filenames = False