(root)/
Python-3.12.0/
Lib/
genericpath.py
       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', 'islink', '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, ValueError):
      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, ValueError):
      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, ValueError):
      44          return False
      45      return stat.S_ISDIR(st.st_mode)
      46  
      47  
      48  # Is a path a symbolic link?
      49  # This will always return false on systems where os.lstat doesn't exist.
      50  
      51  def islink(path):
      52      """Test whether a path is a symbolic link"""
      53      try:
      54          st = os.lstat(path)
      55      except (OSError, ValueError, AttributeError):
      56          return False
      57      return stat.S_ISLNK(st.st_mode)
      58  
      59  
      60  def getsize(filename):
      61      """Return the size of a file, reported by os.stat()."""
      62      return os.stat(filename).st_size
      63  
      64  
      65  def getmtime(filename):
      66      """Return the last modification time of a file, reported by os.stat()."""
      67      return os.stat(filename).st_mtime
      68  
      69  
      70  def getatime(filename):
      71      """Return the last access time of a file, reported by os.stat()."""
      72      return os.stat(filename).st_atime
      73  
      74  
      75  def getctime(filename):
      76      """Return the metadata change time of a file, reported by os.stat()."""
      77      return os.stat(filename).st_ctime
      78  
      79  
      80  # Return the longest prefix of all list elements.
      81  def commonprefix(m):
      82      "Given a list of pathnames, returns the longest common leading component"
      83      if not m: return ''
      84      # Some people pass in a list of pathname parts to operate in an OS-agnostic
      85      # fashion; don't try to translate in that case as that's an abuse of the
      86      # API and they are already doing what they need to be OS-agnostic and so
      87      # they most likely won't be using an os.PathLike object in the sublists.
      88      if not isinstance(m[0], (list, tuple)):
      89          m = tuple(map(os.fspath, m))
      90      s1 = min(m)
      91      s2 = max(m)
      92      for i, c in enumerate(s1):
      93          if c != s2[i]:
      94              return s1[:i]
      95      return s1
      96  
      97  # Are two stat buffers (obtained from stat, fstat or lstat)
      98  # describing the same file?
      99  def samestat(s1, s2):
     100      """Test whether two stat buffers reference the same file"""
     101      return (s1.st_ino == s2.st_ino and
     102              s1.st_dev == s2.st_dev)
     103  
     104  
     105  # Are two filenames really pointing to the same file?
     106  def samefile(f1, f2):
     107      """Test whether two pathnames reference the same actual file or directory
     108  
     109      This is determined by the device number and i-node number and
     110      raises an exception if an os.stat() call on either pathname fails.
     111      """
     112      s1 = os.stat(f1)
     113      s2 = os.stat(f2)
     114      return samestat(s1, s2)
     115  
     116  
     117  # Are two open files really referencing the same file?
     118  # (Not necessarily the same file descriptor!)
     119  def sameopenfile(fp1, fp2):
     120      """Test whether two open file objects reference the same file"""
     121      s1 = os.fstat(fp1)
     122      s2 = os.fstat(fp2)
     123      return samestat(s1, s2)
     124  
     125  
     126  # Split a path in root and extension.
     127  # The extension is everything starting at the last dot in the last
     128  # pathname component; the root is everything before that.
     129  # It is always true that root + ext == p.
     130  
     131  # Generic implementation of splitext, to be parametrized with
     132  # the separators
     133  def _splitext(p, sep, altsep, extsep):
     134      """Split the extension from a pathname.
     135  
     136      Extension is everything from the last dot to the end, ignoring
     137      leading dots.  Returns "(root, ext)"; ext may be empty."""
     138      # NOTE: This code must work for text and bytes strings.
     139  
     140      sepIndex = p.rfind(sep)
     141      if altsep:
     142          altsepIndex = p.rfind(altsep)
     143          sepIndex = max(sepIndex, altsepIndex)
     144  
     145      dotIndex = p.rfind(extsep)
     146      if dotIndex > sepIndex:
     147          # skip all leading dots
     148          filenameIndex = sepIndex + 1
     149          while filenameIndex < dotIndex:
     150              if p[filenameIndex:filenameIndex+1] != extsep:
     151                  return p[:dotIndex], p[dotIndex:]
     152              filenameIndex += 1
     153  
     154      return p, p[:0]
     155  
     156  def _check_arg_types(funcname, *args):
     157      hasstr = hasbytes = False
     158      for s in args:
     159          if isinstance(s, str):
     160              hasstr = True
     161          elif isinstance(s, bytes):
     162              hasbytes = True
     163          else:
     164              raise TypeError(f'{funcname}() argument must be str, bytes, or '
     165                              f'os.PathLike object, not {s.__class__.__name__!r}') from None
     166      if hasstr and hasbytes:
     167          raise TypeError("Can't mix strings and bytes in path components") from None