123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- """
- Path operations common to more than one OS
- Do not use directly. The OS specific modules import the appropriate
- functions from this module themselves.
- """
- import os
- import stat
- __all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime',
- 'getsize', 'isdir', 'isfile', 'samefile', 'sameopenfile',
- 'samestat']
- # Does a path exist?
- # This is false for dangling symbolic links on systems that support them.
- def exists(path):
- """Test whether a path exists. Returns False for broken symbolic links"""
- try:
- os.stat(path)
- except (OSError, ValueError):
- return False
- return True
- # This follows symbolic links, so both islink() and isdir() can be true
- # for the same path on systems that support symlinks
- def isfile(path):
- """Test whether a path is a regular file"""
- try:
- st = os.stat(path)
- except (OSError, ValueError):
- return False
- return stat.S_ISREG(st.st_mode)
- # Is a path a directory?
- # This follows symbolic links, so both islink() and isdir()
- # can be true for the same path on systems that support symlinks
- def isdir(s):
- """Return true if the pathname refers to an existing directory."""
- try:
- st = os.stat(s)
- except (OSError, ValueError):
- return False
- return stat.S_ISDIR(st.st_mode)
- 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
- def getctime(filename):
- """Return the metadata change time of a file, reported by os.stat()."""
- return os.stat(filename).st_ctime
- # 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 ''
- # Some people pass in a list of pathname parts to operate in an OS-agnostic
- # fashion; don't try to translate in that case as that's an abuse of the
- # API and they are already doing what they need to be OS-agnostic and so
- # they most likely won't be using an os.PathLike object in the sublists.
- if not isinstance(m[0], (list, tuple)):
- m = tuple(map(os.fspath, m))
- s1 = min(m)
- s2 = max(m)
- for i, c in enumerate(s1):
- if c != s2[i]:
- return s1[:i]
- return s1
- # Are two stat buffers (obtained from stat, fstat or lstat)
- # describing the same file?
- def samestat(s1, s2):
- """Test whether two stat buffers reference the same file"""
- return (s1.st_ino == s2.st_ino and
- s1.st_dev == s2.st_dev)
- # Are two filenames really pointing to the same file?
- def samefile(f1, f2):
- """Test whether two pathnames reference the same actual file or directory
- This is determined by the device number and i-node number and
- raises an exception if an os.stat() call on either pathname fails.
- """
- s1 = os.stat(f1)
- s2 = os.stat(f2)
- return samestat(s1, s2)
- # Are two open files really referencing the same file?
- # (Not necessarily the same file descriptor!)
- def sameopenfile(fp1, fp2):
- """Test whether two open file objects reference the same file"""
- s1 = os.fstat(fp1)
- s2 = os.fstat(fp2)
- return samestat(s1, s2)
- # Split a path in root and extension.
- # The extension is everything starting at the last dot in the last
- # pathname component; the root is everything before that.
- # It is always true that root + ext == p.
- # Generic implementation of splitext, to be parametrized with
- # the separators
- def _splitext(p, sep, altsep, extsep):
- """Split the extension from a pathname.
- Extension is everything from the last dot to the end, ignoring
- leading dots. Returns "(root, ext)"; ext may be empty."""
- # NOTE: This code must work for text and bytes strings.
- sepIndex = p.rfind(sep)
- if altsep:
- altsepIndex = p.rfind(altsep)
- sepIndex = max(sepIndex, altsepIndex)
- dotIndex = p.rfind(extsep)
- if dotIndex > sepIndex:
- # skip all leading dots
- filenameIndex = sepIndex + 1
- while filenameIndex < dotIndex:
- if p[filenameIndex:filenameIndex+1] != extsep:
- return p[:dotIndex], p[dotIndex:]
- filenameIndex += 1
- return p, p[:0]
- def _check_arg_types(funcname, *args):
- hasstr = hasbytes = False
- for s in args:
- if isinstance(s, str):
- hasstr = True
- elif isinstance(s, bytes):
- hasbytes = True
- else:
- raise TypeError(f'{funcname}() argument must be str, bytes, or '
- f'os.PathLike object, not {s.__class__.__name__!r}') from None
- if hasstr and hasbytes:
- raise TypeError("Can't mix strings and bytes in path components") from None
|