blob: 695fac913289d77fe93aa9bb43b88e63fc776cd9 [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",
Neal Norwitz61cdac62003-01-03 18:01:57 +000011 "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
21
Fred Drakeb4e460a2000-09-28 16:25:20 +000022# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
Guido van Rossum599f2ed1992-01-14 18:28:18 +000023
Fred Drakeb4e460a2000-09-28 16:25:20 +000024def normcase(path):
25 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000026
27
Guido van Rossum217a5fa1990-12-26 15:40:07 +000028def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000029 """Return true if a path is absolute.
30 On the Mac, relative paths begin with a colon,
31 but as a special case, paths with no colons at all are also relative.
32 Anything else is absolute (the string up to the first colon is the
33 volume name)."""
34
Fred Drake8152d322000-12-12 23:20:45 +000035 return ':' in s and s[0] != ':'
Guido van Rossum217a5fa1990-12-26 15:40:07 +000036
Guido van Rossumb5e05e91991-01-01 18:10:40 +000037
Barry Warsaw384d2491997-02-18 21:53:25 +000038def join(s, *p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000039 path = s
40 for t in p:
41 if (not s) or isabs(t):
42 path = t
43 continue
44 if t[:1] == ':':
45 t = t[1:]
46 if ':' not in path:
47 path = ':' + path
Fred Drake8152d322000-12-12 23:20:45 +000048 if path[-1:] != ':':
Guido van Rossum54f22ed2000-02-04 15:10:34 +000049 path = path + ':'
50 path = path + t
51 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000052
Guido van Rossumb5e05e91991-01-01 18:10:40 +000053
Guido van Rossumb5e05e91991-01-01 18:10:40 +000054def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000055 """Split a pathname into two parts: the directory leading up to the final
56 bit, and the basename (the filename, without colons, in that directory).
57 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000058
Guido van Rossum54f22ed2000-02-04 15:10:34 +000059 if ':' not in s: return '', s
60 colon = 0
61 for i in range(len(s)):
Fred Drakeb4e460a2000-09-28 16:25:20 +000062 if s[i] == ':': colon = i + 1
Guido van Rossum54f22ed2000-02-04 15:10:34 +000063 path, file = s[:colon-1], s[colon:]
64 if path and not ':' in path:
65 path = path + ':'
66 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000067
Guido van Rossuma48bf791996-07-23 02:28:32 +000068
69def splitext(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000070 """Split a path into root and extension.
71 The extension is everything starting at the last dot in the last
72 pathname component; the root is everything before that.
73 It is always true that root + ext == p."""
Guido van Rossuma48bf791996-07-23 02:28:32 +000074
Martin v. Löwisde333792002-12-12 20:30:20 +000075 i = p.rfind('.')
76 if i<=p.rfind(':'):
77 return p, ''
78 else:
79 return p[:i], p[i:]
Guido van Rossuma48bf791996-07-23 02:28:32 +000080
Guido van Rossum0ec31261995-08-10 18:09:16 +000081
82def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000083 """Split a pathname into a drive specification and the rest of the
84 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
85 empty (don't use the volume name -- it doesn't have the same
86 syntactic and semantic oddities as DOS drive letters, such as there
87 being a separate current directory per drive)."""
88
89 return '', p
Guido van Rossum0ec31261995-08-10 18:09:16 +000090
91
Guido van Rossumc629d341992-11-05 10:43:02 +000092# Short interfaces to split()
93
94def dirname(s): return split(s)[0]
95def basename(s): return split(s)[1]
96
Jack Jansen791f7d42003-01-15 22:45:48 +000097def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +000098 if not isabs(s):
99 return False
100 components = split(s)
101 return len(components) == 2 and components[1] == ''
Guido van Rossumc629d341992-11-05 10:43:02 +0000102
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000103def isdir(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000104 """Return true if the pathname refers to an existing directory."""
105
106 try:
107 st = os.stat(s)
108 except os.error:
109 return 0
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000110 return S_ISDIR(st.st_mode)
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000111
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000112
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000113# Get size, mtime, atime of files.
114
115def getsize(filename):
116 """Return the size of a file, reported by os.stat()."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000117 return os.stat(filename).st_size
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000118
119def getmtime(filename):
120 """Return the last modification time of a file, reported by os.stat()."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000121 return os.stat(filename).st_mtime
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000122
123def getatime(filename):
124 """Return the last access time of a file, reported by os.stat()."""
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000125 return os.stat(filename).st_atime
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000126
127
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000128def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000129 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000130
Jack Jansen992d58b2002-04-22 13:55:43 +0000131 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000132 import Carbon.File
133 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000134 except:
135 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000136
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000137
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000138def isfile(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000139 """Return true if the pathname refers to an existing regular file."""
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000140
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000141 try:
142 st = os.stat(s)
143 except os.error:
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000144 return False
Raymond Hettinger32200ae2002-06-01 19:51:15 +0000145 return S_ISREG(st.st_mode)
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000146
Martin v. Löwis96a60e42002-12-31 13:11:54 +0000147def getctime(filename):
148 """Return the creation time of a file, reported by os.stat()."""
149 return os.stat(filename).st_ctime
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000150
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000151def exists(s):
Tim Petersbc0e9102002-04-04 22:55:58 +0000152 """Return True if the pathname refers to an existing file or directory."""
Guido van Rossumc629d341992-11-05 10:43:02 +0000153
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000154 try:
155 st = os.stat(s)
156 except os.error:
Tim Petersbc0e9102002-04-04 22:55:58 +0000157 return False
158 return True
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000159
Jack Jansen03c06ee2000-08-23 09:13:40 +0000160# Return the longest prefix of all list elements.
161
162def commonprefix(m):
163 "Given a list of pathnames, returns the longest common leading component"
164 if not m: return ''
165 prefix = m[0]
166 for item in m:
167 for i in range(len(prefix)):
Fred Drake8152d322000-12-12 23:20:45 +0000168 if prefix[:i+1] != item[:i+1]:
Jack Jansen03c06ee2000-08-23 09:13:40 +0000169 prefix = prefix[:i]
170 if i == 0: return ''
171 break
172 return prefix
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000173
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000174def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000175 """Dummy to retain interface-compatibility with other operating systems."""
176 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000177
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000178
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000179def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000180 """Dummy to retain interface-compatibility with other operating systems."""
181 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000182
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000183class norm_error(Exception):
184 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000185
186def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000187 """Normalize a pathname. Will return the same result for
188 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000189
Jack Jansen2fc01092000-08-06 21:18:35 +0000190 if ":" not in s:
191 return ":"+s
192
Fred Drakeb4e460a2000-09-28 16:25:20 +0000193 comps = s.split(":")
Jack Jansen2fc01092000-08-06 21:18:35 +0000194 i = 1
195 while i < len(comps)-1:
196 if comps[i] == "" and comps[i-1] != "":
197 if i > 1:
198 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000199 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000200 else:
201 # best way to handle this is to raise an exception
Greg Ward034cbf12001-08-08 20:55:10 +0000202 raise norm_error, 'Cannot use :: immediately after volume name'
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000203 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000204 i = i + 1
205
Fred Drakeb4e460a2000-09-28 16:25:20 +0000206 s = ":".join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000207
208 # remove trailing ":" except for ":" and "Volume:"
209 if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
210 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000211 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000212
Jack Jansena68bfe21995-08-07 14:09:27 +0000213
214def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000215 """Directory tree walk with callback function.
216
217 For each directory in the directory tree rooted at top (including top
218 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
219 dirname is the name of the directory, and fnames a list of the names of
220 the files and subdirectories in dirname (excluding '.' and '..'). func
221 may modify the fnames list in-place (e.g. via del or slice assignment),
222 and walk will only recurse into the subdirectories whose names remain in
223 fnames; this can be used to implement a filter, or to impose a specific
224 order of visiting. No semantics are defined for, or required of, arg,
225 beyond that arg is always passed to func. It can be used, e.g., to pass
226 a filename pattern, or a mutable object designed to accumulate
227 statistics. Passing None for arg is common."""
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000228
229 try:
230 names = os.listdir(top)
231 except os.error:
232 return
233 func(arg, top, names)
234 for name in names:
235 name = join(top, name)
Jack Jansen992d58b2002-04-22 13:55:43 +0000236 if isdir(name) and not islink(name):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000237 walk(name, func, arg)
Guido van Rossume294cf61999-01-29 18:05:18 +0000238
239
Guido van Rossume294cf61999-01-29 18:05:18 +0000240def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000241 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000242 if not isabs(path):
243 path = join(os.getcwd(), path)
244 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000245
246# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000247def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000248 path = abspath(path)
249 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000250 import Carbon.File
Tim Peters8ac14952002-05-23 15:15:30 +0000251 except ImportError:
252 return path
253 if not path:
254 return path
255 components = path.split(':')
256 path = components[0] + ':'
257 for c in components[1:]:
258 path = join(path, c)
Jack Jansen98fc6832003-02-27 23:18:46 +0000259 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
Tim Peters8ac14952002-05-23 15:15:30 +0000260 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000261
262supports_unicode_filenames = False