| 1 | # Module 'ntpath' -- common operations on WinNT/Win95 pathnames
|
|---|
| 2 | """Common pathname manipulations, WindowsNT/95 version.
|
|---|
| 3 |
|
|---|
| 4 | Instead of importing this module directly, import os and refer to this
|
|---|
| 5 | module as os.path.
|
|---|
| 6 | """
|
|---|
| 7 |
|
|---|
| 8 | import os
|
|---|
| 9 | import stat
|
|---|
| 10 | import sys
|
|---|
| 11 |
|
|---|
| 12 | __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
|
|---|
| 13 | "basename","dirname","commonprefix","getsize","getmtime",
|
|---|
| 14 | "getatime","getctime", "islink","exists","lexists","isdir","isfile",
|
|---|
| 15 | "ismount","walk","expanduser","expandvars","normpath","abspath",
|
|---|
| 16 | "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
|
|---|
| 17 | "extsep","devnull","realpath","supports_unicode_filenames"]
|
|---|
| 18 |
|
|---|
| 19 | # strings representing various path-related bits and pieces
|
|---|
| 20 | curdir = '.'
|
|---|
| 21 | pardir = '..'
|
|---|
| 22 | extsep = '.'
|
|---|
| 23 | sep = '\\'
|
|---|
| 24 | pathsep = ';'
|
|---|
| 25 | altsep = '/'
|
|---|
| 26 | defpath = '.;C:\\bin'
|
|---|
| 27 | if 'ce' in sys.builtin_module_names:
|
|---|
| 28 | defpath = '\\Windows'
|
|---|
| 29 | elif 'os2' in sys.builtin_module_names:
|
|---|
| 30 | # OS/2 w/ VACPP
|
|---|
| 31 | altsep = '/'
|
|---|
| 32 | devnull = 'nul'
|
|---|
| 33 |
|
|---|
| 34 | # Normalize the case of a pathname and map slashes to backslashes.
|
|---|
| 35 | # Other normalizations (such as optimizing '../' away) are not done
|
|---|
| 36 | # (this is done by normpath).
|
|---|
| 37 |
|
|---|
| 38 | def normcase(s):
|
|---|
| 39 | """Normalize case of pathname.
|
|---|
| 40 |
|
|---|
| 41 | Makes all characters lowercase and all slashes into backslashes."""
|
|---|
| 42 | return s.replace("/", "\\").lower()
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 | # Return whether a path is absolute.
|
|---|
| 46 | # Trivial in Posix, harder on the Mac or MS-DOS.
|
|---|
| 47 | # For DOS it is absolute if it starts with a slash or backslash (current
|
|---|
| 48 | # volume), or if a pathname after the volume letter and colon / UNC resource
|
|---|
| 49 | # starts with a slash or backslash.
|
|---|
| 50 |
|
|---|
| 51 | def isabs(s):
|
|---|
| 52 | """Test whether a path is absolute"""
|
|---|
| 53 | s = splitdrive(s)[1]
|
|---|
| 54 | return s != '' and s[:1] in '/\\'
|
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 | # Join two (or more) paths.
|
|---|
| 58 |
|
|---|
| 59 | def join(a, *p):
|
|---|
| 60 | """Join two or more pathname components, inserting "\\" as needed"""
|
|---|
| 61 | path = a
|
|---|
| 62 | for b in p:
|
|---|
| 63 | b_wins = 0 # set to 1 iff b makes path irrelevant
|
|---|
| 64 | if path == "":
|
|---|
| 65 | b_wins = 1
|
|---|
| 66 |
|
|---|
| 67 | elif isabs(b):
|
|---|
| 68 | # This probably wipes out path so far. However, it's more
|
|---|
| 69 | # complicated if path begins with a drive letter:
|
|---|
| 70 | # 1. join('c:', '/a') == 'c:/a'
|
|---|
| 71 | # 2. join('c:/', '/a') == 'c:/a'
|
|---|
| 72 | # But
|
|---|
| 73 | # 3. join('c:/a', '/b') == '/b'
|
|---|
| 74 | # 4. join('c:', 'd:/') = 'd:/'
|
|---|
| 75 | # 5. join('c:/', 'd:/') = 'd:/'
|
|---|
| 76 | if path[1:2] != ":" or b[1:2] == ":":
|
|---|
| 77 | # Path doesn't start with a drive letter, or cases 4 and 5.
|
|---|
| 78 | b_wins = 1
|
|---|
| 79 |
|
|---|
| 80 | # Else path has a drive letter, and b doesn't but is absolute.
|
|---|
| 81 | elif len(path) > 3 or (len(path) == 3 and
|
|---|
| 82 | path[-1] not in "/\\"):
|
|---|
| 83 | # case 3
|
|---|
| 84 | b_wins = 1
|
|---|
| 85 |
|
|---|
| 86 | if b_wins:
|
|---|
| 87 | path = b
|
|---|
| 88 | else:
|
|---|
| 89 | # Join, and ensure there's a separator.
|
|---|
| 90 | assert len(path) > 0
|
|---|
| 91 | if path[-1] in "/\\":
|
|---|
| 92 | if b and b[0] in "/\\":
|
|---|
| 93 | path += b[1:]
|
|---|
| 94 | else:
|
|---|
| 95 | path += b
|
|---|
| 96 | elif path[-1] == ":":
|
|---|
| 97 | path += b
|
|---|
| 98 | elif b:
|
|---|
| 99 | if b[0] in "/\\":
|
|---|
| 100 | path += b
|
|---|
| 101 | else:
|
|---|
| 102 | path += "\\" + b
|
|---|
| 103 | else:
|
|---|
| 104 | # path is not empty and does not end with a backslash,
|
|---|
| 105 | # but b is empty; since, e.g., split('a/') produces
|
|---|
| 106 | # ('a', ''), it's best if join() adds a backslash in
|
|---|
| 107 | # this case.
|
|---|
| 108 | path += '\\'
|
|---|
| 109 |
|
|---|
| 110 | return path
|
|---|
| 111 |
|
|---|
| 112 |
|
|---|
| 113 | # Split a path in a drive specification (a drive letter followed by a
|
|---|
| 114 | # colon) and the path specification.
|
|---|
| 115 | # It is always true that drivespec + pathspec == p
|
|---|
| 116 | def splitdrive(p):
|
|---|
| 117 | """Split a pathname into drive and path specifiers. Returns a 2-tuple
|
|---|
| 118 | "(drive,path)"; either part may be empty"""
|
|---|
| 119 | if p[1:2] == ':':
|
|---|
| 120 | return p[0:2], p[2:]
|
|---|
| 121 | return '', p
|
|---|
| 122 |
|
|---|
| 123 |
|
|---|
| 124 | # Parse UNC paths
|
|---|
| 125 | def splitunc(p):
|
|---|
| 126 | """Split a pathname into UNC mount point and relative path specifiers.
|
|---|
| 127 |
|
|---|
| 128 | Return a 2-tuple (unc, rest); either part may be empty.
|
|---|
| 129 | If unc is not empty, it has the form '//host/mount' (or similar
|
|---|
| 130 | using backslashes). unc+rest is always the input path.
|
|---|
| 131 | Paths containing drive letters never have an UNC part.
|
|---|
| 132 | """
|
|---|
| 133 | if p[1:2] == ':':
|
|---|
| 134 | return '', p # Drive letter present
|
|---|
| 135 | firstTwo = p[0:2]
|
|---|
| 136 | if firstTwo == '//' or firstTwo == '\\\\':
|
|---|
| 137 | # is a UNC path:
|
|---|
| 138 | # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter
|
|---|
| 139 | # \\machine\mountpoint\directories...
|
|---|
| 140 | # directory ^^^^^^^^^^^^^^^
|
|---|
| 141 | normp = normcase(p)
|
|---|
| 142 | index = normp.find('\\', 2)
|
|---|
| 143 | if index == -1:
|
|---|
| 144 | ##raise RuntimeError, 'illegal UNC path: "' + p + '"'
|
|---|
| 145 | return ("", p)
|
|---|
| 146 | index = normp.find('\\', index + 1)
|
|---|
| 147 | if index == -1:
|
|---|
| 148 | index = len(p)
|
|---|
| 149 | return p[:index], p[index:]
|
|---|
| 150 | return '', p
|
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 | # Split a path in head (everything up to the last '/') and tail (the
|
|---|
| 154 | # rest). After the trailing '/' is stripped, the invariant
|
|---|
| 155 | # join(head, tail) == p holds.
|
|---|
| 156 | # The resulting head won't end in '/' unless it is the root.
|
|---|
| 157 |
|
|---|
| 158 | def split(p):
|
|---|
|
|---|