summaryrefslogtreecommitdiffstats
path: root/Lib/ntpath.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/ntpath.py')
-rw-r--r--Lib/ntpath.py229
1 files changed, 115 insertions, 114 deletions
diff --git a/Lib/ntpath.py b/Lib/ntpath.py
index 7a79b53..11a0a3e 100644
--- a/Lib/ntpath.py
+++ b/Lib/ntpath.py
@@ -6,15 +6,19 @@ module as os.path.
"""
import os
-import stat
import sys
+import stat
+import genericpath
+import warnings
+
+from genericpath import *
__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
"getatime","getctime", "islink","exists","lexists","isdir","isfile",
"ismount","walk","expanduser","expandvars","normpath","abspath",
"splitunc","curdir","pardir","sep","pathsep","defpath","altsep",
- "extsep","devnull","realpath","supports_unicode_filenames"]
+ "extsep","devnull","realpath","supports_unicode_filenames","relpath"]
# strings representing various path-related bits and pieces
curdir = '.'
@@ -57,7 +61,9 @@ def isabs(s):
# Join two (or more) paths.
def join(a, *p):
- """Join two or more pathname components, inserting "\\" as needed"""
+ """Join two or more pathname components, inserting "\\" as needed.
+ If any component is an absolute path, all previous path components
+ will be discarded."""
path = a
for b in p:
b_wins = 0 # set to 1 iff b makes path irrelevant
@@ -181,16 +187,8 @@ def split(p):
# It is always true that root + ext == p.
def splitext(p):
- """Split the extension from a pathname.
-
- Extension is everything from the last dot to the end.
- Return (root, ext), either part may be empty."""
-
- i = p.rfind('.')
- if i<=max(p.rfind('/'), p.rfind('\\')):
- return p, ''
- else:
- return p[:i], p[i:]
+ return genericpath._splitext(p, sep, altsep, extsep)
+splitext.__doc__ = genericpath._splitext.__doc__
# Return the tail (basename) part of a path.
@@ -206,86 +204,18 @@ def dirname(p):
"""Returns the directory component of a pathname"""
return split(p)[0]
-
-# Return the longest prefix of all list elements.
-
-def commonprefix(m):
- "Given a list of pathnames, returns the longest common leading component"
- if not m: return ''
- s1 = min(m)
- s2 = max(m)
- n = min(len(s1), len(s2))
- for i in xrange(n):
- if s1[i] != s2[i]:
- return s1[:i]
- return s1[:n]
-
-
-# Get size, mtime, atime of files.
-
-def getsize(filename):
- """Return the size of a file, reported by os.stat()"""
- return os.stat(filename).st_size
-
-def getmtime(filename):
- """Return the last modification time of a file, reported by os.stat()"""
- return os.stat(filename).st_mtime
-
-def getatime(filename):
- """Return the last access time of a file, reported by os.stat()"""
- return os.stat(filename).st_atime
-
-def getctime(filename):
- """Return the creation time of a file, reported by os.stat()."""
- return os.stat(filename).st_ctime
-
# Is a path a symbolic link?
# This will always return false on systems where posix.lstat doesn't exist.
def islink(path):
- """Test for symbolic link. On WindowsNT/95 always returns false"""
+ """Test for symbolic link.
+ On WindowsNT/95 and OS/2 always returns false
+ """
return False
-
-# Does a path exist?
-
-def exists(path):
- """Test whether a path exists"""
- try:
- st = os.stat(path)
- except os.error:
- return False
- return True
-
+# alias exists to lexists
lexists = exists
-
-# Is a path a dos directory?
-# This follows symbolic links, so both islink() and isdir() can be true
-# for the same path.
-
-def isdir(path):
- """Test whether a path is a directory"""
- try:
- st = os.stat(path)
- except os.error:
- return False
- return stat.S_ISDIR(st.st_mode)
-
-
-# Is a path a regular file?
-# This follows symbolic links, so both islink() and isdir() can be true
-# for the same path.
-
-def isfile(path):
- """Test whether a path is a regular file"""
- try:
- st = os.stat(path)
- except os.error:
- return False
- return stat.S_ISREG(st.st_mode)
-
-
# Is a path a mount point? Either a root (with or without drive letter)
# or an UNC path with at most a / or \ after the mount point.
@@ -320,18 +250,17 @@ def walk(top, func, arg):
beyond that arg is always passed to func. It can be used, e.g., to pass
a filename pattern, or a mutable object designed to accumulate
statistics. Passing None for arg is common."""
-
+ warnings.warnpy3k("In 3.x, os.path.walk is removed in favor of os.walk.",
+ stacklevel=2)
try:
names = os.listdir(top)
except os.error:
return
func(arg, top, names)
- exceptions = ('.', '..')
for name in names:
- if name not in exceptions:
- name = join(top, name)
- if isdir(name):
- walk(name, func, arg)
+ name = join(top, name)
+ if isdir(name):
+ walk(name, func, arg)
# Expand paths beginning with '~' or '~user'.
@@ -352,36 +281,44 @@ def expanduser(path):
i, n = 1, len(path)
while i < n and path[i] not in '/\\':
i = i + 1
- if i == 1:
- if 'HOME' in os.environ:
- userhome = os.environ['HOME']
- elif not 'HOMEPATH' in os.environ:
- return path
- else:
- try:
- drive = os.environ['HOMEDRIVE']
- except KeyError:
- drive = ''
- userhome = join(drive, os.environ['HOMEPATH'])
- else:
+
+ if 'HOME' in os.environ:
+ userhome = os.environ['HOME']
+ elif 'USERPROFILE' in os.environ:
+ userhome = os.environ['USERPROFILE']
+ elif not 'HOMEPATH' in os.environ:
return path
+ else:
+ try:
+ drive = os.environ['HOMEDRIVE']
+ except KeyError:
+ drive = ''
+ userhome = join(drive, os.environ['HOMEPATH'])
+
+ if i != 1: #~user
+ userhome = join(dirname(userhome), path[1:i])
+
return userhome + path[i:]
# Expand paths containing shell variable substitutions.
# The following rules apply:
# - no expansion within single quotes
-# - no escape character, except for '$$' which is translated into '$'
+# - '$$' is translated into '$'
+# - '%%' is translated into '%' if '%%' are not seen in %var1%%var2%
# - ${varname} is accepted.
-# - varnames can be made out of letters, digits and the character '_'
+# - $varname is accepted.
+# - %varname% is accepted.
+# - varnames can be made out of letters, digits and the characters '_-'
+# (though is not verifed in the ${varname} and %varname% cases)
# XXX With COMMAND.COM you can use any characters in a variable name,
# XXX except '^|<>='.
def expandvars(path):
- """Expand shell variables of form $var and ${var}.
+ """Expand shell variables of the forms $var, ${var} and %var%.
Unknown variables are left unchanged."""
- if '$' not in path:
+ if '$' not in path and '%' not in path:
return path
import string
varchars = string.ascii_letters + string.digits + '_-'
@@ -399,6 +336,24 @@ def expandvars(path):
except ValueError:
res = res + path
index = pathlen - 1
+ elif c == '%': # variable or '%'
+ if path[index + 1:index + 2] == '%':
+ res = res + c
+ index = index + 1
+ else:
+ path = path[index+1:]
+ pathlen = len(path)
+ try:
+ index = path.index('%')
+ except ValueError:
+ res = res + '%' + path
+ index = pathlen - 1
+ else:
+ var = path[:index]
+ if var in os.environ:
+ res = res + os.environ[var]
+ else:
+ res = res + '%' + var + '%'
elif c == '$': # variable or '$$'
if path[index + 1:index + 2] == '$':
res = res + c
@@ -411,8 +366,10 @@ def expandvars(path):
var = path[:index]
if var in os.environ:
res = res + os.environ[var]
+ else:
+ res = res + '${' + var + '}'
except ValueError:
- res = res + path
+ res = res + '${' + path
index = pathlen - 1
else:
var = ''
@@ -424,8 +381,10 @@ def expandvars(path):
c = path[index:index + 1]
if var in os.environ:
res = res + os.environ[var]
+ else:
+ res = res + '$' + var
if c != '':
- res = res + c
+ index = index - 1
else:
res = res + c
index = index + 1
@@ -438,6 +397,14 @@ def expandvars(path):
def normpath(path):
"""Normalize path, eliminating double slashes, etc."""
+ # Preserve unicode (if path is unicode)
+ backslash, dot = (u'\\', u'.') if isinstance(path, unicode) else ('\\', '.')
+ if path.startswith(('\\\\.\\', '\\\\?\\')):
+ # in the case of paths with these prefixes:
+ # \\.\ -> device names
+ # \\?\ -> literal paths
+ # do not do any normalization, but return the path unchanged
+ return path
path = path.replace("/", "\\")
prefix, path = splitdrive(path)
# We need to be careful here. If the prefix is empty, and the path starts
@@ -452,12 +419,12 @@ def normpath(path):
if prefix == '':
# No drive letter - preserve initial backslashes
while path[:1] == "\\":
- prefix = prefix + "\\"
+ prefix = prefix + backslash
path = path[1:]
else:
# We have a drive letter - collapse initial backslashes
if path.startswith("\\"):
- prefix = prefix + "\\"
+ prefix = prefix + backslash
path = path.lstrip("\\")
comps = path.split("\\")
i = 0
@@ -476,8 +443,8 @@ def normpath(path):
i += 1
# If the path is now empty, substitute '.'
if not prefix and not comps:
- comps.append('.')
- return prefix + "\\".join(comps)
+ comps.append(dot)
+ return prefix + backslash.join(comps)
# Return an absolute path.
@@ -488,7 +455,11 @@ except ImportError: # not running on Windows - mock up something sensible
def abspath(path):
"""Return the absolute version of a path."""
if not isabs(path):
- path = join(os.getcwd(), path)
+ if isinstance(path, unicode):
+ cwd = os.getcwdu()
+ else:
+ cwd = os.getcwd()
+ path = join(cwd, path)
return normpath(path)
else: # use native Windows method on Windows
@@ -500,6 +471,8 @@ else: # use native Windows method on Windows
path = _getfullpathname(path)
except WindowsError:
pass # Bad path - return unchanged.
+ elif isinstance(path, unicode):
+ path = os.getcwdu()
else:
path = os.getcwd()
return normpath(path)
@@ -509,3 +482,31 @@ realpath = abspath
# Win9x family and earlier have no Unicode filename support.
supports_unicode_filenames = (hasattr(sys, "getwindowsversion") and
sys.getwindowsversion()[3] >= 2)
+
+def relpath(path, start=curdir):
+ """Return a relative version of a path"""
+
+ if not path:
+ raise ValueError("no path specified")
+ start_list = abspath(start).split(sep)
+ path_list = abspath(path).split(sep)
+ if start_list[0].lower() != path_list[0].lower():
+ unc_path, rest = splitunc(path)
+ unc_start, rest = splitunc(start)
+ if bool(unc_path) ^ bool(unc_start):
+ raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
+ % (path, start))
+ else:
+ raise ValueError("path is on drive %s, start on drive %s"
+ % (path_list[0], start_list[0]))
+ # Work out how much of the filepath is shared by start and path.
+ for i in range(min(len(start_list), len(path_list))):
+ if start_list[i].lower() != path_list[i].lower():
+ break
+ else:
+ i += 1
+
+ rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+ if not rel_list:
+ return curdir
+ return join(*rel_list)