blob: dbcf3684684e60a39ded28320c5c12d193a02178 [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):
Ezio Melotti5a3ef5b2010-06-25 10:56:11 +000035 if not isinstance(path, (bytes, str)):
36 raise TypeError("normcase() argument must be str or bytes, "
37 "not '{}'".format(path.__class__.__name__))
Fred Drakeb4e460a2000-09-28 16:25:20 +000038 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000039
40
Guido van Rossum217a5fa1990-12-26 15:40:07 +000041def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000042 """Return true if a path is absolute.
43 On the Mac, relative paths begin with a colon,
44 but as a special case, paths with no colons at all are also relative.
45 Anything else is absolute (the string up to the first colon is the
46 volume name)."""
47
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000048 colon = _get_colon(s)
49 return colon in s and s[:1] != colon
Guido van Rossum217a5fa1990-12-26 15:40:07 +000050
Guido van Rossumb5e05e91991-01-01 18:10:40 +000051
Barry Warsaw384d2491997-02-18 21:53:25 +000052def join(s, *p):
Serhiy Storchaka3deeeb02014-10-04 14:58:43 +030053 try:
54 colon = _get_colon(s)
55 path = s
56 for t in p:
57 if (not path) or isabs(t):
58 path = t
59 continue
60 if t[:1] == colon:
61 t = t[1:]
62 if colon not in path:
63 path = colon + path
64 if path[-1:] != colon:
65 path = path + colon
66 path = path + t
67 return path
68 except (TypeError, AttributeError, BytesWarning):
69 genericpath._check_arg_types('join', s, *p)
70 raise
Guido van Rossum217a5fa1990-12-26 15:40:07 +000071
Guido van Rossumb5e05e91991-01-01 18:10:40 +000072
Guido van Rossumb5e05e91991-01-01 18:10:40 +000073def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000074 """Split a pathname into two parts: the directory leading up to the final
75 bit, and the basename (the filename, without colons, in that directory).
76 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000077
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000078 colon = _get_colon(s)
79 if colon not in s: return s[:0], s
80 col = 0
Guido van Rossum54f22ed2000-02-04 15:10:34 +000081 for i in range(len(s)):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000082 if s[i:i+1] == colon: col = i + 1
83 path, file = s[:col-1], s[col:]
84 if path and not colon in path:
85 path = path + colon
Guido van Rossum54f22ed2000-02-04 15:10:34 +000086 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000087
Guido van Rossuma48bf791996-07-23 02:28:32 +000088
89def splitext(p):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000090 if isinstance(p, bytes):
91 return genericpath._splitext(p, b':', altsep, b'.')
92 else:
93 return genericpath._splitext(p, sep, altsep, extsep)
Guido van Rossumd8faa362007-04-27 19:54:29 +000094splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum0ec31261995-08-10 18:09:16 +000095
96def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000097 """Split a pathname into a drive specification and the rest of the
98 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
99 empty (don't use the volume name -- it doesn't have the same
100 syntactic and semantic oddities as DOS drive letters, such as there
101 being a separate current directory per drive)."""
102
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000103 return p[:0], p
Guido van Rossum0ec31261995-08-10 18:09:16 +0000104
105
Guido van Rossumc629d341992-11-05 10:43:02 +0000106# Short interfaces to split()
107
108def dirname(s): return split(s)[0]
109def basename(s): return split(s)[1]
110
Jack Jansen791f7d42003-01-15 22:45:48 +0000111def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +0000112 if not isabs(s):
113 return False
114 components = split(s)
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000115 return len(components) == 2 and not components[1]
Guido van Rossumc629d341992-11-05 10:43:02 +0000116
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000117def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000118 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000119
Jack Jansen992d58b2002-04-22 13:55:43 +0000120 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000121 import Carbon.File
122 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000123 except:
124 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000125
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000126# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
127# case.
128
129def lexists(path):
130 """Test whether a path exists. Returns True for broken symbolic links"""
131
132 try:
133 st = os.lstat(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200134 except OSError:
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000135 return False
136 return True
137
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000138def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000139 """Dummy to retain interface-compatibility with other operating systems."""
140 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000141
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000142
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000143def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000144 """Dummy to retain interface-compatibility with other operating systems."""
145 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000146
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000147class norm_error(Exception):
148 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000149
150def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000151 """Normalize a pathname. Will return the same result for
152 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000153
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000154 colon = _get_colon(s)
Jack Jansen2fc01092000-08-06 21:18:35 +0000155
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000156 if colon not in s:
157 return colon + s
158
159 comps = s.split(colon)
Jack Jansen2fc01092000-08-06 21:18:35 +0000160 i = 1
161 while i < len(comps)-1:
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000162 if not comps[i] and comps[i-1]:
Jack Jansen2fc01092000-08-06 21:18:35 +0000163 if i > 1:
164 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000165 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000166 else:
167 # best way to handle this is to raise an exception
Collin Winterce36ad82007-08-30 01:19:48 +0000168 raise norm_error('Cannot use :: immediately after volume name')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000169 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000170 i = i + 1
171
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000172 s = colon.join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000173
174 # remove trailing ":" except for ":" and "Volume:"
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000175 if s[-1:] == colon and len(comps) > 2 and s != colon*len(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000176 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000177 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000178
Guido van Rossume294cf61999-01-29 18:05:18 +0000179def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000180 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000181 if not isabs(path):
Florent Xicluna19b02d42010-03-08 12:25:35 +0000182 if isinstance(path, bytes):
183 cwd = os.getcwdb()
184 else:
185 cwd = os.getcwd()
186 path = join(cwd, path)
Guido van Rossume294cf61999-01-29 18:05:18 +0000187 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000188
189# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000190def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000191 path = abspath(path)
192 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000193 import Carbon.File
Brett Cannoncd171c82013-07-04 17:43:24 -0400194 except ImportError:
Tim Peters8ac14952002-05-23 15:15:30 +0000195 return path
196 if not path:
197 return path
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000198 colon = _get_colon(path)
199 components = path.split(colon)
200 path = components[0] + colon
Tim Peters8ac14952002-05-23 15:15:30 +0000201 for c in components[1:]:
202 path = join(path, c)
Florent Xicluna54467e02010-03-21 12:29:50 +0000203 try:
204 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
205 except Carbon.File.Error:
206 pass
Tim Peters8ac14952002-05-23 15:15:30 +0000207 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000208
Victor Stinnerccb706c2010-09-13 19:41:36 +0000209supports_unicode_filenames = True