]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.10/PyMod-2.7.10/Lib/ntpath.py
AppPkg/.../Python-2.7.10: AppPkg.dsc, pyconfig.h, PyMod-2.7.10
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.10 / PyMod-2.7.10 / Lib / ntpath.py
CommitLineData
d11973f1
DM
1\r
2# Module 'ntpath' -- common operations on WinNT/Win95 and UEFI pathnames.\r
3#\r
4# Copyright (c) 2015, Daryl McDaniel. All rights reserved.<BR>\r
5# Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>\r
6# This program and the accompanying materials are licensed and made available under\r
7# the terms and conditions of the BSD License that accompanies this distribution.\r
8# The full text of the license may be found at\r
9# http://opensource.org/licenses/bsd-license.\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14\r
15"""Common pathname manipulations, WindowsNT/95 and UEFI version.\r
3ec97ca4
DM
16\r
17Instead of importing this module directly, import os and refer to this\r
18module as os.path.\r
19"""\r
20\r
21import os\r
22import sys\r
23import stat\r
24import genericpath\r
25import warnings\r
26\r
27from genericpath import *\r
28from genericpath import _unicode\r
29\r
30__all__ = ["normcase","isabs","join","splitdrive","split","splitext",\r
31 "basename","dirname","commonprefix","getsize","getmtime",\r
32 "getatime","getctime", "islink","exists","lexists","isdir","isfile",\r
33 "ismount","walk","expanduser","expandvars","normpath","abspath",\r
34 "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",\r
35 "extsep","devnull","realpath","supports_unicode_filenames","relpath"]\r
36\r
37# strings representing various path-related bits and pieces\r
38curdir = '.'\r
39pardir = '..'\r
40extsep = '.'\r
41sep = '\\'\r
42pathsep = ';'\r
43altsep = '/'\r
44defpath = '.;C:\\bin'\r
45if 'ce' in sys.builtin_module_names:\r
46 defpath = '\\Windows'\r
47elif 'os2' in sys.builtin_module_names:\r
48 # OS/2 w/ VACPP\r
49 altsep = '/'\r
50devnull = 'nul'\r
51\r
52# Normalize the case of a pathname and map slashes to backslashes.\r
53# Other normalizations (such as optimizing '../' away) are not done\r
54# (this is done by normpath).\r
55\r
56def normcase(s):\r
57 """Normalize case of pathname.\r
58\r
59 Makes all characters lowercase and all slashes into backslashes."""\r
60 return s.replace("/", "\\").lower()\r
61\r
62\r
63# Return whether a path is absolute.\r
64# Trivial in Posix, harder on the Mac or MS-DOS.\r
65# For DOS it is absolute if it starts with a slash or backslash (current\r
66# volume), or if a pathname after the volume letter and colon / UNC resource\r
67# starts with a slash or backslash.\r
68\r
69def isabs(s):\r
70 """Test whether a path is absolute"""\r
71 s = splitdrive(s)[1]\r
72 return s != '' and s[:1] in '/\\'\r
73\r
74\r
75# Join two (or more) paths.\r
76def join(path, *paths):\r
77 """Join two or more pathname components, inserting "\\" as needed."""\r
78 result_drive, result_path = splitdrive(path)\r
79 for p in paths:\r
80 p_drive, p_path = splitdrive(p)\r
81 if p_path and p_path[0] in '\\/':\r
82 # Second path is absolute\r
83 if p_drive or not result_drive:\r
84 result_drive = p_drive\r
85 result_path = p_path\r
86 continue\r
87 elif p_drive and p_drive != result_drive:\r
88 if p_drive.lower() != result_drive.lower():\r
89 # Different drives => ignore the first path entirely\r
90 result_drive = p_drive\r
91 result_path = p_path\r
92 continue\r
93 # Same drive in different case\r
94 result_drive = p_drive\r
95 # Second path is relative to the first\r
96 if result_path and result_path[-1] not in '\\/':\r
97 result_path = result_path + '\\'\r
98 result_path = result_path + p_path\r
99 ## add separator between UNC and non-absolute path\r
100 if (result_path and result_path[0] not in '\\/' and\r
101 result_drive and result_drive[-1:] != ':'):\r
102 return result_drive + sep + result_path\r
103 return result_drive + result_path\r
104\r
105\r
106# Split a path in a drive specification (a drive letter followed by a\r
107# colon) and the path specification.\r
108# It is always true that drivespec + pathspec == p\r
d11973f1
DM
109# NOTE: for UEFI (and even Windows) you can have multiple characters to the left\r
110# of the ':' for the device or drive spec. This is reflected in the modifications\r
111# to splitdrive() and splitunc().\r
3ec97ca4
DM
112def splitdrive(p):\r
113 """Split a pathname into drive/UNC sharepoint and relative path specifiers.\r
114 Returns a 2-tuple (drive_or_unc, path); either part may be empty.\r
115\r
116 If you assign\r
117 result = splitdrive(p)\r
118 It is always true that:\r
119 result[0] + result[1] == p\r
120\r
121 If the path contained a drive letter, drive_or_unc will contain everything\r
122 up to and including the colon. e.g. splitdrive("c:/dir") returns ("c:", "/dir")\r
123\r
124 If the path contained a UNC path, the drive_or_unc will contain the host name\r
125 and share up to but not including the fourth directory separator character.\r
126 e.g. splitdrive("//host/computer/dir") returns ("//host/computer", "/dir")\r
127\r
128 Paths cannot contain both a drive letter and a UNC path.\r
129\r
130 """\r
131 if len(p) > 1:\r
132 normp = p.replace(altsep, sep)\r
133 if (normp[0:2] == sep*2) and (normp[2:3] != sep):\r
134 # is a UNC path:\r
135 # vvvvvvvvvvvvvvvvvvvv drive letter or UNC path\r
136 # \\machine\mountpoint\directory\etc\...\r
137 # directory ^^^^^^^^^^^^^^^\r
138 index = normp.find(sep, 2)\r
139 if index == -1:\r
140 return '', p\r
141 index2 = normp.find(sep, index + 1)\r
142 # a UNC path can't have two slashes in a row\r
143 # (after the initial two)\r
144 if index2 == index + 1:\r
145 return '', p\r
146 if index2 == -1:\r
147 index2 = len(p)\r
148 return p[:index2], p[index2:]\r
d11973f1
DM
149 index = p.find(':')\r
150 if index != -1:\r
151 index = index + 1\r
152 return p[:index], p[index:]\r
3ec97ca4
DM
153 return '', p\r
154\r
155# Parse UNC paths\r
156def splitunc(p):\r
157 """Split a pathname into UNC mount point and relative path specifiers.\r
158\r
159 Return a 2-tuple (unc, rest); either part may be empty.\r
160 If unc is not empty, it has the form '//host/mount' (or similar\r
161 using backslashes). unc+rest is always the input path.\r
162 Paths containing drive letters never have an UNC part.\r
163 """\r
d11973f1
DM
164 if ':' in p:\r
165 return '', p # Drive letter or device name present\r
3ec97ca4
DM
166 firstTwo = p[0:2]\r
167 if firstTwo == '//' or firstTwo == '\\\\':\r
168 # is a UNC path:\r
169 # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter\r
170 # \\machine\mountpoint\directories...\r
171 # directory ^^^^^^^^^^^^^^^\r
172 normp = p.replace('\\', '/')\r
173 index = normp.find('/', 2)\r
174 if index <= 2:\r
175 return '', p\r
176 index2 = normp.find('/', index + 1)\r
177 # a UNC path can't have two slashes in a row\r
178 # (after the initial two)\r
179 if index2 == index + 1:\r
180 return '', p\r
181 if index2 == -1:\r
182 index2 = len(p)\r
183 return p[:index2], p[index2:]\r
184 return '', p\r
185\r
186\r
187# Split a path in head (everything up to the last '/') and tail (the\r
188# rest). After the trailing '/' is stripped, the invariant\r
189# join(head, tail) == p holds.\r
190# The resulting head won't end in '/' unless it is the root.\r
191\r
192def split(p):\r
193 """Split a pathname.\r
194\r
195 Return tuple (head, tail) where tail is everything after the final slash.\r
196 Either part may be empty."""\r
197\r
198 d, p = splitdrive(p)\r
199 # set i to index beyond p's last slash\r
200 i = len(p)\r
201 while i and p[i-1] not in '/\\':\r
202 i = i - 1\r
203 head, tail = p[:i], p[i:] # now tail has no slashes\r
204 # remove trailing slashes from head, unless it's all slashes\r
205 head2 = head\r
206 while head2 and head2[-1] in '/\\':\r
207 head2 = head2[:-1]\r
208 head = head2 or head\r
209 return d + head, tail\r
210\r
211\r
212# Split a path in root and extension.\r
213# The extension is everything starting at the last dot in the last\r
214# pathname component; the root is everything before that.\r
215# It is always true that root + ext == p.\r
216\r
217def splitext(p):\r
218 return genericpath._splitext(p, sep, altsep, extsep)\r
219splitext.__doc__ = genericpath._splitext.__doc__\r
220\r
221\r
222# Return the tail (basename) part of a path.\r
223\r
224def basename(p):\r
225 """Returns the final component of a pathname"""\r
226 return split(p)[1]\r
227\r
228\r
229# Return the head (dirname) part of a path.\r
230\r
231def dirname(p):\r
232 """Returns the directory component of a pathname"""\r
233 return split(p)[0]\r
234\r
235# Is a path a symbolic link?\r
236# This will always return false on systems where posix.lstat doesn't exist.\r
237\r
238def islink(path):\r
239 """Test for symbolic link.\r
240 On WindowsNT/95 and OS/2 always returns false\r
241 """\r
242 return False\r
243\r
244# alias exists to lexists\r
245lexists = exists\r
246\r
247# Is a path a mount point? Either a root (with or without drive letter)\r
248# or an UNC path with at most a / or \ after the mount point.\r
249\r
250def ismount(path):\r
251 """Test whether a path is a mount point (defined as root of drive)"""\r
252 unc, rest = splitunc(path)\r
253 if unc:\r
254 return rest in ("", "/", "\\")\r
255 p = splitdrive(path)[1]\r
256 return len(p) == 1 and p[0] in '/\\'\r
257\r
258\r
259# Directory tree walk.\r
260# For each directory under top (including top itself, but excluding\r
261# '.' and '..'), func(arg, dirname, filenames) is called, where\r
262# dirname is the name of the directory and filenames is the list\r
263# of files (and subdirectories etc.) in the directory.\r
264# The func may modify the filenames list, to implement a filter,\r
265# or to impose a different order of visiting.\r
266\r
267def walk(top, func, arg):\r
268 """Directory tree walk with callback function.\r
269\r
270 For each directory in the directory tree rooted at top (including top\r
271 itself, but excluding '.' and '..'), call func(arg, dirname, fnames).\r
272 dirname is the name of the directory, and fnames a list of the names of\r
273 the files and subdirectories in dirname (excluding '.' and '..'). func\r
274 may modify the fnames list in-place (e.g. via del or slice assignment),\r
275 and walk will only recurse into the subdirectories whose names remain in\r
276 fnames; this can be used to implement a filter, or to impose a specific\r
277 order of visiting. No semantics are defined for, or required of, arg,\r
278 beyond that arg is always passed to func. It can be used, e.g., to pass\r
279 a filename pattern, or a mutable object designed to accumulate\r
280 statistics. Passing None for arg is common."""\r
281 warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",\r
282 stacklevel=2)\r
283 try:\r
284 names = os.listdir(top)\r
285 except os.error:\r
286 return\r
287 func(arg, top, names)\r
288 for name in names:\r
289 name = join(top, name)\r
290 if isdir(name):\r
291 walk(name, func, arg)\r
292\r
293\r
294# Expand paths beginning with '~' or '~user'.\r
295# '~' means $HOME; '~user' means that user's home directory.\r
296# If the path doesn't begin with '~', or if the user or $HOME is unknown,\r
297# the path is returned unchanged (leaving error reporting to whatever\r
298# function is called with the expanded path as argument).\r
299# See also module 'glob' for expansion of *, ? and [...] in pathnames.\r
300# (A function should also be defined to do full *sh-style environment\r
301# variable expansion.)\r
302\r
303def expanduser(path):\r
304 """Expand ~ and ~user constructs.\r
305\r
306 If user or $HOME is unknown, do nothing."""\r
307 if path[:1] != '~':\r
308 return path\r
309 i, n = 1, len(path)\r
310 while i < n and path[i] not in '/\\':\r
311 i = i + 1\r
312\r
313 if 'HOME' in os.environ:\r
314 userhome = os.environ['HOME']\r
315 elif 'USERPROFILE' in os.environ:\r
316 userhome = os.environ['USERPROFILE']\r
317 elif not 'HOMEPATH' in os.environ:\r
318 return path\r
319 else:\r
320 try:\r
321 drive = os.environ['HOMEDRIVE']\r
322 except KeyError:\r
323 drive = ''\r
324 userhome = join(drive, os.environ['HOMEPATH'])\r
325\r
326 if i != 1: #~user\r
327 userhome = join(dirname(userhome), path[1:i])\r
328\r
329 return userhome + path[i:]\r
330\r
331\r
332# Expand paths containing shell variable substitutions.\r
333# The following rules apply:\r
334# - no expansion within single quotes\r
335# - '$$' is translated into '$'\r
336# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2%\r
337# - ${varname} is accepted.\r
338# - $varname is accepted.\r
339# - %varname% is accepted.\r
340# - varnames can be made out of letters, digits and the characters '_-'\r
341# (though is not verified in the ${varname} and %varname% cases)\r
342# XXX With COMMAND.COM you can use any characters in a variable name,\r
343# XXX except '^|<>='.\r
344\r
345def expandvars(path):\r
346 """Expand shell variables of the forms $var, ${var} and %var%.\r
347\r
348 Unknown variables are left unchanged."""\r
349 if '$' not in path and '%' not in path:\r
350 return path\r
351 import string\r
352 varchars = string.ascii_letters + string.digits + '_-'\r
353 if isinstance(path, _unicode):\r
354 encoding = sys.getfilesystemencoding()\r
355 def getenv(var):\r
356 return os.environ[var.encode(encoding)].decode(encoding)\r
357 else:\r
358 def getenv(var):\r
359 return os.environ[var]\r
360 res = ''\r
361 index = 0\r
362 pathlen = len(path)\r
363 while index < pathlen:\r
364 c = path[index]\r
365 if c == '\'': # no expansion within single quotes\r
366 path = path[index + 1:]\r
367 pathlen = len(path)\r
368 try:\r
369 index = path.index('\'')\r
370 res = res + '\'' + path[:index + 1]\r
371 except ValueError:\r
372 res = res + c + path\r
373 index = pathlen - 1\r
374 elif c == '%': # variable or '%'\r
375 if path[index + 1:index + 2] == '%':\r
376 res = res + c\r
377 index = index + 1\r
378 else:\r
379 path = path[index+1:]\r
380 pathlen = len(path)\r
381 try:\r
382 index = path.index('%')\r
383 except ValueError:\r
384 res = res + '%' + path\r
385 index = pathlen - 1\r
386 else:\r
387 var = path[:index]\r
388 try:\r
389 res = res + getenv(var)\r
390 except KeyError:\r
391 res = res + '%' + var + '%'\r
392 elif c == '$': # variable or '$$'\r
393 if path[index + 1:index + 2] == '$':\r
394 res = res + c\r
395 index = index + 1\r
396 elif path[index + 1:index + 2] == '{':\r
397 path = path[index+2:]\r
398 pathlen = len(path)\r
399 try:\r
400 index = path.index('}')\r
401 var = path[:index]\r
402 try:\r
403 res = res + getenv(var)\r
404 except KeyError:\r
405 res = res + '${' + var + '}'\r
406 except ValueError:\r
407 res = res + '${' + path\r
408 index = pathlen - 1\r
409 else:\r
410 var = ''\r
411 index = index + 1\r
412 c = path[index:index + 1]\r
413 while c != '' and c in varchars:\r
414 var = var + c\r
415 index = index + 1\r
416 c = path[index:index + 1]\r
417 try:\r
418 res = res + getenv(var)\r
419 except KeyError:\r
420 res = res + '$' + var\r
421 if c != '':\r
422 index = index - 1\r
423 else:\r
424 res = res + c\r
425 index = index + 1\r
426 return res\r
427\r
428\r
429# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.\r
430# Previously, this function also truncated pathnames to 8+3 format,\r
431# but as this module is called "ntpath", that's obviously wrong!\r
432\r
433def normpath(path):\r
434 """Normalize path, eliminating double slashes, etc."""\r
435 # Preserve unicode (if path is unicode)\r
436 backslash, dot = (u'\\', u'.') if isinstance(path, _unicode) else ('\\', '.')\r
437 if path.startswith(('\\\\.\\', '\\\\?\\')):\r
438 # in the case of paths with these prefixes:\r
439 # \\.\ -> device names\r
440 # \\?\ -> literal paths\r
441 # do not do any normalization, but return the path unchanged\r
442 return path\r
443 path = path.replace("/", "\\")\r
444 prefix, path = splitdrive(path)\r
445 # We need to be careful here. If the prefix is empty, and the path starts\r
446 # with a backslash, it could either be an absolute path on the current\r
447 # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It\r
448 # is therefore imperative NOT to collapse multiple backslashes blindly in\r
449 # that case.\r
450 # The code below preserves multiple backslashes when there is no drive\r
451 # letter. This means that the invalid filename \\\a\b is preserved\r
452 # unchanged, where a\\\b is normalised to a\b. It's not clear that there\r
453 # is any better behaviour for such edge cases.\r
454 if prefix == '':\r
455 # No drive letter - preserve initial backslashes\r
456 while path[:1] == "\\":\r
457 prefix = prefix + backslash\r
458 path = path[1:]\r
459 else:\r
460 # We have a drive letter - collapse initial backslashes\r
461 if path.startswith("\\"):\r
462 prefix = prefix + backslash\r
463 path = path.lstrip("\\")\r
464 comps = path.split("\\")\r
465 i = 0\r
466 while i < len(comps):\r
467 if comps[i] in ('.', ''):\r
468 del comps[i]\r
469 elif comps[i] == '..':\r
470 if i > 0 and comps[i-1] != '..':\r
471 del comps[i-1:i+1]\r
472 i -= 1\r
473 elif i == 0 and prefix.endswith("\\"):\r
474 del comps[i]\r
475 else:\r
476 i += 1\r
477 else:\r
478 i += 1\r
479 # If the path is now empty, substitute '.'\r
480 if not prefix and not comps:\r
481 comps.append(dot)\r
482 return prefix + backslash.join(comps)\r
483\r
484\r
485# Return an absolute path.\r
486try:\r
487 from nt import _getfullpathname\r
488\r
489except ImportError: # not running on Windows - mock up something sensible\r
490 def abspath(path):\r
491 """Return the absolute version of a path."""\r
492 if not isabs(path):\r
493 if isinstance(path, _unicode):\r
494 cwd = os.getcwdu()\r
495 else:\r
496 cwd = os.getcwd()\r
497 path = join(cwd, path)\r
498 return normpath(path)\r
499\r
500else: # use native Windows method on Windows\r
501 def abspath(path):\r
502 """Return the absolute version of a path."""\r
503\r
504 if path: # Empty path must return current working directory.\r
505 try:\r
506 path = _getfullpathname(path)\r
507 except WindowsError:\r
508 pass # Bad path - return unchanged.\r
509 elif isinstance(path, _unicode):\r
510 path = os.getcwdu()\r
511 else:\r
512 path = os.getcwd()\r
513 return normpath(path)\r
514\r
515# realpath is a no-op on systems without islink support\r
516realpath = abspath\r
517# Win9x family and earlier have no Unicode filename support.\r
518supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and\r
519 sys.getwindowsversion()[3] >= 2)\r
520\r
521def _abspath_split(path):\r
522 abs = abspath(normpath(path))\r
523 prefix, rest = splitunc(abs)\r
524 is_unc = bool(prefix)\r
525 if not is_unc:\r
526 prefix, rest = splitdrive(abs)\r
527 return is_unc, prefix, [x for x in rest.split(sep) if x]\r
528\r
529def relpath(path, start=curdir):\r
530 """Return a relative version of a path"""\r
531\r
532 if not path:\r
533 raise ValueError("no path specified")\r
534\r
535 start_is_unc, start_prefix, start_list = _abspath_split(start)\r
536 path_is_unc, path_prefix, path_list = _abspath_split(path)\r
537\r
538 if path_is_unc ^ start_is_unc:\r
539 raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"\r
540 % (path, start))\r
541 if path_prefix.lower() != start_prefix.lower():\r
542 if path_is_unc:\r
543 raise ValueError("path is on UNC root %s, start on UNC root %s"\r
544 % (path_prefix, start_prefix))\r
545 else:\r
546 raise ValueError("path is on drive %s, start on drive %s"\r
547 % (path_prefix, start_prefix))\r
548 # Work out how much of the filepath is shared by start and path.\r
549 i = 0\r
550 for e1, e2 in zip(start_list, path_list):\r
551 if e1.lower() != e2.lower():\r
552 break\r
553 i += 1\r
554\r
555 rel_list = [pardir] * (len(start_list)-i) + path_list[i:]\r
556 if not rel_list:\r
557 return curdir\r
558 return join(*rel_list)\r
559\r
560try:\r
561 # The genericpath.isdir implementation uses os.stat and checks the mode\r
562 # attribute to tell whether or not the path is a directory.\r
563 # This is overkill on Windows - just pass the path to GetFileAttributes\r
564 # and check the attribute from there.\r
565 from nt import _isdir as isdir\r
566except ImportError:\r
567 # Use genericpath.isdir as imported above.\r
568 pass\r