blob: 1d3fa5644819a254e5196909861db008b09340f7 [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):
Tim Petersbc0e9102002-04-04 22:55:58 +0000153 """Return True if the pathname refers to an existing file or directory."""
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
Jack Jansen03c06ee2000-08-23 09:13:40 +0000161# Return the longest prefix of all list elements.
162
163def commonprefix(m):
164 "Given a list of pathnames, returns the longest common leading component"
165 if not m: return ''
166 prefix = m[0]
167 for item in m:
168 for i in range(len(prefix)):
Fred Drake8152d322000-12-12 23:20:45 +0000169 if prefix[:i+1] != item[:i+1]:
Jack Jansen03c06ee2000-08-23 09:13:40 +0000170 prefix = prefix[:i]
171 if i == 0: return ''
172 break
173 return prefix
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000174
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000175def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000176 """Dummy to retain interface-compatibility with other operating systems."""
177 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000178
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000179
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000180def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000181 """Dummy to retain interface-compatibility with other operating systems."""
182 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000183
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000184class norm_error(Exception):
185 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000186
187def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000188 """Normalize a pathname. Will return the same result for
189 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000190
Jack Jansen2fc01092000-08-06 21:18:35 +0000191 if ":" not in s:
192 return ":"+s
193
Fred Drakeb4e460a2000-09-28 16:25:20 +0000194 comps = s.split(":")
Jack Jansen2fc01092000-08-06 21:18:35 +0000195 i = 1
196 while i < len(comps)-1:
197 if comps[i] == "" and comps[i-1] != "":
198 if i > 1:
199 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000200 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000201 else:
202 # best way to handle this is to raise an exception
Greg Ward034cbf12001-08-08 20:55:10 +0000203 raise norm_error, 'Cannot use :: immediately after volume name'
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000204 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000205 i = i + 1
206
Fred Drakeb4e460a2000-09-28 16:25:20 +0000207 s = ":".join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000208
209 # remove trailing ":" except for ":" and "Volume:"
210 if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
211 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000212 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000213
Jack Jansena68bfe21995-08-07 14:09:27 +0000214
215def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000216 """Directory tree walk with callback function.
217
218 For each directory in the directory tree rooted at top (including top
219 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
220 dirname is the name of the directory, and fnames a list of the names of
221 the files and subdirectories in dirname (excluding '.' and '..'). func
222 may modify the fnames list in-place (e.g. via del or slice assignment),
223 and walk will only recurse into the subdirectories whose names remain in
224 fnames; this can be used to implement a filter, or to impose a specific
225 order of visiting. No semantics are defined for, or required of, arg,
226 beyond that arg is always passed to func. It can be used, e.g., to pass
227 a filename pattern, or a mutable object designed to accumulate
228 statistics. Passing None for arg is common."""
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000229
230 try:
231 names = os.listdir(top)
232 except os.error:
233 return
234 func(arg, top, names)
235 for name in names:
236 name = join(top, name)
Jack Jansen992d58b2002-04-22 13:55:43 +0000237 if isdir(name) and not islink(name):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000238 walk(name, func, arg)
Guido van Rossume294cf61999-01-29 18:05:18 +0000239
240
Guido van Rossume294cf61999-01-29 18:05:18 +0000241def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000242 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000243 if not isabs(path):
244 path = join(os.getcwd(), path)
245 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000246
247# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000248def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000249 path = abspath(path)
250 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000251 import Carbon.File
Tim Peters8ac14952002-05-23 15:15:30 +0000252 except ImportError:
253 return path
254 if not path:
255 return path
256 components = path.split(':')
257 path = components[0] + ':'
258 for c in components[1:]:
259 path = join(path, c)
Jack Jansen98fc6832003-02-27 23:18:46 +0000260 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
Tim Peters8ac14952002-05-23 15:15:30 +0000261 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000262
263supports_unicode_filenames = False