| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 1 | # module 'macpath' -- pathname (or -related) operations for the Macintosh | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 2 |  | 
| Guido van Rossum | 599f2ed | 1992-01-14 18:28:18 +0000 | [diff] [blame] | 3 | import string | 
| Guido van Rossum | 5c1d229 | 1998-03-03 21:49:01 +0000 | [diff] [blame] | 4 | import os | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 5 | from stat import * | 
 | 6 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 7 |  | 
| Guido van Rossum | 599f2ed | 1992-01-14 18:28:18 +0000 | [diff] [blame] | 8 | # Normalize the case of a pathname.  Dummy in Posix, but string.lower here. | 
 | 9 |  | 
 | 10 | normcase = string.lower | 
 | 11 |  | 
 | 12 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 13 | # 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 Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 19 | def isabs(s): | 
 | 20 | 	return ':' in s and s[0] <> ':' | 
 | 21 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 22 |  | 
| Barry Warsaw | 384d249 | 1997-02-18 21:53:25 +0000 | [diff] [blame] | 23 | def join(s, *p): | 
 | 24 | 	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 Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 37 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 38 |  | 
 | 39 | # Split a pathname in two parts: the directory leading up to the final bit, | 
 | 40 | # and the basename (the filename, without colons, in that directory). | 
| Guido van Rossum | fbe0a8e | 1991-08-16 13:27:45 +0000 | [diff] [blame] | 41 | # The result (s, t) is such that join(s, t) yields the original argument. | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 42 |  | 
 | 43 | def split(s): | 
 | 44 | 	if ':' not in s: return '', s | 
 | 45 | 	colon = 0 | 
 | 46 | 	for i in range(len(s)): | 
| Guido van Rossum | bdfcfcc | 1992-01-01 19:35:13 +0000 | [diff] [blame] | 47 | 		if s[i] == ':': colon = i+1 | 
| Guido van Rossum | d6a111e | 1997-05-21 14:59:17 +0000 | [diff] [blame] | 48 | 	path, file = s[:colon-1], s[colon:] | 
 | 49 | 	if path and not ':' in path: | 
 | 50 | 		path = path + ':' | 
 | 51 | 	return path, file | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 52 |  | 
 | 53 |  | 
| Guido van Rossum | a48bf79 | 1996-07-23 02:28:32 +0000 | [diff] [blame] | 54 | # Split a path in root and extension. | 
 | 55 | # The extension is everything starting at the last dot in the last | 
 | 56 | # pathname component; the root is everything before that. | 
 | 57 | # It is always true that root + ext == p. | 
 | 58 |  | 
 | 59 | def splitext(p): | 
 | 60 | 	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 | 
 | 74 |  | 
 | 75 |  | 
| Guido van Rossum | 0ec3126 | 1995-08-10 18:09:16 +0000 | [diff] [blame] | 76 | # Split a pathname into a drive specification and the rest of the | 
 | 77 | # path.  Useful on DOS/Windows/NT; on the Mac, the drive is always | 
 | 78 | # empty (don't use the volume name -- it doesn't have the same | 
 | 79 | # syntactic and semantic oddities as DOS drive letters, such as there | 
 | 80 | # being a separate current directory per drive). | 
 | 81 |  | 
 | 82 | def splitdrive(p): | 
 | 83 | 	return '', p | 
 | 84 |  | 
 | 85 |  | 
| Guido van Rossum | c629d34 | 1992-11-05 10:43:02 +0000 | [diff] [blame] | 86 | # Short interfaces to split() | 
 | 87 |  | 
 | 88 | def dirname(s): return split(s)[0] | 
 | 89 | def basename(s): return split(s)[1] | 
 | 90 |  | 
 | 91 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 92 | # Return true if the pathname refers to an existing directory. | 
 | 93 |  | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 94 | def isdir(s): | 
 | 95 | 	try: | 
| Guido van Rossum | 5c1d229 | 1998-03-03 21:49:01 +0000 | [diff] [blame] | 96 | 		st = os.stat(s) | 
 | 97 | 	except os.error: | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 98 | 		return 0 | 
 | 99 | 	return S_ISDIR(st[ST_MODE]) | 
 | 100 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 101 |  | 
