blob: a6cf66b19ff3c78d8616c3600d866de29d8a2577 [file] [log] [blame]
Guido van Rossumb5e05e91991-01-01 18:10:40 +00001# module 'macpath' -- pathname (or -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 Rossum217a5fa1990-12-26 15:40:07 +00004import mac
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 Rossumb5e05e91991-01-01 18:10:40 +000013# Return true if a path is absolute.
14# On the Mac, relative paths begin with a colon,
15# but as a special case, paths with no colons at all are also relative.
16# Anything else is absolute (the string up to the first colon is the
17# volume name).
18
Guido van Rossum217a5fa1990-12-26 15:40:07 +000019def isabs(s):
20 return ':' in s and s[0] <> ':'
21
Guido van Rossumb5e05e91991-01-01 18:10:40 +000022
Barry Warsaw384d2491997-02-18 21:53:25 +000023# Join pathnames.
24# Ignore the previous parts if a part is absolute.
25# Insert a '/' unless the first part is empty or already ends in '/'.
Guido van Rossumb5e05e91991-01-01 18:10:40 +000026
Barry Warsaw384d2491997-02-18 21:53:25 +000027def join(s, *p):
28 path = s
29 for t in p:
30 if (not s) or isabs(t):
31 path = t
32 continue
33 if t[:1] == ':':
34 t = t[1:]
35 if ':' not in path:
36 path = ':' + path
37 if path[-1:] <> ':':
38 path = path + ':'
39 path = path + t
40 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000041
Guido van Rossumb5e05e91991-01-01 18:10:40 +000042
43# Split a pathname in two parts: the directory leading up to the final bit,
44# and the basename (the filename, without colons, in that directory).
Guido van Rossumfbe0a8e1991-08-16 13:27:45 +000045# The result (s, t) is such that join(s, t) yields the original argument.
Guido van Rossumb5e05e91991-01-01 18:10:40 +000046
47def split(s):
48 if ':' not in s: return '', s
49 colon = 0
50 for i in range(len(s)):
Guido van Rossumbdfcfcc1992-01-01 19:35:13 +000051 if s[i] == ':': colon = i+1
Guido van Rossum7aeb4b91994-08-23 13:32:20 +000052 return s[:colon-1], s[colon:]
Guido van Rossumb5e05e91991-01-01 18:10:40 +000053
54
Guido van Rossuma48bf791996-07-23 02:28:32 +000055# Split a path in 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.
59
60def splitext(p):
61 root, ext = '', ''
62 for c in p:
63 if c == ':':
64 root, ext = root + ext + c, ''
65 elif c == '.':
66 if ext:
67 root, ext = root + ext, c
68 else:
69 ext = c
70 elif ext:
71 ext = ext + c
72 else:
73 root = root + c
74 return root, ext
75
76
Guido van Rossum0ec31261995-08-10 18:09:16 +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
83def splitdrive(p):
84 return '', p
85
86
Guido van Rossumc629d341992-11-05 10:43:02 +000087# Short interfaces to split()
88
89def dirname(s): return split(s)[0]
90def basename(s): return split(s)[1]
91
92
Guido van Rossumb5e05e91991-01-01 18:10:40 +000093# Return true if the pathname refers to an existing directory.
94
Guido van Rossum217a5fa1990-12-26 15:40:07 +000095def isdir(s):
96 try:
97 st = mac.stat(s)
98 except mac.error:
99 return 0
100 return S_ISDIR(st[ST_MODE])
101
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000102
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000103# Return true if the pathname refers to a symbolic link.
104# (Always false on the Mac, until we understand Aliases.)
105
106def islink(s):
107 return 0
108
109
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000110# Return true if the pathname refers to an existing regular file.
111
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000112def isfile(s):
113 try:
114 st = mac.stat(s)
115 except mac.error:
116 return 0
117 return S_ISREG(st[ST_MODE])
118
Guido van Rossumb5e05e91991-01-01 18:10:40 +0000119
120# Return true if the pathname refers to an existing file or directory.
121
Guido van Rossum217a5fa1990-12-26 15:40:07 +0000122def exists(s):
123 try:
124 st = mac.stat(s)
125 except mac.error:
126 return 0
127 return 1
Guido van Rossumc629d341992-11-05 10:43:02 +0000128
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000129#
130# dummy expandvars to retain interface-compatability with other
131# operating systems.
132def expandvars(path):
133 return path
134
135#
136# dummy expanduser to retain interface-compatability with other
137# operating systems.
138def expanduser(path):
139 return path
Guido van Rossumc629d341992-11-05 10:43:02 +0000140
Guido van Rossum0ec31261995-08-10 18:09:16 +0000141# Normalize a pathname: get rid of '::' sequences by backing up,
142# e.g., 'foo:bar::bletch' becomes 'foo:bletch'.
143# Raise the exception norm_error below if backing up is impossible,
144# e.g., for '::foo'.
145# XXX The Unix version doesn't raise an exception but simply
146# returns an unnormalized path. Should do so here too.
147
148norm_error = 'macpath.norm_error: path cannot be normalized'
Guido van Rossumc629d341992-11-05 10:43:02 +0000149
150def normpath(s):
Guido van Rossum0ec31261995-08-10 18:09:16 +0000151 import string
152 if ':' not in s:
153 return ':' + s
154 f = string.splitfields(s, ':')
155 pre = []
156 post = []
157 if not f[0]:
158 pre = f[:1]
159 f = f[1:]
160 if not f[len(f)-1]:
161 post = f[-1:]
162 f = f[:-1]
163 res = []
164 for seg in f:
165 if seg:
166 res.append(seg)
167 else:
168 if not res: raise norm_error, 'path starts with ::'
169 del res[len(res)-1]
170 if not (pre or res):
171 raise norm_error, 'path starts with volume::'
172 if pre: res = pre + res
173 if post: res = res + post
174 s = res[0]
175 for seg in res[1:]:
176 s = s + ':' + seg
Guido van Rossumc629d341992-11-05 10:43:02 +0000177 return s
Jack Jansena68bfe21995-08-07 14:09:27 +0000178
Guido van Rossum0ec31261995-08-10 18:09:16 +0000179
Jack Jansena68bfe21995-08-07 14:09:27 +0000180# Directory tree walk.
181# For each directory under top (including top itself),
182# func(arg, dirname, filenames) is called, where
183# dirname is the name of the directory and filenames is the list
184# of files (and subdirectories etc.) in the directory.
185# The func may modify the filenames list, to implement a filter,
186# or to impose a different order of visiting.
187
188def walk(top, func, arg):
189 try:
190 names = mac.listdir(top)
191 except mac.error:
192 return
193 func(arg, top, names)
194 for name in names:
195 name = join(top, name)
196 if isdir(name):
197 walk(name, func, arg)