blob: 15f42f25e583a778714da39eaba53c02a2c8e733 [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 Rossum599f2ed1992-01-14 18:28:18 +00003import string
Guido van Rossum5c1d2291998-03-03 21:49:01 +00004import os
Guido van Rossum217a5fa1990-12-26 15:40:07 +00005from stat import *
6
Guido van Rossumb5e05e91991-01-01 18:10:40 +00007
Guido van Rossum599f2ed1992-01-14 18:28:18 +00008# Normalize the case of a pathname. Dummy in Posix, but string.lower here.
9
10normcase = string.lower
11
12
Guido van Rossum217a5fa1990-12-26 15:40:07 +000013def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000014 """Return true if a path is absolute.
15 On the Mac, relative paths begin with a colon,
16 but as a special case, paths with no colons at all are also relative.
17 Anything else is absolute (the string up to the first colon is the
18 volume name)."""
19
20 return ':' in s and s[0] <> ':'
Guido van Rossum217a5fa1990-12-26 15:40:07 +000021
Guido van Rossumb5e05e91991-01-01 18:10:40 +000022
Barry Warsaw384d2491997-02-18 21:53:25 +000023def join(s, *p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000024 path = s
25 for t in p:
26 if (not s) or isabs(t):
27 path = t
28 continue
29 if t[:1] == ':':
30 t = t[1:]
31 if ':' not in path:
32 path = ':' + path
33 if path[-1:] <> ':':
34 path = path + ':'
35 path = path + t
36 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000037
Guido van Rossumb5e05e91991-01-01 18:10:40 +000038
Guido van Rossumb5e05e91991-01-01 18:10:40 +000039def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000040 """Split a pathname into two parts: the directory leading up to the final
41 bit, and the basename (the filename, without colons, in that directory).
42 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000043
Guido van Rossum54f22ed2000-02-04 15:10:34 +000044 if ':' not in s: return '', s
45 colon = 0
46 for i in range(len(s)):
47 if s[i] == ':': colon = i+1
48 path, file = s[:colon-1], s[colon:]
49 if path and not ':' in path:
50 path = path + ':'
51 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000052
Guido van Rossuma48bf791996-07-23 02:28:32 +000053
54def splitext(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000055 """Split a path into root and extension.
56 The extension is everything starting at the last dot in the last
57 pathname component; the root is everything before that.
58 It is always true that root + ext == p."""
Guido van Rossuma48bf791996-07-23 02:28:32 +000059
Guido van Rossum54f22ed2000-02-04 15:10:34 +000060 root, ext = '', ''
61 for c in p:
62 if c == ':':
63 root, ext = root + ext + c, ''
64 elif c == '.':
65 if ext:
66 root, ext = root + ext, c
67 else:
68 ext = c
69 elif ext:
70 ext = ext + c
71 else:
72 root = root + c
73 return root, ext
Guido van Rossuma48bf791996-07-23 02:28:32 +000074
Guido van Rossum0ec31261995-08-10 18:09:16 +000075
76def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000077 """Split a pathname into a drive specification and the rest of the
78 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
79 empty (don't use the volume name -- it doesn't have the same
80 syntactic and semantic oddities as DOS drive letters, such as there
81 being a separate current directory per drive)."""
82
83 return '', p
Guido van Rossum0ec31261995-08-10 18:09:16 +000084
85
Guido van Rossumc629d341992-11-05 10:43:02 +000086# Short interfaces to split()
87
88def dirname(s): return split(s)[0]
89def basename(s): return split(s)[1]
90
91
Guido van Rossum217a5fa1990-12-26 15:40:07 +000092def isdir(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000093 """Return true if the pathname refers to an existing directory."""
94
95 try:
96 st = os.stat(s)
97 except os.error:
98 return 0
99 return S_ISDIR(st[ST_MODE])
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000100
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000101
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000102# Get size, mtime, atime of files.
103
104def getsize(filename):
105 """Return the size of a file, reported by os.stat()."""
106 st = os.stat(filename)
Fred Drake69f87c51999-07-23 15:04:05 +0000107 return st[ST_SIZE]
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000108
109def getmtime(filename):
110 """Return the last modification time of a file, reported by os.stat()."""
111 st = os.stat(filename)
Fred Drake69f87c51999-07-23 15:04:05 +0000112 return st[ST_MTIME]
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000113
114def getatime(filename):
115 """Return the last access time of a file, reported by os.stat()."""
116 st = os.stat(filename)
Guido van Rossum46d56512000-07-01 10:52:49 +0000117 return st[ST_ATIME]
Guido van Rossum2bc1f8f1998-07-24 20:49:26 +0000118
119
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000120def islink(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000121 """Return true if the pathname refers to a symbolic link.
122 Always false on the Mac, until we understand Aliases.)"""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000123
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000124 return 0
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000125
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000126
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000127def isfile(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000128 """Return true if the pathname refers to an existing regular file."""
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000129
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000130 try:
131 st = os.stat(s)
132 except os.error:
133 return 0
134 return S_ISREG(st[ST_MODE])
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000135
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000136
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000137def exists(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000138 """Return true if the pathname refers to an existing file or directory."""
Guido van Rossumc629d341992-11-05 10:43:02 +0000139
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000140 try:
141 st = os.stat(s)
142 except os.error:
143 return 0
144 return 1
145
Jack Jansen03c06ee2000-08-23 09:13:40 +0000146# Return the longest prefix of all list elements.
147
148def commonprefix(m):
149 "Given a list of pathnames, returns the longest common leading component"
150 if not m: return ''
151 prefix = m[0]
152 for item in m:
153 for i in range(len(prefix)):
154 if prefix[:i+1] <> item[:i+1]:
155 prefix = prefix[:i]
156 if i == 0: return ''
157 break
158 return prefix
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000159
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000160def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000161 """Dummy to retain interface-compatibility with other operating systems."""
162 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000163
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000164
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000165def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000166 """Dummy to retain interface-compatibility with other operating systems."""
167 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000168
169norm_error = 'macpath.norm_error: path cannot be normalized'
Guido van Rossumc629d341992-11-05 10:43:02 +0000170
171def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000172 """Normalize a pathname. Will return the same result for
173 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000174
Jack Jansen2fc01092000-08-06 21:18:35 +0000175 if ":" not in s:
176 return ":"+s
177
178 comps = string.splitfields(s, ":")
179 i = 1
180 while i < len(comps)-1:
181 if comps[i] == "" and comps[i-1] != "":
182 if i > 1:
183 del comps[i-1:i+1]
184 i = i-1
185 else:
186 # best way to handle this is to raise an exception
187 raise norm_error, 'Cannot use :: immedeately after volume name'
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000188 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000189 i = i + 1
190
191 s = string.join(comps, ":")
192
193 # remove trailing ":" except for ":" and "Volume:"
194 if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
195 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000196 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000197
Jack Jansena68bfe21995-08-07 14:09:27 +0000198
199def walk(top, func, arg):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000200 """Directory tree walk.
201 For each directory under top (including top itself),
202 func(arg, dirname, filenames) is called, where
203 dirname is the name of the directory and filenames is the list
204 of files (and subdirectories etc.) in the directory.
205 The func may modify the filenames list, to implement a filter,
206 or to impose a different order of visiting."""
207
208 try:
209 names = os.listdir(top)
210 except os.error:
211 return
212 func(arg, top, names)
213 for name in names:
214 name = join(top, name)
215 if isdir(name):
216 walk(name, func, arg)
Guido van Rossume294cf61999-01-29 18:05:18 +0000217
218
Guido van Rossume294cf61999-01-29 18:05:18 +0000219def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000220 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000221 if not isabs(path):
222 path = join(os.getcwd(), path)
223 return normpath(path)