Kaydet (Commit) 346f7af8 authored tarafından Guido van Rossum's avatar Guido van Rossum

Added doc strings and reindented according to new standard, without tabs.

(Like ntpath.py, this was contributed by "Charles G. Waldman" <cgw@pgt.com>)
üst 15e22e1c
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
# on other systems (e.g. Mac, Windows), os.path provides the same # on other systems (e.g. Mac, Windows), os.path provides the same
# operations in a manner specific to that platform, and is an alias # operations in a manner specific to that platform, and is an alias
# to another module (e.g. macpath, ntpath). # to another module (e.g. macpath, ntpath).
"""Common pathname manipulations, Posix version.
Instead of importing this module
directly, import os and refer to this module as os.path.
"""
import os import os
import stat import stat
...@@ -16,14 +20,16 @@ import stat ...@@ -16,14 +20,16 @@ import stat
# (another function should be defined to do that). # (another function should be defined to do that).
def normcase(s): def normcase(s):
return s """Normalize case of pathname. Has no effect under Posix"""
return s
# Return wheter a path is absolute. # Return wheter a path is absolute.
# Trivial in Posix, harder on the Mac or MS-DOS. # Trivial in Posix, harder on the Mac or MS-DOS.
def isabs(s): def isabs(s):
return s[:1] == '/' """Test whether a path is absolute"""
return s[:1] == '/'
# Join pathnames. # Join pathnames.
...@@ -31,15 +37,16 @@ def isabs(s): ...@@ -31,15 +37,16 @@ def isabs(s):
# Insert a '/' unless the first part is empty or already ends in '/'. # Insert a '/' unless the first part is empty or already ends in '/'.
def join(a, *p): def join(a, *p):
path = a """Join two or more pathname components, inserting '/' as needed"""
for b in p: path = a
if b[:1] == '/': for b in p:
path = b if b[:1] == '/':
elif path == '' or path[-1:] == '/': path = b
path = path + b elif path == '' or path[-1:] == '/':
else: path = path + b
path = path + '/' + b else:
return path path = path + '/' + b
return path
# Split a path in head (everything up to the last '/') and tail (the # Split a path in head (everything up to the last '/') and tail (the
...@@ -48,13 +55,15 @@ def join(a, *p): ...@@ -48,13 +55,15 @@ def join(a, *p):
# Trailing '/'es are stripped from head unless it is the root. # Trailing '/'es are stripped from head unless it is the root.
def split(p): def split(p):
import string """Split a pathname. Returns tuple "(head, tail)" where "tail" is
i = string.rfind(p, '/') + 1 everything after the final slash. Either part may be empty"""
head, tail = p[:i], p[i:] import string
if head and head <> '/'*len(head): i = string.rfind(p, '/') + 1
while head[-1] == '/': head, tail = p[:i], p[i:]
head = head[:-1] if head and head <> '/'*len(head):
return head, tail while head[-1] == '/':
head = head[:-1]
return head, tail
# Split a path in root and extension. # Split a path in root and extension.
...@@ -63,75 +72,84 @@ def split(p): ...@@ -63,75 +72,84 @@ def split(p):
# It is always true that root + ext == p. # It is always true that root + ext == p.
def splitext(p): def splitext(p):
root, ext = '', '' """Split the extension from a pathname. Extension is everything from the
for c in p: last dot to the end. Returns "(root, ext)", either part may be empty"""
if c == '/': root, ext = '', ''
root, ext = root + ext + c, '' for c in p:
elif c == '.': if c == '/':
if ext: root, ext = root + ext + c, ''
root, ext = root + ext, c elif c == '.':
else: if ext:
ext = c root, ext = root + ext, c
elif ext: else:
ext = ext + c ext = c
else: elif ext:
root = root + c ext = ext + c
return root, ext else:
root = root + c
return root, ext
# Split a pathname into a drive specification and the rest of the # 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. # path. Useful on DOS/Windows/NT; on Unix, the drive is always empty.
def splitdrive(p): def splitdrive(p):
return '', p """Split a pathname into drive and path. On Posix, drive is always
empty"""
return '', p
# Return the tail (basename) part of a path. # Return the tail (basename) part of a path.
def basename(p): def basename(p):
return split(p)[1] """Returns the final component of a pathname"""
return split(p)[1]
# Return the head (dirname) part of a path. # Return the head (dirname) part of a path.
def dirname(p): def dirname(p):
return split(p)[0] """Returns the directory component of a pathname"""
return split(p)[0]
# Return the longest prefix of all list elements. # Return the longest prefix of all list elements.
def commonprefix(m): def commonprefix(m):
if not m: return '' "Given a list of pathnames, returns the longest common leading component"
prefix = m[0] if not m: return ''
for item in m: prefix = m[0]
for i in range(len(prefix)): for item in m:
if prefix[:i+1] <> item[:i+1]: for i in range(len(prefix)):
prefix = prefix[:i] if prefix[:i+1] <> item[:i+1]:
if i == 0: return '' prefix = prefix[:i]
break if i == 0: return ''
return prefix break
return prefix
# Is a path a symbolic link? # Is a path a symbolic link?
# This will always return false on systems where os.lstat doesn't exist. # This will always return false on systems where os.lstat doesn't exist.
def islink(path): def islink(path):
try: """Test whether a path is a symbolic link"""
st = os.lstat(path) try:
except (os.error, AttributeError): st = os.lstat(path)
return 0 except (os.error, AttributeError):
return stat.S_ISLNK(st[stat.ST_MODE]) return 0
return stat.S_ISLNK(st[stat.ST_MODE])
# Does a path exist? # Does a path exist?
# This is false for dangling symbolic links. # This is false for dangling symbolic links.
def exists(path): def exists(path):
try: """Test whether a path exists. Returns false for broken symbolic links"""
st = os.stat(path) try:
except os.error: st = os.stat(path)
return 0 except os.error:
return 1 return 0
return 1
# Is a path a directory? # Is a path a directory?
...@@ -139,11 +157,12 @@ def exists(path): ...@@ -139,11 +157,12 @@ def exists(path):
# for the same path. # for the same path.
def isdir(path): def isdir(path):
try: """Test whether a path is a directory"""
st = os.stat(path) try:
except os.error: st = os.stat(path)
return 0 except os.error:
return stat.S_ISDIR(st[stat.ST_MODE]) return 0
return stat.S_ISDIR(st[stat.ST_MODE])
# Is a path a regular file? # Is a path a regular file?
...@@ -151,78 +170,87 @@ def isdir(path): ...@@ -151,78 +170,87 @@ def isdir(path):
# for the same path. # for the same path.
def isfile(path): def isfile(path):
try: """Test whether a path is a regular file"""
st = os.stat(path) try:
except os.error: st = os.stat(path)
return 0 except os.error:
return stat.S_ISREG(st[stat.ST_MODE]) return 0
return stat.S_ISREG(st[stat.ST_MODE])
# Are two filenames really pointing to the same file? # Are two filenames really pointing to the same file?
def samefile(f1, f2): def samefile(f1, f2):
s1 = os.stat(f1) """Test whether two pathnames reference the same actual file"""
s2 = os.stat(f2) s1 = os.stat(f1)
return samestat(s1, s2) s2 = os.stat(f2)
return samestat(s1, s2)
# Are two open files really referencing the same file? # Are two open files really referencing the same file?
# (Not necessarily the same file descriptor!) # (Not necessarily the same file descriptor!)
def sameopenfile(fp1, fp2): def sameopenfile(fp1, fp2):
s1 = os.fstat(fp1) """Test whether two open file objects reference the same file"""
s2 = os.fstat(fp2) s1 = os.fstat(fp1)
return samestat(s1, s2) s2 = os.fstat(fp2)
return samestat(s1, s2)
# Are two stat buffers (obtained from stat, fstat or lstat) # Are two stat buffers (obtained from stat, fstat or lstat)
# describing the same file? # describing the same file?
def samestat(s1, s2): def samestat(s1, s2):
return s1[stat.ST_INO] == s2[stat.ST_INO] and \ """Test whether two stat buffers reference the same file"""
s1[stat.ST_DEV] == s2[stat.ST_DEV] return s1[stat.ST_INO] == s2[stat.ST_INO] and \
s1[stat.ST_DEV] == s2[stat.ST_DEV]
# Is a path a mount point? # Is a path a mount point?
# (Does this work for all UNIXes? Is it even guaranteed to work by Posix?) # (Does this work for all UNIXes? Is it even guaranteed to work by Posix?)
def ismount(path): def ismount(path):
try: """Test whether a path is a mount point"""
s1 = os.stat(path) try:
s2 = os.stat(join(path, '..')) s1 = os.stat(path)
except os.error: s2 = os.stat(join(path, '..'))
return 0 # It doesn't exist -- so not a mount point :-) except os.error:
dev1 = s1[stat.ST_DEV] return 0 # It doesn't exist -- so not a mount point :-)
dev2 = s2[stat.ST_DEV] dev1 = s1[stat.ST_DEV]
if dev1 != dev2: dev2 = s2[stat.ST_DEV]
return 1 # path/.. on a different device as path if dev1 != dev2:
ino1 = s1[stat.ST_INO] return 1 # path/.. on a different device as path
ino2 = s2[stat.ST_INO] ino1 = s1[stat.ST_INO]
if ino1 == ino2: ino2 = s2[stat.ST_INO]
return 1 # path/.. is the same i-node as path if ino1 == ino2:
return 0 return 1 # path/.. is the same i-node as path
return 0
# Directory tree walk. # Directory tree walk.
# For each directory under top (including top itself, but excluding # For each directory under top (including top itself, but excluding
# '.' and '..'), func(arg, dirname, filenames) is called, where # '.' and '..'), func(arg, dirname, filenames) is called, where
# dirname is the name of the directory and filenames is the list # dirname is the name of the directory and filenames is the list
# files files (and subdirectories etc.) in the directory. # of files (and subdirectories etc.) in the directory.
# The func may modify the filenames list, to implement a filter, # The func may modify the filenames list, to implement a filter,
# or to impose a different order of visiting. # or to impose a different order of visiting.
def walk(top, func, arg): def walk(top, func, arg):
try: """walk(top,func,args) calls func(arg, d, files) for each directory "d"
names = os.listdir(top) in the tree rooted at "top" (including "top" itself). "files" is a list
except os.error: of all the files and subdirs in directory "d".
return """
func(arg, top, names) try:
exceptions = ('.', '..') names = os.listdir(top)
for name in names: except os.error:
if name not in exceptions: return
name = join(top, name) func(arg, top, names)
if isdir(name) and not islink(name): exceptions = ('.', '..')
walk(name, func, arg) for name in names:
if name not in exceptions:
name = join(top, name)
if isdir(name) and not islink(name):
walk(name, func, arg)
# Expand paths beginning with '~' or '~user'. # Expand paths beginning with '~' or '~user'.
...@@ -235,24 +263,26 @@ def walk(top, func, arg): ...@@ -235,24 +263,26 @@ def walk(top, func, arg):
# variable expansion.) # variable expansion.)
def expanduser(path): def expanduser(path):
if path[:1] <> '~': """Expand ~ and ~user constructions. If user or $HOME is unknown,
return path do nothing"""
i, n = 1, len(path) if path[:1] <> '~':
while i < n and path[i] <> '/': return path
i = i+1 i, n = 1, len(path)
if i == 1: while i < n and path[i] <> '/':
if not os.environ.has_key('HOME'): i = i+1
return path if i == 1:
userhome = os.environ['HOME'] if not os.environ.has_key('HOME'):
else: return path
import pwd userhome = os.environ['HOME']
try: else:
pwent = pwd.getpwnam(path[1:i]) import pwd
except KeyError: try:
return path pwent = pwd.getpwnam(path[1:i])
userhome = pwent[5] except KeyError:
if userhome[-1:] == '/': i = i+1 return path
return userhome + path[i:] userhome = pwent[5]
if userhome[-1:] == '/': i = i+1
return userhome + path[i:]
# Expand paths containing shell variable substitutions. # Expand paths containing shell variable substitutions.
...@@ -262,29 +292,31 @@ def expanduser(path): ...@@ -262,29 +292,31 @@ def expanduser(path):
_varprog = None _varprog = None
def expandvars(path): def expandvars(path):
global _varprog """Expand shell variables of form $var and ${var}. Unknown variables
if '$' not in path: are left unchanged"""
return path global _varprog
if not _varprog: if '$' not in path:
import re return path
_varprog = re.compile(r'\$(\w+|\{[^}]*\})') if not _varprog:
i = 0 import re
while 1: _varprog = re.compile(r'\$(\w+|\{[^}]*\})')
m = _varprog.search(path, i) i = 0
if not m: while 1:
break m = _varprog.search(path, i)
i, j = m.span(0) if not m:
name = m.group(1) break
if name[:1] == '{' and name[-1:] == '}': i, j = m.span(0)
name = name[1:-1] name = m.group(1)
if os.environ.has_key(name): if name[:1] == '{' and name[-1:] == '}':
tail = path[j:] name = name[1:-1]
path = path[:i] + os.environ[name] if os.environ.has_key(name):
i = len(path) tail = path[j:]
path = path + tail path = path[:i] + os.environ[name]
else: i = len(path)
i = j path = path + tail
return path else:
i = j
return path
# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B. # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
...@@ -292,26 +324,26 @@ def expandvars(path): ...@@ -292,26 +324,26 @@ def expandvars(path):
# if it contains symbolic links! # if it contains symbolic links!
def normpath(path): def normpath(path):
import string """Normalize path, eliminating double slashes, etc."""
# Treat initial slashes specially import string
slashes = '' # Treat initial slashes specially
while path[:1] == '/': slashes = ''
slashes = slashes + '/' while path[:1] == '/':
path = path[1:] slashes = slashes + '/'
comps = string.splitfields(path, '/') path = path[1:]
i = 0 comps = string.splitfields(path, '/')
while i < len(comps): i = 0
if comps[i] == '.': while i < len(comps):
del comps[i] if comps[i] == '.':
elif comps[i] == '..' and i > 0 and \ del comps[i]
comps[i-1] not in ('', '..'): elif comps[i] == '..' and i > 0 and comps[i-1] not in ('', '..'):
del comps[i-1:i+1] del comps[i-1:i+1]
i = i-1 i = i-1
elif comps[i] == '' and i > 0 and comps[i-1] <> '': elif comps[i] == '' and i > 0 and comps[i-1] <> '':
del comps[i] del comps[i]
else: else:
i = i+1 i = i+1
# If the path is now empty, substitute '.' # If the path is now empty, substitute '.'
if not comps and not slashes: if not comps and not slashes:
comps.append('.') comps.append('.')
return slashes + string.joinfields(comps, '/') return slashes + string.joinfields(comps, '/')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment