summaryrefslogtreecommitdiffstats
path: root/Lib/posixpath.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/posixpath.py')
-rw-r--r--Lib/posixpath.py143
1 files changed, 52 insertions, 91 deletions
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
index 515b0ae..6e2ee175 100644
--- a/Lib/posixpath.py
+++ b/Lib/posixpath.py
@@ -12,6 +12,9 @@ for manipulation of the pathname component of URLs.
import os
import stat
+import genericpath
+import warnings
+from genericpath import *
__all__ = ["normcase","isabs","join","splitdrive","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
@@ -19,7 +22,7 @@ __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
"ismount","walk","expanduser","expandvars","normpath","abspath",
"samefile","sameopenfile","samestat",
"curdir","pardir","sep","pathsep","defpath","altsep","extsep",
- "devnull","realpath","supports_unicode_filenames"]
+ "devnull","realpath","supports_unicode_filenames","relpath"]
# strings representing various path-related bits and pieces
curdir = '.'
@@ -54,7 +57,9 @@ def isabs(s):
# Insert a '/' unless the first part is empty or already ends in '/'.
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:
if b.startswith('/'):
@@ -87,14 +92,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. Returns "(root, ext)", either part may be empty."""
- i = p.rfind('.')
- if i<=p.rfind('/'):
- return p, ''
- else:
- return p[:i], p[i:]
-
+ return genericpath._splitext(p, sep, altsep, extsep)
+splitext.__doc__ = genericpath._splitext.__doc__
# Split a pathname into a drive specification and the rest of the
# path. Useful on DOS/Windows/NT; on Unix, the drive is always empty.
@@ -105,50 +104,24 @@ def splitdrive(p):
return '', p
-# Return the tail (basename) part of a path.
+# Return the tail (basename) part of a path, same as split(path)[1].
def basename(p):
"""Returns the final component of a pathname"""
- return split(p)[1]
+ i = p.rfind('/') + 1
+ return p[i:]
-# Return the head (dirname) part of a path.
+# Return the head (dirname) part of a path, same as split(path)[0].
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
+ i = p.rfind('/') + 1
+ head = p[:i]
+ if head and head != '/'*len(head):
+ head = head.rstrip('/')
+ return head
-def getctime(filename):
- """Return the metadata change 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 os.lstat doesn't exist.
@@ -161,19 +134,6 @@ def islink(path):
return False
return stat.S_ISLNK(st.st_mode)
-
-# Does a path exist?
-# This is false for dangling symbolic links.
-
-def exists(path):
- """Test whether a path exists. Returns False for broken symbolic links"""
- try:
- st = os.stat(path)
- except os.error:
- return False
- return True
-
-
# Being true for dangling symbolic links is also useful.
def lexists(path):
@@ -185,32 +145,6 @@ def lexists(path):
return True
-# Is a path a 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 isfile() 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)
-
-
# Are two filenames really pointing to the same file?
def samefile(f1, f2):
@@ -244,6 +178,9 @@ def samestat(s1, s2):
def ismount(path):
"""Test whether a path is a mount point"""
+ if islink(path):
+ # A symlink can never be a mount point
+ return False
try:
s1 = os.lstat(path)
s2 = os.lstat(join(path, '..'))
@@ -282,7 +219,8 @@ 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:
@@ -328,7 +266,7 @@ def expanduser(path):
except KeyError:
return path
userhome = pwent.pw_dir
- userhome = userhome.rstrip('/')
+ userhome = userhome.rstrip('/') or userhome
return userhome + path[i:]
@@ -372,8 +310,10 @@ def expandvars(path):
def normpath(path):
"""Normalize path, eliminating double slashes, etc."""
+ # Preserve unicode (if path is unicode)
+ slash, dot = (u'/', u'.') if isinstance(path, unicode) else ('/', '.')
if path == '':
- return '.'
+ return dot
initial_slashes = path.startswith('/')
# POSIX allows one or two initial slashes, but treats three or more
# as single slash.
@@ -391,16 +331,20 @@ def normpath(path):
elif new_comps:
new_comps.pop()
comps = new_comps
- path = '/'.join(comps)
+ path = slash.join(comps)
if initial_slashes:
- path = '/'*initial_slashes + path
- return path or '.'
+ path = slash*initial_slashes + path
+ return path or dot
def abspath(path):
"""Return an absolute 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)
@@ -451,3 +395,20 @@ def _resolve_link(path):
return path
supports_unicode_filenames = False
+
+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)
+
+ # Work out how much of the filepath is shared by start and path.
+ i = len(commonprefix([start_list, path_list]))
+
+ rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
+ if not rel_list:
+ return curdir
+ return join(*rel_list)