blob: c02364624436ab84c7d8ca267ea5425043671408 [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 Rossum5c1d2291998-03-03 21:49:01 +00003import os
Guido van Rossum217a5fa1990-12-26 15:40:07 +00004from stat import *
Guido van Rossumd8faa362007-04-27 19:54:29 +00005import genericpath
Thomas Wouters89f507f2006-12-13 04:49:30 +00006from genericpath import *
Guido van Rossum217a5fa1990-12-26 15:40:07 +00007
Skip Montanaro17ab1232001-01-24 06:27:27 +00008__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
9 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +000010 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
Benjamin Petersond71ca412008-05-08 23:44:58 +000011 "expanduser","expandvars","normpath","abspath",
Skip Montanaro117910d2003-02-14 19:35:31 +000012 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000013 "devnull","realpath","supports_unicode_filenames"]
Guido van Rossumb5e05e91991-01-01 18:10:40 +000014
Skip Montanaro117910d2003-02-14 19:35:31 +000015# strings representing various path-related bits and pieces
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000016# These are primarily for export; internally, they are hardcoded.
Skip Montanaro117910d2003-02-14 19:35:31 +000017curdir = ':'
18pardir = '::'
19extsep = '.'
20sep = ':'
21pathsep = '\n'
22defpath = ':'
23altsep = None
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000024devnull = 'Dev:Null'
Skip Montanaro117910d2003-02-14 19:35:31 +000025
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000026def _get_colon(path):
27 if isinstance(path, bytes):
28 return b':'
29 else:
30 return ':'
31
Fred Drakeb4e460a2000-09-28 16:25:20 +000032# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
Guido van Rossum599f2ed1992-01-14 18:28:18 +000033
Fred Drakeb4e460a2000-09-28 16:25:20 +000034def normcase(path):
35 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000036
37
Guido van Rossum217a5fa1990-12-26 15:40:07 +000038def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000039 """Return true if a path is absolute.
40 On the Mac, relative paths begin with a colon,
41 but as a special case, paths with no colons at all are also relative.
42 Anything else is absolute (the string up to the first colon is the
43 volume name)."""
44
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000045 colon = _get_colon(s)
46 return colon in s and s[:1] != colon
Guido van Rossum217a5fa1990-12-26 15:40:07 +000047
Guido van Rossumb5e05e91991-01-01 18:10:40 +000048
Barry Warsaw384d2491997-02-18 21:53:25 +000049def join(s, *p):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000050 colon = _get_colon(s)
Guido van Rossum54f22ed2000-02-04 15:10:34 +000051 path = s
52 for t in p:
53 if (not s) or isabs(t):
54 path = t
55 continue
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000056 if t[:1] == colon:
Guido van Rossum54f22ed2000-02-04 15:10:34 +000057 t = t[1:]
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000058 if colon not in path:
59 path = colon + path
60 if path[-1:] != colon:
61 path = path + colon
Guido van Rossum54f22ed2000-02-04 15:10:34 +000062 path = path + t
63 return path
Guido van Rossum217a5fa1990-12-26 15:40:07 +000064
Guido van Rossumb5e05e91991-01-01 18:10:40 +000065
Guido van Rossumb5e05e91991-01-01 18:10:40 +000066def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000067 """Split a pathname into two parts: the directory leading up to the final
68 bit, and the basename (the filename, without colons, in that directory).
69 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000070
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000071 colon = _get_colon(s)
72 if colon not in s: return s[:0], s
73 col = 0
Guido van Rossum54f22ed2000-02-04 15:10:34 +000074 for i in range(len(s)):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000075 if s[i:i+1] == colon: col = i + 1
76 path, file = s[:col-1], s[col:]
77 if path and not colon in path:
78 path = path + colon
Guido van Rossum54f22ed2000-02-04 15:10:34 +000079 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000080
Guido van Rossuma48bf791996-07-23 02:28:32 +000081
82def splitext(p):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000083 if isinstance(p, bytes):
84 return genericpath._splitext(p, b':', altsep, b'.')
85 else:
86 return genericpath._splitext(p, sep, altsep, extsep)
Guido van Rossumd8faa362007-04-27 19:54:29 +000087splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum0ec31261995-08-10 18:09:16 +000088
89def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000090 """Split a pathname into a drive specification and the rest of the
91 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
92 empty (don't use the volume name -- it doesn't have the same
93 syntactic and semantic oddities as DOS drive letters, such as there
94 being a separate current directory per drive)."""
95
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000096 return p[:0], p
Guido van Rossum0ec31261995-08-10 18:09:16 +000097
98
Guido van Rossumc629d341992-11-05 10:43:02 +000099# Short interfaces to split()
100
101def dirname(s): return split(s)[0]
102def basename(s): return split(s)[1]
103
Jack Jansen791f7d42003-01-15 22:45:48 +0000104def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +0000105 if not isabs(s):
106 return False
107 components = split(s)
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000108 return len(components) == 2 and not components[1]
Guido van Rossumc629d341992-11-05 10:43:02 +0000109
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000110def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000111 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000112
Jack Jansen992d58b2002-04-22 13:55:43 +0000113 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000114 import Carbon.File
115 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000116 except:
117 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000118
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000119# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
120# case.
121
122def lexists(path):
123 """Test whether a path exists. Returns True for broken symbolic links"""
124
125 try:
126 st = os.lstat(path)
127 except os.error:
128 return False
129 return True
130
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000131def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000132 """Dummy to retain interface-compatibility with other operating systems."""
133 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000134
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000135
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000136def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000137 """Dummy to retain interface-compatibility with other operating systems."""
138 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000139
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000140class norm_error(Exception):
141 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000142
143def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000144 """Normalize a pathname. Will return the same result for
145 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000146
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000147 colon = _get_colon(s)
Jack Jansen2fc01092000-08-06 21:18:35 +0000148
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000149 if colon not in s:
150 return colon + s
151
152 comps = s.split(colon)
Jack Jansen2fc01092000-08-06 21:18:35 +0000153 i = 1
154 while i < len(comps)-1:
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000155 if not comps[i] and comps[i-1]:
Jack Jansen2fc01092000-08-06 21:18:35 +0000156 if i > 1:
157 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000158 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000159 else:
160 # best way to handle this is to raise an exception
Collin Winterce36ad82007-08-30 01:19:48 +0000161 raise norm_error('Cannot use :: immediately after volume name')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000162 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000163 i = i + 1
164
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000165 s = colon.join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000166
167 # remove trailing ":" except for ":" and "Volume:"
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000168 if s[-1:] == colon and len(comps) > 2 and s != colon*len(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000169 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000170 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000171
Guido van Rossume294cf61999-01-29 18:05:18 +0000172def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000173 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000174 if not isabs(path):
175 path = join(os.getcwd(), path)
176 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000177
178# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000179def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000180 path = abspath(path)
181 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000182 import Carbon.File
Tim Peters8ac14952002-05-23 15:15:30 +0000183 except ImportError:
184 return path
185 if not path:
186 return path
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000187 colon = _get_colon(path)
188 components = path.split(colon)
189 path = components[0] + colon
Tim Peters8ac14952002-05-23 15:15:30 +0000190 for c in components[1:]:
191 path = join(path, c)
Jack Jansen98fc6832003-02-27 23:18:46 +0000192 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
Tim Peters8ac14952002-05-23 15:15:30 +0000193 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000194
195supports_unicode_filenames = False