# module 'macpath' -- pathname (or -related) operations for the Macintosh import string import os from stat import * # Normalize the case of a pathname. Dummy in Posix, but string.lower here. normcase = string.lower # Return true if a path is absolute. # On the Mac, relative paths begin with a colon, # but as a special case, paths with no colons at all are also relative. # Anything else is absolute (the string up to the first colon is the # volume name). def isabs(s): return ':' in s and s[0] <> ':' def join(s, *p): path = s for t in p: if (not s) or isabs(t): path = t continue if t[:1] == ':': t = t[1:] if ':' not in path: path = ':' + path if path[-1:] <> ':': path = path + ':' path = path + t return path # Split a pathname in two parts: the directory leading up to the final bit, # and the basename (the filename, without colons, in that directory). # The result (s, t) is such that join(s, t) yields the original argument. def split(s): if ':' not in s: return '', s colon = 0 for i in range(len(s)): if s[i] == ':': colon = i+1 path, file = s[:colon-1], s[colon:] if path and not ':' in path: path = path + ':' return path, file # Split a path in root and extension. # The extension is everything starting at the last dot in the last # pathname component; the root is everything before that. # It is always true that root + ext == p. def splitext(p): root, ext = '', '' for c in p: if c == ':': root, ext = root + ext + c, '' elif c == '.': if ext: root, ext = root + ext, c else: ext = c elif ext: ext = ext + c else: root = root + c return root, ext # Split a pathname into a drive specification and the rest of the # path. Useful on DOS/Windows/NT; on the Mac, the drive is always # empty (don't use the volume name -- it doesn't have the same # syntactic and semantic oddities as DOS drive letters, such as there # being a separate current directory per drive). def splitdrive(p): return '', p # Short interfaces to split() def dirname(s): return split(s)[0] def basename(s): return split(s)[1] # Return true if the pathname refers to an existing directory. def isdir(s): try: st = os.stat(s) except os.error: return 0 return S_ISDIR(st[ST_MODE]) # Get size, mtime, atime of files. def getsize(filename): """Return the size of a file, reported by os.stat().""" st = os.stat(filename) return st[stat.ST_SIZE] def getmtime(filename): """Return the last modification time of a file, reported by os.stat().""" st = os.stat(filename) return st[stat.ST_MTIME] def getatime(filename): """Return the last access time of a file, reported by os.stat().""" st = os.stat(filename) return st[stat.ST_MTIME] # Return true if the pathname refers to a symbolic link. # (Always false on the Mac, until we understand Aliases.) def islink(s): return 0 # Return true if the pathname refers to an existing regular file. def isfile(s): try: st = os.stat(s) except os.error: return 0 return S_ISREG(st[ST_MODE]) # Return true if the pathname refers to an existing file or directory. def exists(s): try: st = os.stat(s) except os.error: return 0 return 1 # # dummy expandvars to retain interface-compatability with other # operating systems. def expandvars(path): return path # # dummy expanduser to retain interface-compatability with other # operating systems. def expanduser(path): return path # Normalize a pathname: get rid of '::' sequences by backing up, # e.g., 'foo:bar::bletch' becomes 'foo:bletch'. # Raise the exception norm_error below if backing up is impossible, # e.g., for '::foo'. # XXX The Unix version doesn't raise an exception but simply # returns an unnormalized path. Should do so here too. norm_error = 'macpath.norm_error: path cannot be normalized' def normpath(s): import string if ':' not in s: return ':' + s f = string.splitfields(s, ':') pre = [] post = [] if not f[0]: pre = f[:1] f = f[1:] if not f[len(f)-1]: post = f[-1:] f = f[:-1] res = [] for seg in f: if seg: res.append(seg) else: if not res: raise norm_error, 'path starts with ::' del res[len(res)-1] if not (pre or res): raise norm_error, 'path starts with volume::' if pre: res = pre + res if post: res = res + post s = res[0] for seg in res[1:]: s = s + ':' + seg return s # Directory tree walk. # For each directory under top (including top itself), # func(arg, dirname, filenames) is called, where # dirname is the name of the directory and filenames is the list # of files (and subdirectories etc.) in the directory. # The func may modify the filenames list, to implement a filter, # or to impose a different order of visiting. def walk(top, func, arg): try: names = os.listdir(top) except os.error: return func(arg, top, names) for name in names: name = join(top, name) if isdir(name): walk(name, func, arg) # Return an absolute path. def abspath(path): if not isabs(path): path = join(os.getcwd(), path) return normpath(path)