0001 # Module 'ntpath' -- common operations on WinNT/Win95 pathnames 0002 """Common pathname manipulations, WindowsNT/95 version. 0003 0004 Instead of importing this module directly, import os and refer to this 0005 module as os.path. 0006 """ 0007 0008 import os 0009 import stat 0010 import sys 0011 0012 __all__ = ["normcase","isabs","join","splitdrive","split","splitext", 0013 "basename","dirname","commonprefix","getsize","getmtime", 0014 "getatime","getctime", "islink","exists","isdir","isfile","ismount", 0015 "walk","expanduser","expandvars","normpath","abspath","splitunc", 0016 "curdir","pardir","sep","pathsep","defpath","altsep","extsep", 0017 "devnull","realpath","supports_unicode_filenames"] 0018 0019 # strings representing various path-related bits and pieces 0020 curdir = '.' 0021 pardir = '..' 0022 extsep = '.' 0023 sep = '\\' 0024 pathsep = ';' 0025 altsep = '/' 0026 defpath = '.;C:\\bin' 0027 if 'ce' in sys.builtin_module_names: 0028 defpath = '\\Windows' 0029 elif 'os2' in sys.builtin_module_names: 0030 # OS/2 w/ VACPP 0031 altsep = '/' 0032 devnull = 'nul' 0033 0034 # Normalize the case of a pathname and map slashes to backslashes. 0035 # Other normalizations (such as optimizing '../' away) are not done 0036 # (this is done by normpath). 0037 0038 def normcase(s): 0039 """Normalize case of pathname. 0040 0041 Makes all characters lowercase and all slashes into backslashes.""" 0042 return s.replace("/", "\\").lower() 0043 0044 0045 # Return whether a path is absolute. 0046 # Trivial in Posix, harder on the Mac or MS-DOS. 0047 # For DOS it is absolute if it starts with a slash or backslash (current 0048 # volume), or if a pathname after the volume letter and colon / UNC resource 0049 # starts with a slash or backslash. 0050 0051 def isabs(s): 0052 """Test whether a path is absolute""" 0053 s = splitdrive(s)[1] 0054 return s != '' and s[:1] in '/\\' 0055 0056 0057 # Join two (or more) paths. 0058 0059 def join(a, *p): 0060 """Join two or more pathname components, inserting "\\" as needed""" 0061 path = a 0062 for b in p: 0063 b_wins = 0 # set to 1 iff b makes path irrelevant 0064 if path == "": 0065 b_wins = 1 0066 0067 elif isabs(b): 0068 # This probably wipes out path so far. However, it's more 0069 # complicated if path begins with a drive letter: 0070 # 1. join('c:', '/a') == 'c:/a' 0071 # 2. join('c:/', '/a') == 'c:/a' 0072 # But 0073 # 3. join('c:/a', '/b') == '/b' 0074 # 4. join('c:', 'd:/') = 'd:/' 0075 # 5. join('c:/', 'd:/') = 'd:/' 0076 if path[1:2] != ":" or b[1:2] == ":": 0077 # Path doesn't start with a drive letter, or cases 4 and 5. 0078 b_wins = 1 0079 0080 # Else path has a drive letter, and b doesn't but is absolute. 0081 elif len(path) > 3 or (len(path) == 3 and 0082 path[-1] not in "/\\"): 0083 # case 3 0084 b_wins = 1 0085 0086 if b_wins: 0087 path = b 0088 else: 0089 # Join, and ensure there's a separator. 0090 assert len(path) > 0 0091 if path[-1] in "/\\": 0092 if b and b[0] in "/\\": 0093 path += b[1:] 0094 else: 0095 path += b 0096 elif path[-1] == ":": 0097 path += b 0098 elif b: 0099 if b[0] in "/\\": 0100 path += b 0101 else: 0102 path += "\\" + b 0103 else: 0104 # path is not empty and does not end with a backslash, 0105 # but b is empty; since, e.g., split('a/') produces 0106 # ('a', ''), it's best if join() adds a backslash in 0107 # this case. 0108 path += '\\' 0109 0110 return path 0111 0112 0113 # Split a path in a drive specification (a drive letter followed by a 0114 # colon) and the path specification. 0115 # It is always true that drivespec + pathspec == p 0116 def splitdrive(p): 0117 """Split a pathname into drive and path specifiers. Returns a 2-tuple 0118 "(drive,path)"; either part may be empty""" 0119 if p[1:2] == ':': 0120 return p[0:2], p[2:] 0121 return '', p 0122 0123 0124 # Parse UNC paths 0125 def splitunc(p): 0126 """Split a pathname into UNC mount point and relative path specifiers. 0127 0128 Return a 2-tuple (unc, rest); either part may be empty. 0129 If unc is not empty, it has the form '//host/mount' (or similar 0130 using backslashes). unc+rest is always the input path. 0131 Paths containing drive letters never have an UNC part. 0132 """ 0133 if p[1:2] == ':': 0134 return '', p # Drive letter present 0135 firstTwo = p[0:2] 0136 if firstTwo == '//' or firstTwo == '\\\\': 0137 # is a UNC path: 0138 # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter 0139 # \\machine\mountpoint\directories... 0140 # directory ^^^^^^^^^^^^^^^ 0141 normp = normcase(p) 0142 index = normp.find('\\', 2) 0143 if index == -1: 0144 ##raise RuntimeError, 'illegal UNC path: "' + p + '"' 0145 return ("", p) 0146 index = normp.find('\\', index + 1) 0147 if index == -1: 0148 index = len(p) 0149 return p[:index], p[index:] 0150 return '', p 0151 0152 0153 # Split a path in head (everything up to the last '/') and tail (the 0154 # rest). After the trailing '/' is stripped, the invariant 0155 # join(head, tail) == p holds. 0156 # The resulting head won't end in '/' unless it is the root. 0157 0158 def split(p): 0159 """Split a pathname. 0160 0161 Return tuple (head, tail) where tail is everything after the final slash. 0162 Either part may be empty.""" 0163 0164 d, p = splitdrive(p) 0165 # set i to index beyond p's last slash 0166 i = len(p) 0167 while i and p[i-1] not in '/\\': 0168 i = i - 1 0169 head, tail = p[:i], p[i:] # now tail has no slashes 0170 # remove trailing slashes from head, unless it's all slashes 0171 head2 = head 0172 while head2 and head2[-1] in '/\\': 0173 head2 = head2[:-1] 0174 head = head2 or head 0175 return d + head, tail 0176 0177 0178 # Split a path in root and extension. 0179 # The extension is everything starting at the last dot in the last 0180 # pathname component; the root is everything before that. 0181 # It is always true that root + ext == p. 0182 0183 def splitext(p): 0184 """Split the extension from a pathname. 0185 0186 Extension is everything from the last dot to the end. 0187 Return (root, ext), either part may be empty.""" 0188 0189 i = p.rfind('.') 0190 if i<=max(p.rfind('/'), p.rfind('\\')): 0191 return p, '' 0192 else: 0193 return p[:i], p[i:] 0194 0195 0196 # Return the tail (basename) part of a path. 0197 0198 def basename(p): 0199 """Returns the final component of a pathname""" 0200 return split(p)[1] 0201 0202 0203 # Return the head (dirname) part of a path. 0204 0205 def dirname(p): 0206 """Returns the directory component of a pathname""" 0207 return split(p)[0] 0208 0209 0210 # Return the longest prefix of all list elements. 0211 0212 def commonprefix(m): 0213 "Given a list of pathnames, returns the longest common leading component" 0214 if not m: return '' 0215 prefix = m[0] 0216 for item in m: 0217 for i in range(len(prefix)): 0218 if prefix[:i+1] != item[:i+1]: 0219 prefix = prefix[:i] 0220 if i == 0: return '' 0221 break 0222 return prefix 0223 0224 0225 # Get size, mtime, atime of files. 0226 0227 def getsize(filename): 0228 """Return the size of a file, reported by os.stat()""" 0229 return os.stat(filename).st_size 0230 0231 def getmtime(filename): 0232 """Return the last modification time of a file, reported by os.stat()""" 0233 return os.stat(filename).st_mtime 0234 0235 def getatime(filename): 0236 """Return the last access time of a file, reported by os.stat()""" 0237 return os.stat(filename).st_atime 0238 0239 def getctime(filename): 0240 """Return the creation time of a file, reported by os.stat().""" 0241 return os.stat(filename).st_ctime 0242 0243 # Is a path a symbolic link? 0244 # This will always return false on systems where posix.lstat doesn't exist. 0245 0246 def islink(path): 0247 """Test for symbolic link. On WindowsNT/95 always returns false""" 0248 return False 0249 0250 0251 # Does a path exist? 0252 0253 def exists(path): 0254 """Test whether a path exists""" 0255 try: 0256 st = os.stat(path) 0257 except os.error: 0258 return False 0259 return True 0260 0261 lexists = exists 0262 0263 0264 # Is a path a dos directory? 0265 # This follows symbolic links, so both islink() and isdir() can be true 0266 # for the same path. 0267 0268 def isdir(path): 0269 """Test whether a path is a directory""" 0270 try: 0271 st = os.stat(path) 0272 except os.error: 0273 return False 0274 return stat.S_ISDIR(st.st_mode) 0275 0276 0277 # Is a path a regular file? 0278 # This follows symbolic links, so both islink() and isdir() can be true 0279 # for the same path. 0280 0281 def isfile(path): 0282 """Test whether a path is a regular file""" 0283 try: 0284 st = os.stat(path) 0285 except os.error: 0286 return False 0287 return stat.S_ISREG(st.st_mode) 0288 0289 0290 # Is a path a mount point? Either a root (with or without drive letter) 0291 # or an UNC path with at most a / or \ after the mount point. 0292 0293 def ismount(path): 0294 """Test whether a path is a mount point (defined as root of drive)""" 0295 unc, rest = splitunc(path) 0296 if unc: 0297 return rest in ("", "/", "\\") 0298 p = splitdrive(path)[1] 0299 return len(p) == 1 and p[0] in '/\\' 0300 0301 0302 # Directory tree walk. 0303 # For each directory under top (including top itself, but excluding 0304 # '.' and '..'), func(arg, dirname, filenames) is called, where 0305 # dirname is the name of the directory and filenames is the list 0306 # of files (and subdirectories etc.) in the directory. 0307 # The func may modify the filenames list, to implement a filter, 0308 # or to impose a different order of visiting. 0309 0310 def walk(top, func, arg): 0311 """Directory tree walk with callback function. 0312 0313 For each directory in the directory tree rooted at top (including top 0314 itself, but excluding '.' and '..'), call func(arg, dirname, fnames). 0315 dirname is the name of the directory, and fnames a list of the names of 0316 the files and subdirectories in dirname (excluding '.' and '..'). func 0317 may modify the fnames list in-place (e.g. via del or slice assignment), 0318 and walk will only recurse into the subdirectories whose names remain in 0319 fnames; this can be used to implement a filter, or to impose a specific 0320 order of visiting. No semantics are defined for, or required of, arg, 0321 beyond that arg is always passed to func. It can be used, e.g., to pass 0322 a filename pattern, or a mutable object designed to accumulate 0323 statistics. Passing None for arg is common.""" 0324 0325 try: 0326 names = os.listdir(top) 0327 except os.error: 0328 return 0329 func(arg, top, names) 0330 exceptions = ('.', '..') 0331 for name in names: 0332 if name not in exceptions: 0333 name = join(top, name) 0334 if isdir(name): 0335 walk(name, func, arg) 0336 0337 0338 # Expand paths beginning with '~' or '~user'. 0339 # '~' means $HOME; '~user' means that user's home directory. 0340 # If the path doesn't begin with '~', or if the user or $HOME is unknown, 0341 # the path is returned unchanged (leaving error reporting to whatever 0342 # function is called with the expanded path as argument). 0343 # See also module 'glob' for expansion of *, ? and [...] in pathnames. 0344 # (A function should also be defined to do full *sh-style environment 0345 # variable expansion.) 0346 0347 def expanduser(path): 0348 """Expand ~ and ~user constructs. 0349 0350 If user or $HOME is unknown, do nothing.""" 0351 if path[:1] != '~': 0352 return path 0353 i, n = 1, len(path) 0354 while i < n and path[i] not in '/\\': 0355 i = i + 1 0356 if i == 1: 0357 if 'HOME' in os.environ: 0358 userhome = os.environ['HOME'] 0359 elif not 'HOMEPATH' in os.environ: 0360 return path 0361 else: 0362 try: 0363 drive = os.environ['HOMEDRIVE'] 0364 except KeyError: 0365 drive = '' 0366 userhome = join(drive, os.environ['HOMEPATH']) 0367 else: 0368 return path 0369 return userhome + path[i:] 0370 0371 0372 # Expand paths containing shell variable substitutions. 0373 # The following rules apply: 0374 # - no expansion within single quotes 0375 # - no escape character, except for '$$' which is translated into '$' 0376 # - ${varname} is accepted. 0377 # - varnames can be made out of letters, digits and the character '_' 0378 # XXX With COMMAND.COM you can use any characters in a variable name, 0379 # XXX except '^|<>='. 0380 0381 def expandvars(path): 0382 """Expand shell variables of form $var and ${var}. 0383 0384 Unknown variables are left unchanged.""" 0385 if '$' not in path: 0386 return path 0387 import string 0388 varchars = string.ascii_letters + string.digits + '_-' 0389 res = '' 0390 index = 0 0391 pathlen = len(path) 0392 while index < pathlen: 0393 c = path[index] 0394 if c == '\'': # no expansion within single quotes 0395 path = path[index + 1:] 0396 pathlen = len(path) 0397 try: 0398 index = path.index('\'') 0399 res = res + '\'' + path[:index + 1] 0400 except ValueError: 0401 res = res + path 0402 index = pathlen - 1 0403 elif c == '$': # variable or '$$' 0404 if path[index + 1:index + 2] == '$': 0405 res = res + c 0406 index = index + 1 0407 elif path[index + 1:index + 2] == '{': 0408 path = path[index+2:] 0409 pathlen = len(path) 0410 try: 0411 index = path.index('}') 0412 var = path[:index] 0413 if var in os.environ: 0414 res = res + os.environ[var] 0415 except ValueError: 0416 res = res + path 0417 index = pathlen - 1 0418 else: 0419 var = '' 0420 index = index + 1 0421 c = path[index:index + 1] 0422 while c != '' and c in varchars: 0423 var = var + c 0424 index = index + 1 0425 c = path[index:index + 1] 0426 if var in os.environ: 0427 res = res + os.environ[var] 0428 if c != '': 0429 res = res + c 0430 else: 0431 res = res + c 0432 index = index + 1 0433 return res 0434 0435 0436 # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B. 0437 # Previously, this function also truncated pathnames to 8+3 format, 0438 # but as this module is called "ntpath", that's obviously wrong! 0439 0440 def normpath(path): 0441 """Normalize path, eliminating double slashes, etc.""" 0442 path = path.replace("/", "\\") 0443 prefix, path = splitdrive(path) 0444 # We need to be careful here. If the prefix is empty, and the path starts 0445 # with a backslash, it could either be an absolute path on the current 0446 # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It 0447 # is therefore imperative NOT to collapse multiple backslashes blindly in 0448 # that case. 0449 # The code below preserves multiple backslashes when there is no drive 0450 # letter. This means that the invalid filename \\\a\b is preserved 0451 # unchanged, where a\\\b is normalised to a\b. It's not clear that there 0452 # is any better behaviour for such edge cases. 0453 if prefix == '': 0454 # No drive letter - preserve initial backslashes 0455 while path[:1] == "\\": 0456 prefix = prefix + "\\" 0457 path = path[1:] 0458 else: 0459 # We have a drive letter - collapse initial backslashes 0460 if path.startswith("\\"): 0461 prefix = prefix + "\\" 0462 path = path.lstrip("\\") 0463 comps = path.split("\\") 0464 i = 0 0465 while i < len(comps): 0466 if comps[i] in ('.', ''): 0467 del comps[i] 0468 elif comps[i] == '..': 0469 if i > 0 and comps[i-1] != '..': 0470 del comps[i-1:i+1] 0471 i -= 1 0472 elif i == 0 and prefix.endswith("\\"): 0473 del comps[i] 0474 else: 0475 i += 1 0476 else: 0477 i += 1 0478 # If the path is now empty, substitute '.' 0479 if not prefix and not comps: 0480 comps.append('.') 0481 return prefix + "\\".join(comps) 0482 0483 0484 # Return an absolute path. 0485 def abspath(path): 0486 """Return the absolute version of a path""" 0487 try: 0488 from nt import _getfullpathname 0489 except ImportError: # Not running on Windows - mock up something sensible. 0490 global abspath 0491 def _abspath(path): 0492 if not isabs(path): 0493 path = join(os.getcwd(), path) 0494 return normpath(path) 0495 abspath = _abspath 0496 return _abspath(path) 0497 0498 if path: # Empty path must return current working directory. 0499 try: 0500 path = _getfullpathname(path) 0501 except WindowsError: 0502 pass # Bad path - return unchanged. 0503 else: 0504 path = os.getcwd() 0505 return normpath(path) 0506 0507 # realpath is a no-op on systems without islink support 0508 realpath = abspath 0509 # Win9x family and earlier have no Unicode filename support. 0510 supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and 0511 sys.getwindowsversion()[3] >= 2) 0512
Generated by PyXR 0.9.4