blob: 2ea3358301f7df446279448ed8b4ae6758ef81c5 [file] [log] [blame]
Guido van Rossum15e22e11997-12-05 19:03:01 +00001# Module 'ntpath' -- common operations on WinNT/Win95 pathnames
Tim Peters2344fae2001-01-15 00:50:52 +00002"""Common pathname manipulations, WindowsNT/95 version.
Guido van Rossum534972b1999-02-03 17:20:50 +00003
4Instead of importing this module directly, import os and refer to this
5module as os.path.
Guido van Rossum15e22e11997-12-05 19:03:01 +00006"""
Guido van Rossum555915a1994-02-24 11:32:59 +00007
8import os
9import stat
Mark Hammond8696ebc2002-10-08 02:44:31 +000010import sys
Martin v. Löwis05c075d2007-03-07 11:04:33 +000011import genericpath
Jack Diederich7b604642006-08-26 18:42:06 +000012from genericpath import *
Skip Montanaro4d5d5bf2000-07-13 01:01:03 +000013
Skip Montanaro269b83b2001-02-06 01:07:02 +000014__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
15 "basename","dirname","commonprefix","getsize","getmtime",
Georg Brandlf0de6a12005-08-22 18:02:59 +000016 "getatime","getctime", "islink","exists","lexists","isdir","isfile",
17 "ismount","walk","expanduser","expandvars","normpath","abspath",
18 "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
19 "extsep","devnull","realpath","supports_unicode_filenames"]
Guido van Rossum555915a1994-02-24 11:32:59 +000020
Skip Montanaro117910d2003-02-14 19:35:31 +000021# strings representing various path-related bits and pieces
22curdir = '.'
23pardir = '..'
24extsep = '.'
25sep = '\\'
26pathsep = ';'
Skip Montanaro9ddac3e2003-03-28 22:23:24 +000027altsep = '/'
Andrew MacIntyre437966c2003-02-17 09:17:50 +000028defpath = '.;C:\\bin'
Skip Montanaro117910d2003-02-14 19:35:31 +000029if 'ce' in sys.builtin_module_names:
30 defpath = '\\Windows'
31elif 'os2' in sys.builtin_module_names:
Andrew MacIntyre437966c2003-02-17 09:17:50 +000032 # OS/2 w/ VACPP
Skip Montanaro117910d2003-02-14 19:35:31 +000033 altsep = '/'
Martin v. Löwisbdec50f2004-06-08 08:29:33 +000034devnull = 'nul'
Skip Montanaro117910d2003-02-14 19:35:31 +000035
Guido van Rossume2ad88c1997-08-12 14:46:58 +000036# Normalize the case of a pathname and map slashes to backslashes.
37# Other normalizations (such as optimizing '../' away) are not done
Guido van Rossum555915a1994-02-24 11:32:59 +000038# (this is done by normpath).
Guido van Rossume2ad88c1997-08-12 14:46:58 +000039
Guido van Rossum555915a1994-02-24 11:32:59 +000040def normcase(s):
Guido van Rossum16a0bc21998-02-18 13:48:31 +000041 """Normalize case of pathname.
42
Guido van Rossum534972b1999-02-03 17:20:50 +000043 Makes all characters lowercase and all slashes into backslashes."""
Fred Drakeb4e460a2000-09-28 16:25:20 +000044 return s.replace("/", "\\").lower()
Guido van Rossum555915a1994-02-24 11:32:59 +000045
Guido van Rossum77e1db31997-06-02 23:11:57 +000046
Fred Drakeef0b5dd2000-02-17 17:30:40 +000047# Return whether a path is absolute.
Guido van Rossum555915a1994-02-24 11:32:59 +000048# Trivial in Posix, harder on the Mac or MS-DOS.
49# For DOS it is absolute if it starts with a slash or backslash (current
Guido van Rossum534972b1999-02-03 17:20:50 +000050# volume), or if a pathname after the volume letter and colon / UNC resource
51# starts with a slash or backslash.
Guido van Rossum555915a1994-02-24 11:32:59 +000052
53def isabs(s):
Guido van Rossum15e22e11997-12-05 19:03:01 +000054 """Test whether a path is absolute"""
55 s = splitdrive(s)[1]
56 return s != '' and s[:1] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +000057
58
Guido van Rossum77e1db31997-06-02 23:11:57 +000059# Join two (or more) paths.
60
Barry Warsaw384d2491997-02-18 21:53:25 +000061def join(a, *p):
Guido van Rossum15e22e11997-12-05 19:03:01 +000062 """Join two or more pathname components, inserting "\\" as needed"""
63 path = a
64 for b in p:
Tim Peters33dc0a12001-07-27 08:09:54 +000065 b_wins = 0 # set to 1 iff b makes path irrelevant
66 if path == "":
67 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000068
Tim Peters33dc0a12001-07-27 08:09:54 +000069 elif isabs(b):
70 # This probably wipes out path so far. However, it's more
71 # complicated if path begins with a drive letter:
72 # 1. join('c:', '/a') == 'c:/a'
73 # 2. join('c:/', '/a') == 'c:/a'
74 # But
75 # 3. join('c:/a', '/b') == '/b'
76 # 4. join('c:', 'd:/') = 'd:/'
77 # 5. join('c:/', 'd:/') = 'd:/'
78 if path[1:2] != ":" or b[1:2] == ":":
79 # Path doesn't start with a drive letter, or cases 4 and 5.
80 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000081
Tim Peters33dc0a12001-07-27 08:09:54 +000082 # Else path has a drive letter, and b doesn't but is absolute.
83 elif len(path) > 3 or (len(path) == 3 and
84 path[-1] not in "/\\"):
85 # case 3
86 b_wins = 1
Tim Peters1bdd0f22001-07-19 17:18:18 +000087
Tim Peters33dc0a12001-07-27 08:09:54 +000088 if b_wins:
89 path = b
90 else:
91 # Join, and ensure there's a separator.
92 assert len(path) > 0
93 if path[-1] in "/\\":
94 if b and b[0] in "/\\":
95 path += b[1:]
96 else:
97 path += b
98 elif path[-1] == ":":
99 path += b
100 elif b:
101 if b[0] in "/\\":
102 path += b
103 else:
104 path += "\\" + b
Tim Peters6a3e5f12001-11-05 21:25:02 +0000105 else:
106 # path is not empty and does not end with a backslash,
107 # but b is empty; since, e.g., split('a/') produces
108 # ('a', ''), it's best if join() adds a backslash in
109 # this case.
110 path += '\\'
Tim Peters1bdd0f22001-07-19 17:18:18 +0000111
Guido van Rossum15e22e11997-12-05 19:03:01 +0000112 return path
Guido van Rossum555915a1994-02-24 11:32:59 +0000113
114
115# Split a path in a drive specification (a drive letter followed by a
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000116# colon) and the path specification.
Guido van Rossum555915a1994-02-24 11:32:59 +0000117# It is always true that drivespec + pathspec == p
118def splitdrive(p):
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000119 """Split a pathname into drive and path specifiers. Returns a 2-tuple
120"(drive,path)"; either part may be empty"""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000121 if p[1:2] == ':':
122 return p[0:2], p[2:]
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000123 return '', p
124
125
126# Parse UNC paths
127def splitunc(p):
128 """Split a pathname into UNC mount point and relative path specifiers.
129
130 Return a 2-tuple (unc, rest); either part may be empty.
131 If unc is not empty, it has the form '//host/mount' (or similar
132 using backslashes). unc+rest is always the input path.
133 Paths containing drive letters never have an UNC part.
134 """
135 if p[1:2] == ':':
136 return '', p # Drive letter present
Guido van Rossum534972b1999-02-03 17:20:50 +0000137 firstTwo = p[0:2]
138 if firstTwo == '//' or firstTwo == '\\\\':
139 # is a UNC path:
140 # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
141 # \\machine\mountpoint\directories...
142 # directory ^^^^^^^^^^^^^^^
143 normp = normcase(p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000144 index = normp.find('\\', 2)
Guido van Rossum534972b1999-02-03 17:20:50 +0000145 if index == -1:
146 ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
147 return ("", p)
Fred Drakeb4e460a2000-09-28 16:25:20 +0000148 index = normp.find('\\', index + 1)
Guido van Rossum534972b1999-02-03 17:20:50 +0000149 if index == -1:
150 index = len(p)
151 return p[:index], p[index:]
Guido van Rossum15e22e11997-12-05 19:03:01 +0000152 return '', p
Guido van Rossum555915a1994-02-24 11:32:59 +0000153
154
155# Split a path in head (everything up to the last '/') and tail (the
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000156# rest). After the trailing '/' is stripped, the invariant
Guido van Rossum555915a1994-02-24 11:32:59 +0000157# join(head, tail) == p holds.
158# The resulting head won't end in '/' unless it is the root.
159
160def split(p):
Guido van Rossum534972b1999-02-03 17:20:50 +0000161 """Split a pathname.
162
163 Return tuple (head, tail) where tail is everything after the final slash.
164 Either part may be empty."""
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000165
Guido van Rossum15e22e11997-12-05 19:03:01 +0000166 d, p = splitdrive(p)
Guido van Rossum8f0fa9e1999-03-19 21:05:12 +0000167 # set i to index beyond p's last slash
168 i = len(p)
169 while i and p[i-1] not in '/\\':
170 i = i - 1
171 head, tail = p[:i], p[i:] # now tail has no slashes
172 # remove trailing slashes from head, unless it's all slashes
173 head2 = head
174 while head2 and head2[-1] in '/\\':
175 head2 = head2[:-1]
176 head = head2 or head
Guido van Rossum15e22e11997-12-05 19:03:01 +0000177 return d + head, tail
Guido van Rossum555915a1994-02-24 11:32:59 +0000178
179
180# Split a path in root and extension.
Guido van Rossum73e122f1997-01-22 00:17:26 +0000181# The extension is everything starting at the last dot in the last
Guido van Rossum555915a1994-02-24 11:32:59 +0000182# pathname component; the root is everything before that.
183# It is always true that root + ext == p.
184
185def splitext(p):
Martin v. Löwis05c075d2007-03-07 11:04:33 +0000186 return genericpath._splitext(p, sep, altsep, extsep)
187splitext.__doc__ = genericpath._splitext.__doc__
Guido van Rossum555915a1994-02-24 11:32:59 +0000188
189
190# Return the tail (basename) part of a path.
191
192def basename(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000193 """Returns the final component of a pathname"""
194 return split(p)[1]
Guido van Rossum555915a1994-02-24 11:32:59 +0000195
196
197# Return the head (dirname) part of a path.
198
199def dirname(p):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000200 """Returns the directory component of a pathname"""
201 return split(p)[0]
Guido van Rossum555915a1994-02-24 11:32:59 +0000202
Guido van Rossum555915a1994-02-24 11:32:59 +0000203# Is a path a symbolic link?
204# This will always return false on systems where posix.lstat doesn't exist.
205
206def islink(path):
Jack Diederich7b604642006-08-26 18:42:06 +0000207 """Test for symbolic link.
208 On WindowsNT/95 and OS/2 always returns false
209 """
Guido van Rossum8ca162f2002-04-07 06:36:23 +0000210 return False
Guido van Rossum555915a1994-02-24 11:32:59 +0000211
Jack Diederich7b604642006-08-26 18:42:06 +0000212# alias exists to lexists
Johannes Gijsbersae882f72004-08-30 10:19:56 +0000213lexists = exists
214
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000215# Is a path a mount point? Either a root (with or without drive letter)
216# or an UNC path with at most a / or \ after the mount point.
Guido van Rossum555915a1994-02-24 11:32:59 +0000217
218def ismount(path):
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000219 """Test whether a path is a mount point (defined as root of drive)"""
Guido van Rossumf3c695c1999-04-06 19:32:19 +0000220 unc, rest = splitunc(path)
221 if unc:
222 return rest in ("", "/", "\\")
Guido van Rossumca99c2c1998-01-19 22:25:59 +0000223 p = splitdrive(path)[1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000224 return len(p) == 1 and p[0] in '/\\'
Guido van Rossum555915a1994-02-24 11:32:59 +0000225
226
227# Directory tree walk.
228# For each directory under top (including top itself, but excluding
229# '.' and '..'), func(arg, dirname, filenames) is called, where
230# dirname is the name of the directory and filenames is the list
Walter Dörwaldf0dfc7a2003-10-20 14:01:56 +0000231# of files (and subdirectories etc.) in the directory.
Guido van Rossum555915a1994-02-24 11:32:59 +0000232# The func may modify the filenames list, to implement a filter,
233# or to impose a different order of visiting.
234
235def walk(top, func, arg):
Tim Peterscf5e6a42001-10-10 04:16:20 +0000236 """Directory tree walk with callback function.
Guido van Rossum534972b1999-02-03 17:20:50 +0000237
Tim Peterscf5e6a42001-10-10 04:16:20 +0000238 For each directory in the directory tree rooted at top (including top
239 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
240 dirname is the name of the directory, and fnames a list of the names of
241 the files and subdirectories in dirname (excluding '.' and '..'). func
242 may modify the fnames list in-place (e.g. via del or slice assignment),
243 and walk will only recurse into the subdirectories whose names remain in
244 fnames; this can be used to implement a filter, or to impose a specific
245 order of visiting. No semantics are defined for, or required of, arg,
246 beyond that arg is always passed to func. It can be used, e.g., to pass
247 a filename pattern, or a mutable object designed to accumulate
248 statistics. Passing None for arg is common."""
249
Guido van Rossum15e22e11997-12-05 19:03:01 +0000250 try:
251 names = os.listdir(top)
252 except os.error:
253 return
254 func(arg, top, names)
255 exceptions = ('.', '..')
256 for name in names:
257 if name not in exceptions:
258 name = join(top, name)
259 if isdir(name):
260 walk(name, func, arg)
Guido van Rossum555915a1994-02-24 11:32:59 +0000261
262
263# Expand paths beginning with '~' or '~user'.
264# '~' means $HOME; '~user' means that user's home directory.
265# If the path doesn't begin with '~', or if the user or $HOME is unknown,
266# the path is returned unchanged (leaving error reporting to whatever
267# function is called with the expanded path as argument).
268# See also module 'glob' for expansion of *, ? and [...] in pathnames.
269# (A function should also be defined to do full *sh-style environment
270# variable expansion.)
271
272def expanduser(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000273 """Expand ~ and ~user constructs.
274
275 If user or $HOME is unknown, do nothing."""
Fred Drake8152d322000-12-12 23:20:45 +0000276 if path[:1] != '~':
Guido van Rossum15e22e11997-12-05 19:03:01 +0000277 return path
278 i, n = 1, len(path)
279 while i < n and path[i] not in '/\\':
Fred Drakeb4e460a2000-09-28 16:25:20 +0000280 i = i + 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000281 if i == 1:
Raymond Hettinger54f02222002-06-01 14:18:47 +0000282 if 'HOME' in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000283 userhome = os.environ['HOME']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000284 elif not 'HOMEPATH' in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000285 return path
286 else:
287 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000288 drive = os.environ['HOMEDRIVE']
Guido van Rossum15e22e11997-12-05 19:03:01 +0000289 except KeyError:
290 drive = ''
291 userhome = join(drive, os.environ['HOMEPATH'])
292 else:
293 return path
294 return userhome + path[i:]
Guido van Rossum555915a1994-02-24 11:32:59 +0000295
296
297# Expand paths containing shell variable substitutions.
298# The following rules apply:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000299# - no expansion within single quotes
300# - no escape character, except for '$$' which is translated into '$'
301# - ${varname} is accepted.
302# - varnames can be made out of letters, digits and the character '_'
Guido van Rossum555915a1994-02-24 11:32:59 +0000303# XXX With COMMAND.COM you can use any characters in a variable name,
304# XXX except '^|<>='.
305
Tim Peters2344fae2001-01-15 00:50:52 +0000306def expandvars(path):
Guido van Rossum534972b1999-02-03 17:20:50 +0000307 """Expand shell variables of form $var and ${var}.
308
309 Unknown variables are left unchanged."""
Guido van Rossum15e22e11997-12-05 19:03:01 +0000310 if '$' not in path:
311 return path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000312 import string
Fred Drake79e75e12001-07-20 19:05:50 +0000313 varchars = string.ascii_letters + string.digits + '_-'
Guido van Rossum15e22e11997-12-05 19:03:01 +0000314 res = ''
315 index = 0
316 pathlen = len(path)
317 while index < pathlen:
318 c = path[index]
319 if c == '\'': # no expansion within single quotes
320 path = path[index + 1:]
321 pathlen = len(path)
322 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000323 index = path.index('\'')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000324 res = res + '\'' + path[:index + 1]
Fred Drakeb4e460a2000-09-28 16:25:20 +0000325 except ValueError:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000326 res = res + path
Fred Drakeb4e460a2000-09-28 16:25:20 +0000327 index = pathlen - 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000328 elif c == '$': # variable or '$$'
329 if path[index + 1:index + 2] == '$':
330 res = res + c
331 index = index + 1
332 elif path[index + 1:index + 2] == '{':
333 path = path[index+2:]
334 pathlen = len(path)
335 try:
Fred Drakeb4e460a2000-09-28 16:25:20 +0000336 index = path.index('}')
Guido van Rossum15e22e11997-12-05 19:03:01 +0000337 var = path[:index]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000338 if var in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000339 res = res + os.environ[var]
Sjoerd Mullender33a0a062007-01-16 16:42:38 +0000340 else:
341 res = res + '${' + var + '}'
Fred Drakeb4e460a2000-09-28 16:25:20 +0000342 except ValueError:
Sjoerd Mullender33a0a062007-01-16 16:42:38 +0000343 res = res + '${' + path
Guido van Rossum15e22e11997-12-05 19:03:01 +0000344 index = pathlen - 1
345 else:
346 var = ''
347 index = index + 1
348 c = path[index:index + 1]
349 while c != '' and c in varchars:
350 var = var + c
351 index = index + 1
352 c = path[index:index + 1]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000353 if var in os.environ:
Guido van Rossum15e22e11997-12-05 19:03:01 +0000354 res = res + os.environ[var]
Sjoerd Mullender33a0a062007-01-16 16:42:38 +0000355 else:
356 res = res + '$' + var
Guido van Rossum15e22e11997-12-05 19:03:01 +0000357 if c != '':
Sjoerd Mullender33a0a062007-01-16 16:42:38 +0000358 index = index - 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000359 else:
360 res = res + c
361 index = index + 1
362 return res
Guido van Rossum555915a1994-02-24 11:32:59 +0000363
364
Tim Peters54a14a32001-08-30 22:05:26 +0000365# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.
Guido van Rossum3df7b5a1996-08-26 16:35:26 +0000366# Previously, this function also truncated pathnames to 8+3 format,
367# but as this module is called "ntpath", that's obviously wrong!
Guido van Rossum555915a1994-02-24 11:32:59 +0000368
369def normpath(path):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000370 """Normalize path, eliminating double slashes, etc."""
Fred Drakeb4e460a2000-09-28 16:25:20 +0000371 path = path.replace("/", "\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000372 prefix, path = splitdrive(path)
Brett Cannonbdc36272004-07-10 20:42:22 +0000373 # We need to be careful here. If the prefix is empty, and the path starts
374 # with a backslash, it could either be an absolute path on the current
375 # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It
376 # is therefore imperative NOT to collapse multiple backslashes blindly in
377 # that case.
378 # The code below preserves multiple backslashes when there is no drive
379 # letter. This means that the invalid filename \\\a\b is preserved
380 # unchanged, where a\\\b is normalised to a\b. It's not clear that there
381 # is any better behaviour for such edge cases.
382 if prefix == '':
383 # No drive letter - preserve initial backslashes
384 while path[:1] == "\\":
385 prefix = prefix + "\\"
386 path = path[1:]
387 else:
388 # We have a drive letter - collapse initial backslashes
389 if path.startswith("\\"):
390 prefix = prefix + "\\"
391 path = path.lstrip("\\")
Fred Drakeb4e460a2000-09-28 16:25:20 +0000392 comps = path.split("\\")
Guido van Rossum15e22e11997-12-05 19:03:01 +0000393 i = 0
394 while i < len(comps):
Tim Peters54a14a32001-08-30 22:05:26 +0000395 if comps[i] in ('.', ''):
Guido van Rossum15e22e11997-12-05 19:03:01 +0000396 del comps[i]
Tim Peters54a14a32001-08-30 22:05:26 +0000397 elif comps[i] == '..':
398 if i > 0 and comps[i-1] != '..':
399 del comps[i-1:i+1]
400 i -= 1
401 elif i == 0 and prefix.endswith("\\"):
402 del comps[i]
403 else:
404 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000405 else:
Tim Peters54a14a32001-08-30 22:05:26 +0000406 i += 1
Guido van Rossum15e22e11997-12-05 19:03:01 +0000407 # If the path is now empty, substitute '.'
408 if not prefix and not comps:
409 comps.append('.')
Fred Drakeb4e460a2000-09-28 16:25:20 +0000410 return prefix + "\\".join(comps)
Guido van Rossume294cf61999-01-29 18:05:18 +0000411
412
413# Return an absolute path.
Tim Peters21fbd572006-04-21 21:18:10 +0000414try:
415 from nt import _getfullpathname
Mark Hammondf717f052002-01-17 00:44:26 +0000416
Tim Peters21fbd572006-04-21 21:18:10 +0000417except ImportError: # not running on Windows - mock up something sensible
418 def abspath(path):
419 """Return the absolute version of a path."""
420 if not isabs(path):
421 path = join(os.getcwd(), path)
422 return normpath(path)
423
424else: # use native Windows method on Windows
425 def abspath(path):
426 """Return the absolute version of a path."""
427
428 if path: # Empty path must return current working directory.
429 try:
430 path = _getfullpathname(path)
431 except WindowsError:
432 pass # Bad path - return unchanged.
433 else:
434 path = os.getcwd()
435 return normpath(path)
Guido van Rossum83eeef42001-09-17 15:16:09 +0000436
437# realpath is a no-op on systems without islink support
438realpath = abspath
Mark Hammond8696ebc2002-10-08 02:44:31 +0000439# Win9x family and earlier have no Unicode filename support.
Tim Peters26bc25a2002-10-09 07:56:04 +0000440supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
441 sys.getwindowsversion()[3] >= 2)