+++ /dev/null
-# Module 'ntpath' -- common operations on WinNT/Win95 pathnames\r
-"""Common pathname manipulations, WindowsNT/95 version.\r
-\r
-Instead of importing this module directly, import os and refer to this\r
-module as os.path.\r
-"""\r
-\r
-import os\r
-import sys\r
-import stat\r
-import genericpath\r
-import warnings\r
-\r
-from genericpath import *\r
-\r
-__all__ = ["normcase","isabs","join","splitdrive","split","splitext",\r
- "basename","dirname","commonprefix","getsize","getmtime",\r
- "getatime","getctime", "islink","exists","lexists","isdir","isfile",\r
- "ismount","walk","expanduser","expandvars","normpath","abspath",\r
- "splitunc","curdir","pardir","sep","pathsep","defpath","altsep",\r
- "extsep","devnull","realpath","supports_unicode_filenames","relpath"]\r
-\r
-# strings representing various path-related bits and pieces\r
-curdir = '.'\r
-pardir = '..'\r
-extsep = '.'\r
-sep = '\\'\r
-pathsep = ';'\r
-altsep = '/'\r
-defpath = '.;C:\\bin'\r
-if 'ce' in sys.builtin_module_names:\r
- defpath = '\\Windows'\r
-elif 'os2' in sys.builtin_module_names:\r
- # OS/2 w/ VACPP\r
- altsep = '/'\r
-devnull = 'nul'\r
-\r
-# Normalize the case of a pathname and map slashes to backslashes.\r
-# Other normalizations (such as optimizing '../' away) are not done\r
-# (this is done by normpath).\r
-\r
-def normcase(s):\r
- """Normalize case of pathname.\r
-\r
- Makes all characters lowercase and all slashes into backslashes."""\r
- return s.replace("/", "\\").lower()\r
-\r
-\r
-# Return whether a path is absolute.\r
-# Trivial in Posix, harder on the Mac or MS-DOS.\r
-# For DOS it is absolute if it starts with a slash or backslash (current\r
-# volume), or if a pathname after the volume letter and colon / UNC resource\r
-# starts with a slash or backslash.\r
-\r
-def isabs(s):\r
- """Test whether a path is absolute"""\r
- s = splitdrive(s)[1]\r
- return s != '' and s[:1] in '/\\'\r
-\r
-\r
-# Join two (or more) paths.\r
-\r
-def join(a, *p):\r
- """Join two or more pathname components, inserting "\\" as needed.\r
- If any component is an absolute path, all previous path components\r
- will be discarded."""\r
- path = a\r
- for b in p:\r
- b_wins = 0 # set to 1 iff b makes path irrelevant\r
- if path == "":\r
- b_wins = 1\r
-\r
- elif isabs(b):\r
- # This probably wipes out path so far. However, it's more\r
- # complicated if path begins with a drive letter:\r
- # 1. join('c:', '/a') == 'c:/a'\r
- # 2. join('c:/', '/a') == 'c:/a'\r
- # But\r
- # 3. join('c:/a', '/b') == '/b'\r
- # 4. join('c:', 'd:/') = 'd:/'\r
- # 5. join('c:/', 'd:/') = 'd:/'\r
- if path[1:2] != ":" or b[1:2] == ":":\r
- # Path doesn't start with a drive letter, or cases 4 and 5.\r
- b_wins = 1\r
-\r
- # Else path has a drive letter, and b doesn't but is absolute.\r
- elif len(path) > 3 or (len(path) == 3 and\r
- path[-1] not in "/\\"):\r
- # case 3\r
- b_wins = 1\r
-\r
- if b_wins:\r
- path = b\r
- else:\r
- # Join, and ensure there's a separator.\r
- assert len(path) > 0\r
- if path[-1] in "/\\":\r
- if b and b[0] in "/\\":\r
- path += b[1:]\r
- else:\r
- path += b\r
- elif path[-1] == ":":\r
- path += b\r
- elif b:\r
- if b[0] in "/\\":\r
- path += b\r
- else:\r
- path += "\\" + b\r
- else:\r
- # path is not empty and does not end with a backslash,\r
- # but b is empty; since, e.g., split('a/') produces\r
- # ('a', ''), it's best if join() adds a backslash in\r
- # this case.\r
- path += '\\'\r
-\r
- return path\r
-\r
-\r
-# Split a path in a drive specification (a drive letter followed by a\r
-# colon) and the path specification.\r
-# It is always true that drivespec + pathspec == p\r
-def splitdrive(p):\r
- """Split a pathname into drive and path specifiers. Returns a 2-tuple\r
-"(drive,path)"; either part may be empty"""\r
- pparts = p.split(':', 2)\r
- numparts = len(pparts)\r
- if numparts == 2:\r
- return pparts[0] + ':', pparts[1]\r
- else:\r
- if numparts == 1:\r
- return '', pparts[0]\r
- return '', p\r
-\r
-\r
-# Parse UNC paths\r
-def splitunc(p):\r
- """Split a pathname into UNC mount point and relative path specifiers.\r
-\r
- Return a 2-tuple (unc, rest); either part may be empty.\r
- If unc is not empty, it has the form '//host/mount' (or similar\r
- using backslashes). unc+rest is always the input path.\r
- Paths containing drive letters never have an UNC part.\r
- """\r
- if len(p.split(':', 2)) > 1:\r
- return '', p # Drive letter present\r
- firstTwo = p[0:2]\r
- if firstTwo == '//' or firstTwo == '\\\\':\r
- # is a UNC path:\r
- # vvvvvvvvvvvvvvvvvvvv equivalent to drive letter\r
- # \\machine\mountpoint\directories...\r
- # directory ^^^^^^^^^^^^^^^\r
- normp = normcase(p)\r
- index = normp.find('\\', 2)\r
- if index == -1:\r
- ##raise RuntimeError, 'illegal UNC path: "' + p + '"'\r
- return ("", p)\r
- index = normp.find('\\', index + 1)\r
- if index == -1:\r
- index = len(p)\r
- return p[:index], p[index:]\r
- return '', p\r
-\r
-\r
-# Split a path in head (everything up to the last '/') and tail (the\r
-# rest). After the trailing '/' is stripped, the invariant\r
-# join(head, tail) == p holds.\r
-# The resulting head won't end in '/' unless it is the root.\r
-\r
-def split(p):\r
- """Split a pathname.\r
-\r
- Return tuple (head, tail) where tail is everything after the final slash.\r
- Either part may be empty."""\r
-\r
- d, p = splitdrive(p)\r
- # set i to index beyond p's last slash\r
- i = len(p)\r
- while i and p[i-1] not in '/\\':\r
- i = i - 1\r
- head, tail = p[:i], p[i:] # now tail has no slashes\r
- # remove trailing slashes from head, unless it's all slashes\r
- head2 = head\r
- while head2 and head2[-1] in '/\\':\r
- head2 = head2[:-1]\r
- head = head2 or head\r
- return d + head, tail\r
-\r
-\r
-# Split a path in root and extension.\r
-# The extension is everything starting at the last dot in the last\r
-# pathname component; the root is everything before that.\r
-# It is always true that root + ext == p.\r
-\r
-def splitext(p):\r
- return genericpath._splitext(p, sep, altsep, extsep)\r
-splitext.__doc__ = genericpath._splitext.__doc__\r
-\r
-\r
-# Return the tail (basename) part of a path.\r
-\r
-def basename(p):\r
- """Returns the final component of a pathname"""\r
- return split(p)[1]\r
-\r
-\r
-# Return the head (dirname) part of a path.\r
-\r
-def dirname(p):\r
- """Returns the directory component of a pathname"""\r
- return split(p)[0]\r
-\r
-# Is a path a symbolic link?\r
-# This will always return false on systems where posix.lstat doesn't exist.\r
-\r
-def islink(path):\r
- """Test for symbolic link.\r
- On WindowsNT/95 and OS/2 always returns false\r
- """\r
- return False\r
-\r
-# alias exists to lexists\r
-lexists = exists\r
-\r
-# Is a path a mount point? Either a root (with or without drive letter)\r
-# or an UNC path with at most a / or \ after the mount point.\r
-\r
-def ismount(path):\r
- """Test whether a path is a mount point (defined as root of drive)"""\r
- unc, rest = splitunc(path)\r
- if unc:\r
- return rest in ("", "/", "\\")\r
- p = splitdrive(path)[1]\r
- return len(p) == 1 and p[0] in '/\\'\r
-\r
-\r
-# Directory tree walk.\r
-# For each directory under top (including top itself, but excluding\r
-# '.' and '..'), func(arg, dirname, filenames) is called, where\r
-# dirname is the name of the directory and filenames is the list\r
-# of files (and subdirectories etc.) in the directory.\r
-# The func may modify the filenames list, to implement a filter,\r
-# or to impose a different order of visiting.\r
-\r
-def walk(top, func, arg):\r
- """Directory tree walk with callback function.\r
-\r
- For each directory in the directory tree rooted at top (including top\r
- itself, but excluding '.' and '..'), call func(arg, dirname, fnames).\r
- dirname is the name of the directory, and fnames a list of the names of\r
- the files and subdirectories in dirname (excluding '.' and '..'). func\r
- may modify the fnames list in-place (e.g. via del or slice assignment),\r
- and walk will only recurse into the subdirectories whose names remain in\r
- fnames; this can be used to implement a filter, or to impose a specific\r
- order of visiting. No semantics are defined for, or required of, arg,\r
- beyond that arg is always passed to func. It can be used, e.g., to pass\r
- a filename pattern, or a mutable object designed to accumulate\r
- statistics. Passing None for arg is common."""\r
- warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",\r
- stacklevel=2)\r
- try:\r
- names = os.listdir(top)\r
- except os.error:\r
- return\r
- func(arg, top, names)\r
- for name in names:\r
- name = join(top, name)\r
- if isdir(name):\r
- walk(name, func, arg)\r
-\r
-\r
-# Expand paths beginning with '~' or '~user'.\r
-# '~' means $HOME; '~user' means that user's home directory.\r
-# If the path doesn't begin with '~', or if the user or $HOME is unknown,\r
-# the path is returned unchanged (leaving error reporting to whatever\r
-# function is called with the expanded path as argument).\r
-# See also module 'glob' for expansion of *, ? and [...] in pathnames.\r
-# (A function should also be defined to do full *sh-style environment\r
-# variable expansion.)\r
-\r
-def expanduser(path):\r
- """Expand ~ and ~user constructs.\r
-\r
- If user or $HOME is unknown, do nothing."""\r
- if path[:1] != '~':\r
- return path\r
- i, n = 1, len(path)\r
- while i < n and path[i] not in '/\\':\r
- i = i + 1\r
-\r
- if 'HOME' in os.environ:\r
- userhome = os.environ['HOME']\r
- elif 'USERPROFILE' in os.environ:\r
- userhome = os.environ['USERPROFILE']\r
- elif not 'HOMEPATH' in os.environ:\r
- return path\r
- else:\r
- try:\r
- drive = os.environ['HOMEDRIVE']\r
- except KeyError:\r
- drive = ''\r
- userhome = join(drive, os.environ['HOMEPATH'])\r
-\r
- if i != 1: #~user\r
- userhome = join(dirname(userhome), path[1:i])\r
-\r
- return userhome + path[i:]\r
-\r
-\r
-# Expand paths containing shell variable substitutions.\r
-# The following rules apply:\r
-# - no expansion within single quotes\r
-# - '$$' is translated into '$'\r
-# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2%\r
-# - ${varname} is accepted.\r
-# - $varname is accepted.\r
-# - %varname% is accepted.\r
-# - varnames can be made out of letters, digits and the characters '_-'\r
-# (though is not verified in the ${varname} and %varname% cases)\r
-# XXX With COMMAND.COM you can use any characters in a variable name,\r
-# XXX except '^|<>='.\r
-\r
-def expandvars(path):\r
- """Expand shell variables of the forms $var, ${var} and %var%.\r
-\r
- Unknown variables are left unchanged."""\r
- if '$' not in path and '%' not in path:\r
- return path\r
- import string\r
- varchars = string.ascii_letters + string.digits + '_-'\r
- res = ''\r
- index = 0\r
- pathlen = len(path)\r
- while index < pathlen:\r
- c = path[index]\r
- if c == '\'': # no expansion within single quotes\r
- path = path[index + 1:]\r
- pathlen = len(path)\r
- try:\r
- index = path.index('\'')\r
- res = res + '\'' + path[:index + 1]\r
- except ValueError:\r
- res = res + path\r
- index = pathlen - 1\r
- elif c == '%': # variable or '%'\r
- if path[index + 1:index + 2] == '%':\r
- res = res + c\r
- index = index + 1\r
- else:\r
- path = path[index+1:]\r
- pathlen = len(path)\r
- try:\r
- index = path.index('%')\r
- except ValueError:\r
- res = res + '%' + path\r
- index = pathlen - 1\r
- else:\r
- var = path[:index]\r
- if var in os.environ:\r
- res = res + os.environ[var]\r
- else:\r
- res = res + '%' + var + '%'\r
- elif c == '$': # variable or '$$'\r
- if path[index + 1:index + 2] == '$':\r
- res = res + c\r
- index = index + 1\r
- elif path[index + 1:index + 2] == '{':\r
- path = path[index+2:]\r
- pathlen = len(path)\r
- try:\r
- index = path.index('}')\r
- var = path[:index]\r
- if var in os.environ:\r
- res = res + os.environ[var]\r
- else:\r
- res = res + '${' + var + '}'\r
- except ValueError:\r
- res = res + '${' + path\r
- index = pathlen - 1\r
- else:\r
- var = ''\r
- index = index + 1\r
- c = path[index:index + 1]\r
- while c != '' and c in varchars:\r
- var = var + c\r
- index = index + 1\r
- c = path[index:index + 1]\r
- if var in os.environ:\r
- res = res + os.environ[var]\r
- else:\r
- res = res + '$' + var\r
- if c != '':\r
- index = index - 1\r
- else:\r
- res = res + c\r
- index = index + 1\r
- return res\r
-\r
-\r
-# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A\B.\r
-# Previously, this function also truncated pathnames to 8+3 format,\r
-# but as this module is called "ntpath", that's obviously wrong!\r
-\r
-def normpath(path):\r
- """Normalize path, eliminating double slashes, etc."""\r
- # Preserve unicode (if path is unicode)\r
- backslash, dot = (u'\\', u'.') if isinstance(path, unicode) else ('\\', '.')\r
- if path.startswith(('\\\\.\\', '\\\\?\\')):\r
- # in the case of paths with these prefixes:\r
- # \\.\ -> device names\r
- # \\?\ -> literal paths\r
- # do not do any normalization, but return the path unchanged\r
- return path\r
- path = path.replace("/", "\\")\r
- prefix, path = splitdrive(path)\r
- # We need to be careful here. If the prefix is empty, and the path starts\r
- # with a backslash, it could either be an absolute path on the current\r
- # drive (\dir1\dir2\file) or a UNC filename (\\server\mount\dir1\file). It\r
- # is therefore imperative NOT to collapse multiple backslashes blindly in\r
- # that case.\r
- # The code below preserves multiple backslashes when there is no drive\r
- # letter. This means that the invalid filename \\\a\b is preserved\r
- # unchanged, where a\\\b is normalised to a\b. It's not clear that there\r
- # is any better behaviour for such edge cases.\r
- if prefix == '':\r
- # No drive letter - preserve initial backslashes\r
- while path[:1] == "\\":\r
- prefix = prefix + backslash\r
- path = path[1:]\r
- else:\r
- # We have a drive letter - collapse initial backslashes\r
- if path.startswith("\\"):\r
- prefix = prefix + backslash\r
- path = path.lstrip("\\")\r
- comps = path.split("\\")\r
- i = 0\r
- while i < len(comps):\r
- if comps[i] in ('.', ''):\r
- del comps[i]\r
- elif comps[i] == '..':\r
- if i > 0 and comps[i-1] != '..':\r
- del comps[i-1:i+1]\r
- i -= 1\r
- elif i == 0 and prefix.endswith("\\"):\r
- del comps[i]\r
- else:\r
- i += 1\r
- else:\r
- i += 1\r
- # If the path is now empty, substitute '.'\r
- if not prefix and not comps:\r
- comps.append(dot)\r
- return prefix + backslash.join(comps)\r
-\r
-\r
-# Return an absolute path.\r
-try:\r
- from nt import _getfullpathname\r
-\r
-except ImportError: # not running on Windows - mock up something sensible\r
- def abspath(path):\r
- """Return the absolute version of a path."""\r
- if not isabs(path):\r
- if isinstance(path, unicode):\r
- cwd = os.getcwdu()\r
- else:\r
- cwd = os.getcwd()\r
- path = join(cwd, path)\r
- return normpath(path)\r
-\r
-else: # use native Windows method on Windows\r
- def abspath(path):\r
- """Return the absolute version of a path."""\r
-\r
- if path: # Empty path must return current working directory.\r
- try:\r
- path = _getfullpathname(path)\r
- except WindowsError:\r
- pass # Bad path - return unchanged.\r
- elif isinstance(path, unicode):\r
- path = os.getcwdu()\r
- else:\r
- path = os.getcwd()\r
- return normpath(path)\r
-\r
-# realpath is a no-op on systems without islink support\r
-realpath = abspath\r
-# Win9x family and earlier have no Unicode filename support.\r
-supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and\r
- sys.getwindowsversion()[3] >= 2)\r
-\r
-def _abspath_split(path):\r
- abs = abspath(normpath(path))\r
- prefix, rest = splitunc(abs)\r
- is_unc = bool(prefix)\r
- if not is_unc:\r
- prefix, rest = splitdrive(abs)\r
- return is_unc, prefix, [x for x in rest.split(sep) if x]\r
-\r
-def relpath(path, start=curdir):\r
- """Return a relative version of a path"""\r
-\r
- if not path:\r
- raise ValueError("no path specified")\r
-\r
- start_is_unc, start_prefix, start_list = _abspath_split(start)\r
- path_is_unc, path_prefix, path_list = _abspath_split(path)\r
-\r
- if path_is_unc ^ start_is_unc:\r
- raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"\r
- % (path, start))\r
- if path_prefix.lower() != start_prefix.lower():\r
- if path_is_unc:\r
- raise ValueError("path is on UNC root %s, start on UNC root %s"\r
- % (path_prefix, start_prefix))\r
- else:\r
- raise ValueError("path is on drive %s, start on drive %s"\r
- % (path_prefix, start_prefix))\r
- # Work out how much of the filepath is shared by start and path.\r
- i = 0\r
- for e1, e2 in zip(start_list, path_list):\r
- if e1.lower() != e2.lower():\r
- break\r
- i += 1\r
-\r
- rel_list = [pardir] * (len(start_list)-i) + path_list[i:]\r
- if not rel_list:\r
- return curdir\r
- return join(*rel_list)\r