python-2.5.2/win32/Lib/posixpath.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 """Common operations on Posix pathnames.
       
     2 
       
     3 Instead of importing this module directly, import os and refer to
       
     4 this module as os.path.  The "os.path" name is an alias for this
       
     5 module on Posix systems; on other systems (e.g. Mac, Windows),
       
     6 os.path provides the same operations in a manner specific to that
       
     7 platform, and is an alias to another module (e.g. macpath, ntpath).
       
     8 
       
     9 Some of this can actually be useful on non-Posix systems too, e.g.
       
    10 for manipulation of the pathname component of URLs.
       
    11 """
       
    12 
       
    13 import os
       
    14 import stat
       
    15 
       
    16 __all__ = ["normcase","isabs","join","splitdrive","split","splitext",
       
    17            "basename","dirname","commonprefix","getsize","getmtime",
       
    18            "getatime","getctime","islink","exists","lexists","isdir","isfile",
       
    19            "ismount","walk","expanduser","expandvars","normpath","abspath",
       
    20            "samefile","sameopenfile","samestat",
       
    21            "curdir","pardir","sep","pathsep","defpath","altsep","extsep",
       
    22            "devnull","realpath","supports_unicode_filenames"]
       
    23 
       
    24 # strings representing various path-related bits and pieces
       
    25 curdir = '.'
       
    26 pardir = '..'
       
    27 extsep = '.'
       
    28 sep = '/'
       
    29 pathsep = ':'
       
    30 defpath = ':/bin:/usr/bin'
       
    31 altsep = None
       
    32 devnull = '/dev/null'
       
    33 
       
    34 # Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
       
    35 # On MS-DOS this may also turn slashes into backslashes; however, other
       
    36 # normalizations (such as optimizing '../' away) are not allowed
       
    37 # (another function should be defined to do that).
       
    38 
       
    39 def normcase(s):
       
    40     """Normalize case of pathname.  Has no effect under Posix"""
       
    41     return s
       
    42 
       
    43 
       
    44 # Return whether a path is absolute.
       
    45 # Trivial in Posix, harder on the Mac or MS-DOS.
       
    46 
       
    47 def isabs(s):
       
    48     """Test whether a path is absolute"""
       
    49     return s.startswith('/')
       
    50 
       
    51 
       
    52 # Join pathnames.
       
    53 # Ignore the previous parts if a part is absolute.
       
    54 # Insert a '/' unless the first part is empty or already ends in '/'.
       
    55 
       
    56 def join(a, *p):
       
    57     """Join two or more pathname components, inserting '/' as needed"""
       
    58     path = a
       
    59     for b in p:
       
    60         if b.startswith('/'):
       
    61             path = b
       
    62         elif path == '' or path.endswith('/'):
       
    63             path +=  b
       
    64         else:
       
    65             path += '/' + b
       
    66     return path
       
    67 
       
    68 
       
    69 # Split a path in head (everything up to the last '/') and tail (the
       
    70 # rest).  If the path ends in '/', tail will be empty.  If there is no
       
    71 # '/' in the path, head  will be empty.
       
    72 # Trailing '/'es are stripped from head unless it is the root.
       
    73 
       
    74 def split(p):
       
    75     """Split a pathname.  Returns tuple "(head, tail)" where "tail" is
       
    76     everything after the final slash.  Either part may be empty."""
       
    77     i = p.rfind('/') + 1
       
    78     head, tail = p[:i], p[i:]
       
    79     if head and head != '/'*len(head):
       
    80         head = head.rstrip('/')
       
    81     return head, tail
       
    82 
       
    83 
       
    84 # Split a path in root and extension.
       
    85 # The extension is everything starting at the last dot in the last
       
    86 # pathname component; the root is everything before that.
       
    87 # It is always true that root + ext == p.
       
    88 
       
    89 def splitext(p):
       
    90     """Split the extension from a pathname.  Extension is everything from the
       
    91     last dot to the end.  Returns "(root, ext)", either part may be empty."""
       
    92     i = p.rfind('.')
       
    93     if i<=p.rfind('/'):
       
    94         return p, ''
       
    95     else:
       
    96         return p[:i], p[i:]
       
    97 
       
    98 
       
    99 # Split a pathname into a drive specification and the rest of the
       
   100 # path.  Useful on DOS/Windows/NT; on Unix, the drive is always empty.
       
   101 
       
   102 def splitdrive(p):
       
   103     """Split a pathname into drive and path. On Posix, drive is always
       
   104     empty."""
       
   105     return '', p
       
   106 
       
   107 
       
   108 # Return the tail (basename) part of a path.
       
   109 
       
   110 def basename(p):
       
   111     """Returns the final component of a pathname"""
       
   112     return split(p)[1]
       
   113 
       
   114 
       
   115 # Return the head (dirname) part of a path.
       
   116 
       
   117 def dirname(p):
       
   118     """Returns the directory component of a pathname"""
       
   119     return split(p)[0]
       
   120 
       
   121 
       
   122 # Return the longest prefix of all list elements.
       
   123 
       
   124 def commonprefix(m):
       
   125     "Given a list of pathnames, returns the longest common leading component"
       
   126     if not m: return ''
       
   127     s1 = min(m)
       
   128     s2 = max(m)
       
   129     n = min(len(s1), len(s2))
       
   130     for i in xrange(n):
       
   131         if s1[i] != s2[i]:
       
   132             return s1[:i]
       
   133     return s1[:n]
       
   134 
       
   135 # Get size, mtime, atime of files.
       
   136 
       
   137 def getsize(filename):
       
   138     """Return the size of a file, reported by os.stat()."""
       
   139     return os.stat(filename).st_size
       
   140 
       
   141 def getmtime(filename):
       
   142     """Return the last modification time of a file, reported by os.stat()."""
       
   143     return os.stat(filename).st_mtime
       
   144 
       
   145 def getatime(filename):
       
   146     """Return the last access time of a file, reported by os.stat()."""
       
   147     return os.stat(filename).st_atime
       
   148 
       
   149 def getctime(filename):
       
   150     """Return the metadata change time of a file, reported by os.stat()."""
       
   151     return os.stat(filename).st_ctime
       
   152 
       
   153 # Is a path a symbolic link?
       
   154 # This will always return false on systems where os.lstat doesn't exist.
       
   155 
       
   156 def islink(path):
       
   157     """Test whether a path is a symbolic link"""
       
   158     try:
       
   159         st = os.lstat(path)
       
   160     except (os.error, AttributeError):
       
   161         return False
       
   162     return stat.S_ISLNK(st.st_mode)
       
   163 
       
   164 
       
   165 # Does a path exist?
       
   166 # This is false for dangling symbolic links.
       
   167 
       
   168 def exists(path):
       
   169     """Test whether a path exists.  Returns False for broken symbolic links"""
       
   170     try:
       
   171         st = os.stat(path)
       
   172     except os.error:
       
   173         return False
       
   174     return True
       
   175 
       
   176 
       
   177 # Being true for dangling symbolic links is also useful.
       
   178 
       
   179 def lexists(path):
       
   180     """Test whether a path exists.  Returns True for broken symbolic links"""
       
   181     try:
       
   182         st = os.lstat(path)
       
   183     except os.error:
       
   184         return False
       
   185     return True
       
   186 
       
   187 
       
   188 # Is a path a directory?
       
   189 # This follows symbolic links, so both islink() and isdir() can be true
       
   190 # for the same path.
       
   191 
       
   192 def isdir(path):
       
   193     """Test whether a path is a directory"""
       
   194     try:
       
   195         st = os.stat(path)
       
   196     except os.error:
       
   197         return False
       
   198     return stat.S_ISDIR(st.st_mode)
       
   199 
       
   200 
       
   201 # Is a path a regular file?
       
   202 # This follows symbolic links, so both islink() and isfile() can be true
       
   203 # for the same path.
       
   204 
       
   205 def isfile(path):
       
   206     """Test whether a path is a regular file"""
       
   207     try:
       
   208         st = os.stat(path)
       
   209     except os.error:
       
   210         return False
       
   211     return stat.S_ISREG(st.st_mode)
       
   212 
       
   213 
       
   214 # Are two filenames really pointing to the same file?
       
   215 
       
   216 def samefile(f1, f2):
       
   217     """Test whether two pathnames reference the same actual file"""
       
   218     s1 = os.stat(f1)
       
   219     s2 = os.stat(f2)
       
   220     return samestat(s1, s2)
       
   221 
       
   222 
       
   223 # Are two open files really referencing the same file?
       
   224 # (Not necessarily the same file descriptor!)
       
   225 
       
   226 def sameopenfile(fp1, fp2):
       
   227     """Test whether two open file objects reference the same file"""
       
   228     s1 = os.fstat(fp1)
       
   229     s2 = os.fstat(fp2)
       
   230     return samestat(s1, s2)
       
   231 
       
   232 
       
   233 # Are two stat buffers (obtained from stat, fstat or lstat)
       
   234 # describing the same file?
       
   235 
       
   236 def samestat(s1, s2):
       
   237     """Test whether two stat buffers reference the same file"""
       
   238     return s1.st_ino == s2.st_ino and \
       
   239            s1.st_dev == s2.st_dev
       
   240 
       
   241 
       
   242 # Is a path a mount point?
       
   243 # (Does this work for all UNIXes?  Is it even guaranteed to work by Posix?)
       
   244 
       
   245 def ismount(path):
       
   246     """Test whether a path is a mount point"""
       
   247     try:
       
   248         s1 = os.lstat(path)
       
   249         s2 = os.lstat(join(path, '..'))
       
   250     except os.error:
       
   251         return False # It doesn't exist -- so not a mount point :-)
       
   252     dev1 = s1.st_dev
       
   253     dev2 = s2.st_dev
       
   254     if dev1 != dev2:
       
   255         return True     # path/.. on a different device as path
       
   256     ino1 = s1.st_ino
       
   257     ino2 = s2.st_ino
       
   258     if ino1 == ino2:
       
   259         return True     # path/.. is the same i-node as path
       
   260     return False
       
   261 
       
   262 
       
   263 # Directory tree walk.
       
   264 # For each directory under top (including top itself, but excluding
       
   265 # '.' and '..'), func(arg, dirname, filenames) is called, where
       
   266 # dirname is the name of the directory and filenames is the list
       
   267 # of files (and subdirectories etc.) in the directory.
       
   268 # The func may modify the filenames list, to implement a filter,
       
   269 # or to impose a different order of visiting.
       
   270 
       
   271 def walk(top, func, arg):
       
   272     """Directory tree walk with callback function.
       
   273 
       
   274     For each directory in the directory tree rooted at top (including top
       
   275     itself, but excluding '.' and '..'), call func(arg, dirname, fnames).
       
   276     dirname is the name of the directory, and fnames a list of the names of
       
   277     the files and subdirectories in dirname (excluding '.' and '..').  func
       
   278     may modify the fnames list in-place (e.g. via del or slice assignment),
       
   279     and walk will only recurse into the subdirectories whose names remain in
       
   280     fnames; this can be used to implement a filter, or to impose a specific
       
   281     order of visiting.  No semantics are defined for, or required of, arg,
       
   282     beyond that arg is always passed to func.  It can be used, e.g., to pass
       
   283     a filename pattern, or a mutable object designed to accumulate
       
   284     statistics.  Passing None for arg is common."""
       
   285 
       
   286     try:
       
   287         names = os.listdir(top)
       
   288     except os.error:
       
   289         return
       
   290     func(arg, top, names)
       
   291     for name in names:
       
   292         name = join(top, name)
       
   293         try:
       
   294             st = os.lstat(name)
       
   295         except os.error:
       
   296             continue
       
   297         if stat.S_ISDIR(st.st_mode):
       
   298             walk(name, func, arg)
       
   299 
       
   300 
       
   301 # Expand paths beginning with '~' or '~user'.
       
   302 # '~' means $HOME; '~user' means that user's home directory.
       
   303 # If the path doesn't begin with '~', or if the user or $HOME is unknown,
       
   304 # the path is returned unchanged (leaving error reporting to whatever
       
   305 # function is called with the expanded path as argument).
       
   306 # See also module 'glob' for expansion of *, ? and [...] in pathnames.
       
   307 # (A function should also be defined to do full *sh-style environment
       
   308 # variable expansion.)
       
   309 
       
   310 def expanduser(path):
       
   311     """Expand ~ and ~user constructions.  If user or $HOME is unknown,
       
   312     do nothing."""
       
   313     if not path.startswith('~'):
       
   314         return path
       
   315     i = path.find('/', 1)
       
   316     if i < 0:
       
   317         i = len(path)
       
   318     if i == 1:
       
   319         if 'HOME' not in os.environ:
       
   320             import pwd
       
   321             userhome = pwd.getpwuid(os.getuid()).pw_dir
       
   322         else:
       
   323             userhome = os.environ['HOME']
       
   324     else:
       
   325         import pwd
       
   326         try:
       
   327             pwent = pwd.getpwnam(path[1:i])
       
   328         except KeyError:
       
   329             return path
       
   330         userhome = pwent.pw_dir
       
   331     userhome = userhome.rstrip('/')
       
   332     return userhome + path[i:]
       
   333 
       
   334 
       
   335 # Expand paths containing shell variable substitutions.
       
   336 # This expands the forms $variable and ${variable} only.
       
   337 # Non-existent variables are left unchanged.
       
   338 
       
   339 _varprog = None
       
   340 
       
   341 def expandvars(path):
       
   342     """Expand shell variables of form $var and ${var}.  Unknown variables
       
   343     are left unchanged."""
       
   344     global _varprog
       
   345     if '$' not in path:
       
   346         return path
       
   347     if not _varprog:
       
   348         import re
       
   349         _varprog = re.compile(r'\$(\w+|\{[^}]*\})')
       
   350     i = 0
       
   351     while True:
       
   352         m = _varprog.search(path, i)
       
   353         if not m:
       
   354             break
       
   355         i, j = m.span(0)
       
   356         name = m.group(1)
       
   357         if name.startswith('{') and name.endswith('}'):
       
   358             name = name[1:-1]
       
   359         if name in os.environ:
       
   360             tail = path[j:]
       
   361             path = path[:i] + os.environ[name]
       
   362             i = len(path)
       
   363             path += tail
       
   364         else:
       
   365             i = j
       
   366     return path
       
   367 
       
   368 
       
   369 # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
       
   370 # It should be understood that this may change the meaning of the path
       
   371 # if it contains symbolic links!
       
   372 
       
   373 def normpath(path):
       
   374     """Normalize path, eliminating double slashes, etc."""
       
   375     if path == '':
       
   376         return '.'
       
   377     initial_slashes = path.startswith('/')
       
   378     # POSIX allows one or two initial slashes, but treats three or more
       
   379     # as single slash.
       
   380     if (initial_slashes and
       
   381         path.startswith('//') and not path.startswith('///')):
       
   382         initial_slashes = 2
       
   383     comps = path.split('/')
       
   384     new_comps = []
       
   385     for comp in comps:
       
   386         if comp in ('', '.'):
       
   387             continue
       
   388         if (comp != '..' or (not initial_slashes and not new_comps) or
       
   389              (new_comps and new_comps[-1] == '..')):
       
   390             new_comps.append(comp)
       
   391         elif new_comps:
       
   392             new_comps.pop()
       
   393     comps = new_comps
       
   394     path = '/'.join(comps)
       
   395     if initial_slashes:
       
   396         path = '/'*initial_slashes + path
       
   397     return path or '.'
       
   398 
       
   399 
       
   400 def abspath(path):
       
   401     """Return an absolute path."""
       
   402     if not isabs(path):
       
   403         path = join(os.getcwd(), path)
       
   404     return normpath(path)
       
   405 
       
   406 
       
   407 # Return a canonical path (i.e. the absolute location of a file on the
       
   408 # filesystem).
       
   409 
       
   410 def realpath(filename):
       
   411     """Return the canonical path of the specified filename, eliminating any
       
   412 symbolic links encountered in the path."""
       
   413     if isabs(filename):
       
   414         bits = ['/'] + filename.split('/')[1:]
       
   415     else:
       
   416         bits = [''] + filename.split('/')
       
   417 
       
   418     for i in range(2, len(bits)+1):
       
   419         component = join(*bits[0:i])
       
   420         # Resolve symbolic links.
       
   421         if islink(component):
       
   422             resolved = _resolve_link(component)
       
   423             if resolved is None:
       
   424                 # Infinite loop -- return original component + rest of the path
       
   425                 return abspath(join(*([component] + bits[i:])))
       
   426             else:
       
   427                 newpath = join(*([resolved] + bits[i:]))
       
   428                 return realpath(newpath)
       
   429 
       
   430     return abspath(filename)
       
   431 
       
   432 
       
   433 def _resolve_link(path):
       
   434     """Internal helper function.  Takes a path and follows symlinks
       
   435     until we either arrive at something that isn't a symlink, or
       
   436     encounter a path we've seen before (meaning that there's a loop).
       
   437     """
       
   438     paths_seen = []
       
   439     while islink(path):
       
   440         if path in paths_seen:
       
   441             # Already seen this path, so we must have a symlink loop
       
   442             return None
       
   443         paths_seen.append(path)
       
   444         # Resolve where the link points to
       
   445         resolved = os.readlink(path)
       
   446         if not isabs(resolved):
       
   447             dir = dirname(path)
       
   448             path = normpath(join(dir, resolved))
       
   449         else:
       
   450             path = normpath(resolved)
       
   451     return path
       
   452 
       
   453 supports_unicode_filenames = False