Home | History | Annotate | Download | only in Lib
      1 """
      2 Path operations common to more than one OS
      3 Do not use directly.  The OS specific modules import the appropriate
      4 functions from this module themselves.
      5 """
      6 import os
      7 import stat
      8 
      9 __all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime',
     10            'getsize', 'isdir', 'isfile', 'samefile', 'sameopenfile',
     11            'samestat']
     12 
     13 
     14 # Does a path exist?
     15 # This is false for dangling symbolic links on systems that support them.
     16 def exists(path):
     17     """Test whether a path exists.  Returns False for broken symbolic links"""
     18     try:
     19         os.stat(path)
     20     except OSError:
     21         return False
     22     return True
     23 
     24 
     25 # This follows symbolic links, so both islink() and isdir() can be true
     26 # for the same path on systems that support symlinks
     27 def isfile(path):
     28     """Test whether a path is a regular file"""
     29     try:
     30         st = os.stat(path)
     31     except OSError:
     32         return False
     33     return stat.S_ISREG(st.st_mode)
     34 
     35 
     36 # Is a path a directory?
     37 # This follows symbolic links, so both islink() and isdir()
     38 # can be true for the same path on systems that support symlinks
     39 def isdir(s):
     40     """Return true if the pathname refers to an existing directory."""
     41     try:
     42         st = os.stat(s)
     43     except OSError:
     44         return False
     45     return stat.S_ISDIR(st.st_mode)
     46 
     47 
     48 def getsize(filename):
     49     """Return the size of a file, reported by os.stat()."""
     50     return os.stat(filename).st_size
     51 
     52 
     53 def getmtime(filename):
     54     """Return the last modification time of a file, reported by os.stat()."""
     55     return os.stat(filename).st_mtime
     56 
     57 
     58 def getatime(filename):
     59     """Return the last access time of a file, reported by os.stat()."""
     60     return os.stat(filename).st_atime
     61 
     62 
     63 def getctime(filename):
     64     """Return the metadata change time of a file, reported by os.stat()."""
     65     return os.stat(filename).st_ctime
     66 
     67 
     68 # Return the longest prefix of all list elements.
     69 def commonprefix(m):
     70     "Given a list of pathnames, returns the longest common leading component"
     71     if not m: return ''
     72     # Some people pass in a list of pathname parts to operate in an OS-agnostic
     73     # fashion; don't try to translate in that case as that's an abuse of the
     74     # API and they are already doing what they need to be OS-agnostic and so
     75     # they most likely won't be using an os.PathLike object in the sublists.
     76     if not isinstance(m[0], (list, tuple)):
     77         m = tuple(map(os.fspath, m))
     78     s1 = min(m)
     79     s2 = max(m)
     80     for i, c in enumerate(s1):
     81         if c != s2[i]:
     82             return s1[:i]
     83     return s1
     84 
     85 # Are two stat buffers (obtained from stat, fstat or lstat)
     86 # describing the same file?
     87 def samestat(s1, s2):
     88     """Test whether two stat buffers reference the same file"""
     89     return (s1.st_ino == s2.st_ino and
     90             s1.st_dev == s2.st_dev)
     91 
     92 
     93 # Are two filenames really pointing to the same file?
     94 def samefile(f1, f2):
     95     """Test whether two pathnames reference the same actual file"""
     96     s1 = os.stat(f1)
     97     s2 = os.stat(f2)
     98     return samestat(s1, s2)
     99 
    100 
    101 # Are two open files really referencing the same file?
    102 # (Not necessarily the same file descriptor!)
    103 def sameopenfile(fp1, fp2):
    104     """Test whether two open file objects reference the same file"""
    105     s1 = os.fstat(fp1)
    106     s2 = os.fstat(fp2)
    107     return samestat(s1, s2)
    108 
    109 
    110 # Split a path in root and extension.
    111 # The extension is everything starting at the last dot in the last
    112 # pathname component; the root is everything before that.
    113 # It is always true that root + ext == p.
    114 
    115 # Generic implementation of splitext, to be parametrized with
    116 # the separators
    117 def _splitext(p, sep, altsep, extsep):
    118     """Split the extension from a pathname.
    119 
    120     Extension is everything from the last dot to the end, ignoring
    121     leading dots.  Returns "(root, ext)"; ext may be empty."""
    122     # NOTE: This code must work for text and bytes strings.
    123 
    124     sepIndex = p.rfind(sep)
    125     if altsep:
    126         altsepIndex = p.rfind(altsep)
    127         sepIndex = max(sepIndex, altsepIndex)
    128 
    129     dotIndex = p.rfind(extsep)
    130     if dotIndex > sepIndex:
    131         # skip all leading dots
    132         filenameIndex = sepIndex + 1
    133         while filenameIndex < dotIndex:
    134             if p[filenameIndex:filenameIndex+1] != extsep:
    135                 return p[:dotIndex], p[dotIndex:]
    136             filenameIndex += 1
    137 
    138     return p, p[:0]
    139 
    140 def _check_arg_types(funcname, *args):
    141     hasstr = hasbytes = False
    142     for s in args:
    143         if isinstance(s, str):
    144             hasstr = True
    145         elif isinstance(s, bytes):
    146             hasbytes = True
    147         else:
    148             raise TypeError('%s() argument must be str or bytes, not %r' %
    149                             (funcname, s.__class__.__name__)) from None
    150     if hasstr and hasbytes:
    151         raise TypeError("Can't mix strings and bytes in path components") from None
    152