blob: aacf7235b011fd0e69626b69ff595de800d0b761 [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
Serhiy Storchaka34601982018-01-07 17:54:31 +02003# strings representing various path-related bits and pieces
4# These are primarily for export; internally, they are hardcoded.
5# Should be set before imports for resolving cyclic dependency.
6curdir = ':'
7pardir = '::'
8extsep = '.'
9sep = ':'
10pathsep = '\n'
11defpath = ':'
12altsep = None
13devnull = 'Dev:Null'
14
Guido van Rossum5c1d2291998-03-03 21:49:01 +000015import os
Guido van Rossum217a5fa1990-12-26 15:40:07 +000016from stat import *
Guido van Rossumd8faa362007-04-27 19:54:29 +000017import genericpath
Thomas Wouters89f507f2006-12-13 04:49:30 +000018from genericpath import *
Victor Stinner89a1c932017-05-15 11:01:21 +020019import warnings
20
21warnings.warn('the macpath module is deprecated in 3.7 and will be removed '
22 'in 3.8', DeprecationWarning, stacklevel=2)
Guido van Rossum217a5fa1990-12-26 15:40:07 +000023
Skip Montanaro17ab1232001-01-24 06:27:27 +000024__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
25 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +000026 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
Benjamin Petersond71ca412008-05-08 23:44:58 +000027 "expanduser","expandvars","normpath","abspath",
Skip Montanaro117910d2003-02-14 19:35:31 +000028 "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000029 "devnull","realpath","supports_unicode_filenames"]
Guido van Rossumb5e05e91991-01-01 18:10:40 +000030
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000031def _get_colon(path):
32 if isinstance(path, bytes):
33 return b':'
34 else:
35 return ':'
36
Fred Drakeb4e460a2000-09-28 16:25:20 +000037# Normalize the case of a pathname. Dummy in Posix, but <s>.lower() here.
Guido van Rossum599f2ed1992-01-14 18:28:18 +000038
Fred Drakeb4e460a2000-09-28 16:25:20 +000039def normcase(path):
Ezio Melotti5a3ef5b2010-06-25 10:56:11 +000040 if not isinstance(path, (bytes, str)):
41 raise TypeError("normcase() argument must be str or bytes, "
42 "not '{}'".format(path.__class__.__name__))
Fred Drakeb4e460a2000-09-28 16:25:20 +000043 return path.lower()
Guido van Rossum599f2ed1992-01-14 18:28:18 +000044
45
Guido van Rossum217a5fa1990-12-26 15:40:07 +000046def isabs(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000047 """Return true if a path is absolute.
48 On the Mac, relative paths begin with a colon,
49 but as a special case, paths with no colons at all are also relative.
50 Anything else is absolute (the string up to the first colon is the
51 volume name)."""
52
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000053 colon = _get_colon(s)
54 return colon in s and s[:1] != colon
Guido van Rossum217a5fa1990-12-26 15:40:07 +000055
Guido van Rossumb5e05e91991-01-01 18:10:40 +000056
Barry Warsaw384d2491997-02-18 21:53:25 +000057def join(s, *p):
Serhiy Storchaka3deeeb02014-10-04 14:58:43 +030058 try:
59 colon = _get_colon(s)
60 path = s
Serhiy Storchaka5bfc03f2015-05-19 11:00:07 +030061 if not p:
62 path[:0] + colon #23780: Ensure compatible data type even if p is null.
Serhiy Storchaka3deeeb02014-10-04 14:58:43 +030063 for t in p:
64 if (not path) or isabs(t):
65 path = t
66 continue
67 if t[:1] == colon:
68 t = t[1:]
69 if colon not in path:
70 path = colon + path
71 if path[-1:] != colon:
72 path = path + colon
73 path = path + t
74 return path
75 except (TypeError, AttributeError, BytesWarning):
76 genericpath._check_arg_types('join', s, *p)
77 raise
Guido van Rossum217a5fa1990-12-26 15:40:07 +000078
Guido van Rossumb5e05e91991-01-01 18:10:40 +000079
Guido van Rossumb5e05e91991-01-01 18:10:40 +000080def split(s):
Guido van Rossum54f22ed2000-02-04 15:10:34 +000081 """Split a pathname into two parts: the directory leading up to the final
82 bit, and the basename (the filename, without colons, in that directory).
83 The result (s, t) is such that join(s, t) yields the original argument."""
Guido van Rossumb5e05e91991-01-01 18:10:40 +000084
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000085 colon = _get_colon(s)
86 if colon not in s: return s[:0], s
87 col = 0
Guido van Rossum54f22ed2000-02-04 15:10:34 +000088 for i in range(len(s)):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000089 if s[i:i+1] == colon: col = i + 1
90 path, file = s[:col-1], s[col:]
91 if path and not colon in path:
92 path = path + colon
Guido van Rossum54f22ed2000-02-04 15:10:34 +000093 return path, file
Guido van Rossumb5e05e91991-01-01 18:10:40 +000094
Guido van Rossuma48bf791996-07-23 02:28:32 +000095
96def splitext(p):
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +000097 if isinstance(p, bytes):
98 return genericpath._splitext(p, b':', altsep, b'.')
99 else:
100 return genericpath._splitext(p, sep, altsep, extsep)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000101splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum0ec31261995-08-10 18:09:16 +0000102
103def splitdrive(p):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000104 """Split a pathname into a drive specification and the rest of the
105 path. Useful on DOS/Windows/NT; on the Mac, the drive is always
106 empty (don't use the volume name -- it doesn't have the same
107 syntactic and semantic oddities as DOS drive letters, such as there
108 being a separate current directory per drive)."""
109
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000110 return p[:0], p
Guido van Rossum0ec31261995-08-10 18:09:16 +0000111
112
Guido van Rossumc629d341992-11-05 10:43:02 +0000113# Short interfaces to split()
114
115def dirname(s): return split(s)[0]
116def basename(s): return split(s)[1]
117
Jack Jansen791f7d42003-01-15 22:45:48 +0000118def ismount(s):
Tim Peters2c60f7a2003-01-29 03:49:43 +0000119 if not isabs(s):
120 return False
121 components = split(s)
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000122 return len(components) == 2 and not components[1]
Guido van Rossumc629d341992-11-05 10:43:02 +0000123
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000124def islink(s):
Jack Jansen992d58b2002-04-22 13:55:43 +0000125 """Return true if the pathname refers to a symbolic link."""
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000126
Jack Jansen992d58b2002-04-22 13:55:43 +0000127 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000128 import Carbon.File
129 return Carbon.File.ResolveAliasFile(s, 0)[2]
Jack Jansen992d58b2002-04-22 13:55:43 +0000130 except:
131 return False
Guido van Rossum7e4b2de1995-01-27 02:41:45 +0000132
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000133# Is `stat`/`lstat` a meaningful difference on the Mac? This is safe in any
134# case.
135
136def lexists(path):
137 """Test whether a path exists. Returns True for broken symbolic links"""
138
139 try:
140 st = os.lstat(path)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +0200141 except OSError:
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000142 return False
143 return True
144
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000145def expandvars(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000146 """Dummy to retain interface-compatibility with other operating systems."""
147 return path
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000148
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000149
Jack Jansenf4e7d2a1995-12-15 13:23:37 +0000150def expanduser(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000151 """Dummy to retain interface-compatibility with other operating systems."""
152 return path
Guido van Rossum0ec31261995-08-10 18:09:16 +0000153
Neal Norwitz93cf79f2002-03-31 14:06:41 +0000154class norm_error(Exception):
155 """Path cannot be normalized"""
Guido van Rossumc629d341992-11-05 10:43:02 +0000156
157def normpath(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000158 """Normalize a pathname. Will return the same result for
159 equivalent paths."""
Jack Jansena68bfe21995-08-07 14:09:27 +0000160
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000161 colon = _get_colon(s)
Jack Jansen2fc01092000-08-06 21:18:35 +0000162
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000163 if colon not in s:
164 return colon + s
165
166 comps = s.split(colon)
Jack Jansen2fc01092000-08-06 21:18:35 +0000167 i = 1
168 while i < len(comps)-1:
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000169 if not comps[i] and comps[i-1]:
Jack Jansen2fc01092000-08-06 21:18:35 +0000170 if i > 1:
171 del comps[i-1:i+1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000172 i = i - 1
Jack Jansen2fc01092000-08-06 21:18:35 +0000173 else:
174 # best way to handle this is to raise an exception
Collin Winterce36ad82007-08-30 01:19:48 +0000175 raise norm_error('Cannot use :: immediately after volume name')
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000176 else:
Jack Jansen2fc01092000-08-06 21:18:35 +0000177 i = i + 1
178
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000179 s = colon.join(comps)
Jack Jansen2fc01092000-08-06 21:18:35 +0000180
181 # remove trailing ":" except for ":" and "Volume:"
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000182 if s[-1:] == colon and len(comps) > 2 and s != colon*len(s):
Jack Jansen2fc01092000-08-06 21:18:35 +0000183 s = s[:-1]
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000184 return s
Guido van Rossum0ec31261995-08-10 18:09:16 +0000185
Guido van Rossume294cf61999-01-29 18:05:18 +0000186def abspath(path):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000187 """Return an absolute path."""
Guido van Rossume294cf61999-01-29 18:05:18 +0000188 if not isabs(path):
Florent Xicluna19b02d42010-03-08 12:25:35 +0000189 if isinstance(path, bytes):
190 cwd = os.getcwdb()
191 else:
192 cwd = os.getcwd()
193 path = join(cwd, path)
Guido van Rossume294cf61999-01-29 18:05:18 +0000194 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000195
196# realpath is a no-op on systems without islink support
Jack Jansen992d58b2002-04-22 13:55:43 +0000197def realpath(path):
Tim Peters8ac14952002-05-23 15:15:30 +0000198 path = abspath(path)
199 try:
Jack Jansen98fc6832003-02-27 23:18:46 +0000200 import Carbon.File
Brett Cannoncd171c82013-07-04 17:43:24 -0400201 except ImportError:
Tim Peters8ac14952002-05-23 15:15:30 +0000202 return path
203 if not path:
204 return path
Amaury Forgeot d'Arcb186f342008-10-03 21:57:20 +0000205 colon = _get_colon(path)
206 components = path.split(colon)
207 path = components[0] + colon
Tim Peters8ac14952002-05-23 15:15:30 +0000208 for c in components[1:]:
209 path = join(path, c)
Florent Xicluna54467e02010-03-21 12:29:50 +0000210 try:
211 path = Carbon.File.FSResolveAliasFile(path, 1)[0].as_pathname()
212 except Carbon.File.Error:
213 pass
Tim Peters8ac14952002-05-23 15:15:30 +0000214 return path
Mark Hammond8696ebc2002-10-08 02:44:31 +0000215
Victor Stinnerccb706c2010-09-13 19:41:36 +0000216supports_unicode_filenames = True