blob: d389d70a97cca9c77a65d6ec2686712fccaabd2d [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 *
Thomas Wouters89f507f2006-12-13 04:49:30 +00005from genericpath import *
Guido van Rossum217a5fa1990-12-26 15:40:07 +00006
Skip Montanaro17ab1232001-01-24 06:27:27 +00007__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
8 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +00009 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
Mark Hammond8696ebc2002-10-08 02:44:31 +000010 "walk","expanduser","expandvars","normpath","abspath",
Skip Montanaro117910d2003-02-14 19:35:31 +000011 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000012 "devnull","realpath","supports_unicode_filenames"]
Guido van Rossumb5e05e91991-01-01 18:10:40 +000013
Skip Montanaro117910d2003-02-14 19:35:31 +000014# strings representing various path-related bits and pieces
15curdir = ':'
16pardir = '::'
17extsep = '.'
18sep = ':'
19pathsep = '\n'
20defpath = ':'
21altsep = None
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000022devnull = 'Dev:Null'
Skip Montanaro117910d2003-02-14 19:35:31 +000023
Fred Drakeb4e460a2000-09-28 16:25:20 +000024# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
Guido van Rossum599f2ed1992-01-14 18:28:18 +000025
Fred Drakeb4e460a2000-09-28 16:25:20 +000026def normcase(path):
27 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000028
29
Guido van Rossum217a5fa1990-12-26 15:40:07 +000030def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000031 """Return true if a path is absolute.
32 On the Mac, relative paths begin with a colon,
33 but as a special case, paths with no colons at all are also relative.
34 Anything else is absolute (the string up to the first colon is the
35 volume name)."""
36
Fred Drake8152d322000-12-12 23:20:45 +000037 return ':' in s and s[0] != ':'
Guido van Rossum217a5fa1990-12-26 15:40:07 +000038
Guido van Rossumb5e05e91991-01-01 18:10:40 +000039
Barry Warsaw384d2491997-02-18 21:53:25 +000040def join(s, *p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000041 path = s
42 for t in p:
43 if (not s) or isabs(t):
44 path = t
45 continue
46 if t[:1] == ':':
47 t = t[1:]
48 if ':' not in path:
49 path = ':' + path
Fred Drake8152d322000-12-12 23:20:45 +000050 if path[-1:] != ':':
Guido van Rossum54f22ed2000-02-04 15:10:34 +000051 path = path + ':'
52 path = path + t
53 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000054
Guido van Rossumb5e05e91991-01-01 18:10:40 +000055
Guido van Rossumb5e05e91991-01-01 18:10:40 +000056def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000057 """Split a pathname into two parts: the directory leading up to the final
58 bit, and the basename (the filename, without colons, in that directory).
59 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000060
Guido van Rossum54f22ed2000-02-04 15:10:34 +000061 if ':' not in s: return '', s
62 colon = 0
63 for i in range(len(s)):
Fred Drakeb4e460a2000-09-28 16:25:20 +000064 if s[i] == ':': colon = i + 1
Guido van Rossum54f22ed2000-02-04 15:10:34 +000065 path, file = s[:colon-1], s[colon:]
66 if path and not ':' in path:
67 path = path + ':'
68 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000069
Guido van Rossuma48bf791996-07-23 02:28:32 +000070
71def splitext(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000072 """Split a path into root and extension.
73 The extension is everything starting at the last dot in the last
74 pathname component; the root is everything before that.
75 It is always true that root + ext == p."""
Guido van Rossuma48bf791996-07-23 02:28:32 +000076
Martin v. Löwisde333792002-12-12 20:30:20 +000077 i = p.rfind('.')
78 if i<=p.rfind(':'):
79 return p, ''
80 else:
81 return p[:i], p[i:]
Guido van Rossuma48bf791996-07-23 02:28:32 +000082
Guido van Rossum0ec31261995-08-10 18:09:16 +000083
84def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000085 """Split a pathname into a drive specification and the rest of the
86 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
87 empty (don't use the volume name -- it doesn't have the same
88 syntactic and semantic oddities as DOS drive letters, such as there
89 being a separate current directory per drive)."""
90
91 return '', p
Guido van Rossum0ec31261995-08-10 18:09:16 +000092
93
Guido van Rossumc629d341992-11-05 10:43:02 +000094# Short interfaces to split()
95
96def dirname(s): return split(s)[0]
97def basename(s): return split(s)[1]
98
Jack Jansen791f7d42003-01-15 22:45:48 +000099def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +0000100 if not isabs(s):
101 return False
102 components = split(s)
103 return len(components) == 2 and components[1] == ''
Guido van Rossumc629d341992-11-05 10:43:02 +0000104
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000105def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000106 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000107
Jack Jansen992d58b2002-04-22 13:55:43 +0000108 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000109 import Carbon.File
110 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000111 except:
112 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000113
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000114# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
115# case.
116
117def lexists(path):
118 """Test whether a path exists. Returns True for broken symbolic links"""
119
120 try:
121 st = os.lstat(path)
122 except os.error:
123 return False
124 return True
125
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000126def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000127 """Dummy to retain interface-compatibility with other operating systems."""
128 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000129
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000130
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000131def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000132 """Dummy to retain interface-compatibility with other operating systems."""
133 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000134
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000135class norm_error(Exception):
136 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000137
138def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000139 """Normalize a pathname. Will return the same result for
140 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000141
Jack Jansen2fc01092000-08-06 21:18:35 +0000142 if ":" not in s:
143 return ":"+s
144
Fred Drakeb4e460a2000-09-28 16:25:20 +0000145 comps = s.split(":")
Jack Jansen2fc01092000-08-06 21:18:35 +0000146 i = 1
147 while i < len(comps)-1:
148 if comps[i] == "" and comps[i-1] != "":
149 if i > 1:
150 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000151 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000152 else:
153 # best way to handle this is to raise an exception
Greg Ward034cbf12001-08-08 20:55:10 +0000154 raise norm_error, 'Cannot use :: immediately after volume name'
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000155 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000156 i = i + 1
157
Fred Drakeb4e460a2000-09-28 16:25:20 +0000158 s = ":".join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000159
160 # remove trailing ":" except for ":" and "Volume:"
161 if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
162 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000163 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000164
Jack Jansena68bfe21995-08-07 14:09:27 +0000165
166def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000167 """Directory tree walk with callback function.
168
169 For each directory in the directory tree rooted at top (including top
170 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
171 dirname is the name of the directory, and fnames a list of the names of
172 the files and subdirectories in dirname (excluding '.' and '..'). func
173 may modify the fnames list in-place (e.g. via del or slice assignment),
174 and walk will only recurse into the subdirectories whose names remain in
175 fnames; this can be used to implement a filter, or to impose a specific
176 order of visiting. No semantics are defined for, or required of, arg,
177 beyond that arg is always passed to func. It can be used, e.g., to pass
178 a filename pattern, or a mutable object designed to accumulate
179 statistics. Passing None for arg is common."""
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000180
181 try:
182 names = os.listdir(top)
183 except os.error:
184 return
185 func(arg, top, names)
186 for name in names:
187 name = join(top, name)
Jack Jansen992d58b2002-04-22 13:55:43 +0000188 if isdir(name) and not islink(name):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000189 walk(name, func, arg)
Guido van Rossume294cf61999-01-29 18:05:18 +0000190
191
Guido van Rossume294cf61999-01-29 18:05:18 +0000192def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000193 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000194 if not isabs(path):
195 path = join(os.getcwd(), path)
196 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000197
198# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000199def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000200 path = abspath(path)
201 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000202 import Carbon.File
Tim Peters8ac14952002-05-23 15:15:30 +0000203 except ImportError:
204 return path
205 if not path:
206 return path
207 components = path.split(':')
208 path = components[0] + ':'
209 for c in components[1:]:
210 path = join(path, c)
Jack Jansen98fc6832003-02-27 23:18:46 +0000211 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
Tim Peters8ac14952002-05-23 15:15:30 +0000212 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000213
214supports_unicode_filenames = False