macpath.py 5.9 KB
Newer Older
1
"""Pathname and path-related operations for the Macintosh."""
Guido van Rossum's avatar
Guido van Rossum committed
2

3
import os
Guido van Rossum's avatar
Guido van Rossum committed
4 5
from stat import *

6 7 8 9
__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
           "basename","dirname","commonprefix","getsize","getmtime",
           "getatime","islink","exists","isdir","isfile",
           "walk","expanduser","expandvars","normpath","abspath"]
10

11
# Normalize the case of a pathname.  Dummy in Posix, but <s>.lower() here.
12

13 14
def normcase(path):
    return path.lower()
15 16


Guido van Rossum's avatar
Guido van Rossum committed
17
def isabs(s):
18 19 20 21 22 23
    """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)."""

24
    return ':' in s and s[0] != ':'
Guido van Rossum's avatar
Guido van Rossum committed
25

26

27
def join(s, *p):
28 29 30 31 32 33 34 35 36
    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
37
        if path[-1:] != ':':
38 39 40 41
            path = path + ':'
        path = path + t
    return path

42 43

def split(s):
44 45 46
    """Split a pathname into 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."""
47

48 49 50
    if ':' not in s: return '', s
    colon = 0
    for i in range(len(s)):
51
        if s[i] == ':': colon = i + 1
52 53 54 55
    path, file = s[:colon-1], s[colon:]
    if path and not ':' in path:
        path = path + ':'
    return path, file
56

Guido van Rossum's avatar
Guido van Rossum committed
57 58

def splitext(p):
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    """Split a path into 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."""

    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

79

80
def splitdrive(p):
81 82 83 84 85 86 87
    """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)."""

    return '', p
88 89


90
# Short interfaces to split()
Guido van Rossum's avatar
Guido van Rossum committed
91

92 93
def dirname(s): return split(s)[0]
def basename(s): return split(s)[1]
Guido van Rossum's avatar
Guido van Rossum committed
94

95

Guido van Rossum's avatar
Guido van Rossum committed
96
def isdir(s):
97 98 99 100 101 102 103
    """Return true if the pathname refers to an existing directory."""

    try:
        st = os.stat(s)
    except os.error:
        return 0
    return S_ISDIR(st[ST_MODE])
Guido van Rossum's avatar
Guido van Rossum committed
104

105

106 107 108 109 110
# Get size, mtime, atime of files.

def getsize(filename):
    """Return the size of a file, reported by os.stat()."""
    st = os.stat(filename)
111
    return st[ST_SIZE]
112 113 114 115

def getmtime(filename):
    """Return the last modification time of a file, reported by os.stat()."""
    st = os.stat(filename)
116
    return st[ST_MTIME]
117 118 119 120

def getatime(filename):
    """Return the last access time of a file, reported by os.stat()."""
    st = os.stat(filename)
121
    return st[ST_ATIME]
122 123


Guido van Rossum's avatar
Guido van Rossum committed
124
def islink(s):
125 126
    """Return true if the pathname refers to a symbolic link.
    Always false on the Mac, until we understand Aliases.)"""
Guido van Rossum's avatar
Guido van Rossum committed
127

128
    return 0
Guido van Rossum's avatar
Guido van Rossum committed
129

130

Guido van Rossum's avatar
Guido van Rossum committed
131
def isfile(s):
132
    """Return true if the pathname refers to an existing regular file."""
Guido van Rossum's avatar
Guido van Rossum committed
133

134 135 136 137 138
    try:
        st = os.stat(s)
    except os.error:
        return 0
    return S_ISREG(st[ST_MODE])
139 140


Guido van Rossum's avatar
Guido van Rossum committed
141
def exists(s):
142 143 144 145 146 147 148 149
    """Return true if the pathname refers to an existing file or directory."""

    try:
        st = os.stat(s)
    except os.error:
        return 0
    return 1

150 151 152 153 154 155 156 157
# Return the longest prefix of all list elements.

def commonprefix(m):
    "Given a list of pathnames, returns the longest common leading component"
    if not m: return ''
    prefix = m[0]
    for item in m:
        for i in range(len(prefix)):
158
            if prefix[:i+1] != item[:i+1]:
159 160 161 162
                prefix = prefix[:i]
                if i == 0: return ''
                break
    return prefix
163

164
def expandvars(path):
165 166
    """Dummy to retain interface-compatibility with other operating systems."""
    return path
167

168

169 170 171
def expanduser(path):
    """Dummy to retain interface-compatibility with other operating systems."""
    return path
172 173

norm_error = 'macpath.norm_error: path cannot be normalized'
174 175

def normpath(s):
176 177 178 179 180 181
    """Normalize a pathname.  Will return the same result for
    equivalent paths."""

    if ":" not in s:
        return ":"+s

182
    comps = s.split(":")
183 184 185 186 187
    i = 1
    while i < len(comps)-1:
        if comps[i] == "" and comps[i-1] != "":
            if i > 1:
                del comps[i-1:i+1]
188
                i = i - 1
189 190 191
            else:
                # best way to handle this is to raise an exception
                raise norm_error, 'Cannot use :: immedeately after volume name'
192
        else:
193 194
            i = i + 1

195
    s = ":".join(comps)
196 197 198 199

    # remove trailing ":" except for ":" and "Volume:"
    if s[-1] == ":" and len(comps) > 2 and s != ":"*len(s):
        s = s[:-1]
200 201
    return s

202 203

def walk(top, func, arg):
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
    """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."""

    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)


Guido van Rossum's avatar
Guido van Rossum committed
223
def abspath(path):
224
    """Return an absolute path."""
Guido van Rossum's avatar
Guido van Rossum committed
225 226 227
    if not isabs(path):
        path = join(os.getcwd(), path)
    return normpath(path)