| Guido van Rossum | 2bc1f8f | 1998-07-24 20:49:26 +0000 | [diff] [blame] | 102 | # Get size, mtime, atime of files. | 
 | 103 |  | 
 | 104 | def getsize(filename): | 
 | 105 |     """Return the size of a file, reported by os.stat().""" | 
 | 106 |     st = os.stat(filename) | 
| Fred Drake | 69f87c5 | 1999-07-23 15:04:05 +0000 | [diff] [blame] | 107 |     return st[ST_SIZE] | 
| Guido van Rossum | 2bc1f8f | 1998-07-24 20:49:26 +0000 | [diff] [blame] | 108 |  | 
 | 109 | def getmtime(filename): | 
 | 110 |     """Return the last modification time of a file, reported by os.stat().""" | 
 | 111 |     st = os.stat(filename) | 
| Fred Drake | 69f87c5 | 1999-07-23 15:04:05 +0000 | [diff] [blame] | 112 |     return st[ST_MTIME] | 
| Guido van Rossum | 2bc1f8f | 1998-07-24 20:49:26 +0000 | [diff] [blame] | 113 |  | 
 | 114 | def getatime(filename): | 
 | 115 |     """Return the last access time of a file, reported by os.stat().""" | 
 | 116 |     st = os.stat(filename) | 
| Fred Drake | 69f87c5 | 1999-07-23 15:04:05 +0000 | [diff] [blame] | 117 |     return st[ST_MTIME] | 
| Guido van Rossum | 2bc1f8f | 1998-07-24 20:49:26 +0000 | [diff] [blame] | 118 |  | 
 | 119 |  | 
| Guido van Rossum | 7e4b2de | 1995-01-27 02:41:45 +0000 | [diff] [blame] | 120 | # Return true if the pathname refers to a symbolic link. | 
 | 121 | # (Always false on the Mac, until we understand Aliases.) | 
 | 122 |  | 
 | 123 | def islink(s): | 
 | 124 | 	return 0 | 
 | 125 |  | 
 | 126 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 127 | # Return true if the pathname refers to an existing regular file. | 
 | 128 |  | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 129 | def isfile(s): | 
 | 130 | 	try: | 
| Guido van Rossum | 5c1d229 | 1998-03-03 21:49:01 +0000 | [diff] [blame] | 131 | 		st = os.stat(s) | 
 | 132 | 	except os.error: | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 133 | 		return 0 | 
 | 134 | 	return S_ISREG(st[ST_MODE]) | 
 | 135 |  | 
| Guido van Rossum | b5e05e9 | 1991-01-01 18:10:40 +0000 | [diff] [blame] | 136 |  | 
 | 137 | # Return true if the pathname refers to an existing file or directory. | 
 | 138 |  | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 139 | def exists(s): | 
 | 140 | 	try: | 
| Guido van Rossum | 5c1d229 | 1998-03-03 21:49:01 +0000 | [diff] [blame] | 141 | 		st = os.stat(s) | 
 | 142 | 	except os.error: | 
| Guido van Rossum | 217a5fa | 1990-12-26 15:40:07 +0000 | [diff] [blame] | 143 | 		return 0 | 
 | 144 | 	return 1 | 
| Guido van Rossum | c629d34 | 1992-11-05 10:43:02 +0000 | [diff] [blame] | 145 |  | 
| Jack Jansen | f4e7d2a | 1995-12-15 13:23:37 +0000 | [diff] [blame] | 146 | # | 
 | 147 | # dummy expandvars to retain interface-compatability with other | 
 | 148 | # operating systems. | 
 | 149 | def expandvars(path): | 
 | 150 | 	return path | 
 | 151 |  | 
 | 152 | # | 
 | 153 | # dummy expanduser to retain interface-compatability with other | 
 | 154 | # operating systems. | 
 | 155 | def expanduser(path): | 
 | 156 | 	return path | 
