blob: 3e36f79dd8998e27e8febafa308a5ec24de0813f [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)
Fred Drake69f87c51999-07-23 15:04:05 +0000117 return st[ST_MTIME]
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
146
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000147def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000148 """Dummy to retain interface-compatibility with other operating systems."""
149 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000150
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000151
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000152def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000153 """Dummy to retain interface-compatibility with other operating systems."""
154 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000155
156norm_error = 'macpath.norm_error: path cannot be normalized'
Guido van Rossumc629d341992-11-05 10:43:02 +0000157
158def normpath(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000159 """Normalize a pathname: get rid of '::' sequences by backing up,
160 e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
161 Raise the exception norm_error below if backing up is impossible,
162 e.g., for '::foo'."""
163 # XXX The Unix version doesn't raise an exception but simply
164 # returns an unnormalized path. Should do so here too.
Jack Jansena68bfe21995-08-07 14:09:27 +0000165
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000166 import string
167 if ':' not in s:
168 return ':' + s
169 f = string.splitfields(s, ':')
170 pre = []
171 post = []
172 if not f[0]:
173 pre = f[:1]
174 f = f[1:]
175 if not f[len(f)-1]:
176 post = f[-1:]
177 f = f[:-1]
178 res = []
179 for seg in f:
180 if seg:
181 res.append(seg)
182 else:
183 if not res: raise norm_error, 'path starts with ::'
184 del res[len(res)-1]
185 if not (pre or res):
186 raise norm_error, 'path starts with volume::'
187 if pre: res = pre + res
188 if post: res = res + post
189 s = res[0]
190 for seg in res[1:]:
191 s = s + ':' + seg
192 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000193
Jack Jansena68bfe21995-08-07 14:09:27 +0000194
195def walk(top, func, arg):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000196 """Directory tree walk.
197 For each directory under top (including top itself),
198 func(arg, dirname, filenames) is called, where
199 dirname is the name of the directory and filenames is the list
200 of files (and subdirectories etc.) in the directory.
201 The func may modify the filenames list, to implement a filter,
202 or to impose a different order of visiting."""
203
204 try:
205 names = os.listdir(top)
206 except os.error:
207 return
208 func(arg, top, names)
209 for name in names:
210 name = join(top, name)
211 if isdir(name):
212 walk(name, func, arg)
Guido van Rossume294cf61999-01-29 18:05:18 +0000213
214
Guido van Rossume294cf61999-01-29 18:05:18 +0000215def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000216 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000217 if not isabs(path):
218 path = join(os.getcwd(), path)
219 return normpath(path)