| Guido van Rossum | c629d34 | 1992-11-05 10:43:02 +0000 | [diff] [blame] | 157 |  | 
| Guido van Rossum | 0ec3126 | 1995-08-10 18:09:16 +0000 | [diff] [blame] | 158 | # Normalize a pathname: get rid of '::' sequences by backing up, | 
 | 159 | # e.g., 'foo:bar::bletch' becomes 'foo:bletch'. | 
 | 160 | # Raise the exception norm_error below if backing up is impossible, | 
 | 161 | # e.g., for '::foo'. | 
 | 162 | # XXX The Unix version doesn't raise an exception but simply | 
 | 163 | # returns an unnormalized path.  Should do so here too. | 
 | 164 |  | 
 | 165 | norm_error = 'macpath.norm_error: path cannot be normalized' | 
| Guido van Rossum | c629d34 | 1992-11-05 10:43:02 +0000 | [diff] [blame] | 166 |  | 
 | 167 | def normpath(s): | 
| Guido van Rossum | 0ec3126 | 1995-08-10 18:09:16 +0000 | [diff] [blame] | 168 | 	import string | 
 | 169 | 	if ':' not in s: | 
 | 170 | 		return ':' + s | 
 | 171 | 	f = string.splitfields(s, ':') | 
 | 172 | 	pre = [] | 
 | 173 | 	post = [] | 
 | 174 | 	if not f[0]: | 
 | 175 | 		pre = f[:1] | 
 | 176 | 		f = f[1:] | 
 | 177 | 	if not f[len(f)-1]: | 
 | 178 | 		post = f[-1:] | 
 | 179 | 		f = f[:-1] | 
 | 180 | 	res = [] | 
 | 181 | 	for seg in f: | 
 | 182 | 		if seg: | 
 | 183 | 			res.append(seg) | 
 | 184 | 		else: | 
 | 185 | 			if not res: raise norm_error, 'path starts with ::' | 
 | 186 | 			del res[len(res)-1] | 
 | 187 | 			if not (pre or res): | 
 | 188 | 				raise norm_error, 'path starts with volume::' | 
 | 189 | 	if pre: res = pre + res | 
 | 190 | 	if post: res = res + post | 
 | 191 | 	s = res[0] | 
 | 192 | 	for seg in res[1:]: | 
 | 193 | 		s = s + ':' + seg | 
| Guido van Rossum | c629d34 | 1992-11-05 10:43:02 +0000 | [diff] [blame] | 194 | 	return s | 
| Jack Jansen | a68bfe2 | 1995-08-07 14:09:27 +0000 | [diff] [blame] | 195 |  | 
| Guido van Rossum | 0ec3126 | 1995-08-10 18:09:16 +0000 | [diff] [blame] | 196 |  | 
| Jack Jansen | a68bfe2 | 1995-08-07 14:09:27 +0000 | [diff] [blame] | 197 | # Directory tree walk. | 
 | 198 | # For each directory under top (including top itself), | 
 | 199 | # func(arg, dirname, filenames) is called, where | 
 | 200 | # dirname is the name of the directory and filenames is the list | 
 | 201 | # of files (and subdirectories etc.) in the directory. | 
 | 202 | # The func may modify the filenames list, to implement a filter, | 
 | 203 | # or to impose a different order of visiting. | 
 | 204 |  | 
 | 205 | def walk(top, func, arg): | 
 | 206 | 	try: | 
| Guido van Rossum | 5c1d229 | 1998-03-03 21:49:01 +0000 | [diff] [blame] | 207 | 		names = os.listdir(top) | 
 | 208 | 	except os.error: | 
| Jack Jansen | a68bfe2 | 1995-08-07 14:09:27 +0000 | [diff] [blame] | 209 | 		return | 
 | 210 | 	func(arg, top, names) | 
 | 211 | 	for name in names: | 
 | 212 | 		name = join(top, name) | 
 | 213 | 		if isdir(name): | 
 | 214 | 			walk(name, func, arg) | 
| Guido van Rossum | e294cf6 | 1999-01-29 18:05:18 +0000 | [diff] [blame] | 215 |  | 
 | 216 |  | 
 | 217 | # Return an absolute path. | 
 | 218 | def abspath(path): | 
 | 219 |     if not isabs(path): | 
 | 220 |         path = join(os.getcwd(), path) | 
 | 221 |     return normpath(path) |