1*cda5da8dSAndroid Build Coastguard Workerimport fnmatch 2*cda5da8dSAndroid Build Coastguard Workerimport functools 3*cda5da8dSAndroid Build Coastguard Workerimport io 4*cda5da8dSAndroid Build Coastguard Workerimport ntpath 5*cda5da8dSAndroid Build Coastguard Workerimport os 6*cda5da8dSAndroid Build Coastguard Workerimport posixpath 7*cda5da8dSAndroid Build Coastguard Workerimport re 8*cda5da8dSAndroid Build Coastguard Workerimport sys 9*cda5da8dSAndroid Build Coastguard Workerimport warnings 10*cda5da8dSAndroid Build Coastguard Workerfrom _collections_abc import Sequence 11*cda5da8dSAndroid Build Coastguard Workerfrom errno import ENOENT, ENOTDIR, EBADF, ELOOP 12*cda5da8dSAndroid Build Coastguard Workerfrom operator import attrgetter 13*cda5da8dSAndroid Build Coastguard Workerfrom stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO 14*cda5da8dSAndroid Build Coastguard Workerfrom urllib.parse import quote_from_bytes as urlquote_from_bytes 15*cda5da8dSAndroid Build Coastguard Worker 16*cda5da8dSAndroid Build Coastguard Worker 17*cda5da8dSAndroid Build Coastguard Worker__all__ = [ 18*cda5da8dSAndroid Build Coastguard Worker "PurePath", "PurePosixPath", "PureWindowsPath", 19*cda5da8dSAndroid Build Coastguard Worker "Path", "PosixPath", "WindowsPath", 20*cda5da8dSAndroid Build Coastguard Worker ] 21*cda5da8dSAndroid Build Coastguard Worker 22*cda5da8dSAndroid Build Coastguard Worker# 23*cda5da8dSAndroid Build Coastguard Worker# Internals 24*cda5da8dSAndroid Build Coastguard Worker# 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Worker_WINERROR_NOT_READY = 21 # drive exists but is not accessible 27*cda5da8dSAndroid Build Coastguard Worker_WINERROR_INVALID_NAME = 123 # fix for bpo-35306 28*cda5da8dSAndroid Build Coastguard Worker_WINERROR_CANT_RESOLVE_FILENAME = 1921 # broken symlink pointing to itself 29*cda5da8dSAndroid Build Coastguard Worker 30*cda5da8dSAndroid Build Coastguard Worker# EBADF - guard against macOS `stat` throwing EBADF 31*cda5da8dSAndroid Build Coastguard Worker_IGNORED_ERRNOS = (ENOENT, ENOTDIR, EBADF, ELOOP) 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker_IGNORED_WINERRORS = ( 34*cda5da8dSAndroid Build Coastguard Worker _WINERROR_NOT_READY, 35*cda5da8dSAndroid Build Coastguard Worker _WINERROR_INVALID_NAME, 36*cda5da8dSAndroid Build Coastguard Worker _WINERROR_CANT_RESOLVE_FILENAME) 37*cda5da8dSAndroid Build Coastguard Worker 38*cda5da8dSAndroid Build Coastguard Workerdef _ignore_error(exception): 39*cda5da8dSAndroid Build Coastguard Worker return (getattr(exception, 'errno', None) in _IGNORED_ERRNOS or 40*cda5da8dSAndroid Build Coastguard Worker getattr(exception, 'winerror', None) in _IGNORED_WINERRORS) 41*cda5da8dSAndroid Build Coastguard Worker 42*cda5da8dSAndroid Build Coastguard Worker 43*cda5da8dSAndroid Build Coastguard Workerdef _is_wildcard_pattern(pat): 44*cda5da8dSAndroid Build Coastguard Worker # Whether this pattern needs actual matching using fnmatch, or can 45*cda5da8dSAndroid Build Coastguard Worker # be looked up directly as a file. 46*cda5da8dSAndroid Build Coastguard Worker return "*" in pat or "?" in pat or "[" in pat 47*cda5da8dSAndroid Build Coastguard Worker 48*cda5da8dSAndroid Build Coastguard Worker 49*cda5da8dSAndroid Build Coastguard Workerclass _Flavour(object): 50*cda5da8dSAndroid Build Coastguard Worker """A flavour implements a particular (platform-specific) set of path 51*cda5da8dSAndroid Build Coastguard Worker semantics.""" 52*cda5da8dSAndroid Build Coastguard Worker 53*cda5da8dSAndroid Build Coastguard Worker def __init__(self): 54*cda5da8dSAndroid Build Coastguard Worker self.join = self.sep.join 55*cda5da8dSAndroid Build Coastguard Worker 56*cda5da8dSAndroid Build Coastguard Worker def parse_parts(self, parts): 57*cda5da8dSAndroid Build Coastguard Worker parsed = [] 58*cda5da8dSAndroid Build Coastguard Worker sep = self.sep 59*cda5da8dSAndroid Build Coastguard Worker altsep = self.altsep 60*cda5da8dSAndroid Build Coastguard Worker drv = root = '' 61*cda5da8dSAndroid Build Coastguard Worker it = reversed(parts) 62*cda5da8dSAndroid Build Coastguard Worker for part in it: 63*cda5da8dSAndroid Build Coastguard Worker if not part: 64*cda5da8dSAndroid Build Coastguard Worker continue 65*cda5da8dSAndroid Build Coastguard Worker if altsep: 66*cda5da8dSAndroid Build Coastguard Worker part = part.replace(altsep, sep) 67*cda5da8dSAndroid Build Coastguard Worker drv, root, rel = self.splitroot(part) 68*cda5da8dSAndroid Build Coastguard Worker if sep in rel: 69*cda5da8dSAndroid Build Coastguard Worker for x in reversed(rel.split(sep)): 70*cda5da8dSAndroid Build Coastguard Worker if x and x != '.': 71*cda5da8dSAndroid Build Coastguard Worker parsed.append(sys.intern(x)) 72*cda5da8dSAndroid Build Coastguard Worker else: 73*cda5da8dSAndroid Build Coastguard Worker if rel and rel != '.': 74*cda5da8dSAndroid Build Coastguard Worker parsed.append(sys.intern(rel)) 75*cda5da8dSAndroid Build Coastguard Worker if drv or root: 76*cda5da8dSAndroid Build Coastguard Worker if not drv: 77*cda5da8dSAndroid Build Coastguard Worker # If no drive is present, try to find one in the previous 78*cda5da8dSAndroid Build Coastguard Worker # parts. This makes the result of parsing e.g. 79*cda5da8dSAndroid Build Coastguard Worker # ("C:", "/", "a") reasonably intuitive. 80*cda5da8dSAndroid Build Coastguard Worker for part in it: 81*cda5da8dSAndroid Build Coastguard Worker if not part: 82*cda5da8dSAndroid Build Coastguard Worker continue 83*cda5da8dSAndroid Build Coastguard Worker if altsep: 84*cda5da8dSAndroid Build Coastguard Worker part = part.replace(altsep, sep) 85*cda5da8dSAndroid Build Coastguard Worker drv = self.splitroot(part)[0] 86*cda5da8dSAndroid Build Coastguard Worker if drv: 87*cda5da8dSAndroid Build Coastguard Worker break 88*cda5da8dSAndroid Build Coastguard Worker break 89*cda5da8dSAndroid Build Coastguard Worker if drv or root: 90*cda5da8dSAndroid Build Coastguard Worker parsed.append(drv + root) 91*cda5da8dSAndroid Build Coastguard Worker parsed.reverse() 92*cda5da8dSAndroid Build Coastguard Worker return drv, root, parsed 93*cda5da8dSAndroid Build Coastguard Worker 94*cda5da8dSAndroid Build Coastguard Worker def join_parsed_parts(self, drv, root, parts, drv2, root2, parts2): 95*cda5da8dSAndroid Build Coastguard Worker """ 96*cda5da8dSAndroid Build Coastguard Worker Join the two paths represented by the respective 97*cda5da8dSAndroid Build Coastguard Worker (drive, root, parts) tuples. Return a new (drive, root, parts) tuple. 98*cda5da8dSAndroid Build Coastguard Worker """ 99*cda5da8dSAndroid Build Coastguard Worker if root2: 100*cda5da8dSAndroid Build Coastguard Worker if not drv2 and drv: 101*cda5da8dSAndroid Build Coastguard Worker return drv, root2, [drv + root2] + parts2[1:] 102*cda5da8dSAndroid Build Coastguard Worker elif drv2: 103*cda5da8dSAndroid Build Coastguard Worker if drv2 == drv or self.casefold(drv2) == self.casefold(drv): 104*cda5da8dSAndroid Build Coastguard Worker # Same drive => second path is relative to the first 105*cda5da8dSAndroid Build Coastguard Worker return drv, root, parts + parts2[1:] 106*cda5da8dSAndroid Build Coastguard Worker else: 107*cda5da8dSAndroid Build Coastguard Worker # Second path is non-anchored (common case) 108*cda5da8dSAndroid Build Coastguard Worker return drv, root, parts + parts2 109*cda5da8dSAndroid Build Coastguard Worker return drv2, root2, parts2 110*cda5da8dSAndroid Build Coastguard Worker 111*cda5da8dSAndroid Build Coastguard Worker 112*cda5da8dSAndroid Build Coastguard Workerclass _WindowsFlavour(_Flavour): 113*cda5da8dSAndroid Build Coastguard Worker # Reference for Windows paths can be found at 114*cda5da8dSAndroid Build Coastguard Worker # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx 115*cda5da8dSAndroid Build Coastguard Worker 116*cda5da8dSAndroid Build Coastguard Worker sep = '\\' 117*cda5da8dSAndroid Build Coastguard Worker altsep = '/' 118*cda5da8dSAndroid Build Coastguard Worker has_drv = True 119*cda5da8dSAndroid Build Coastguard Worker pathmod = ntpath 120*cda5da8dSAndroid Build Coastguard Worker 121*cda5da8dSAndroid Build Coastguard Worker is_supported = (os.name == 'nt') 122*cda5da8dSAndroid Build Coastguard Worker 123*cda5da8dSAndroid Build Coastguard Worker drive_letters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') 124*cda5da8dSAndroid Build Coastguard Worker ext_namespace_prefix = '\\\\?\\' 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Worker reserved_names = ( 127*cda5da8dSAndroid Build Coastguard Worker {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | 128*cda5da8dSAndroid Build Coastguard Worker {'COM%s' % c for c in '123456789\xb9\xb2\xb3'} | 129*cda5da8dSAndroid Build Coastguard Worker {'LPT%s' % c for c in '123456789\xb9\xb2\xb3'} 130*cda5da8dSAndroid Build Coastguard Worker ) 131*cda5da8dSAndroid Build Coastguard Worker 132*cda5da8dSAndroid Build Coastguard Worker # Interesting findings about extended paths: 133*cda5da8dSAndroid Build Coastguard Worker # * '\\?\c:\a' is an extended path, which bypasses normal Windows API 134*cda5da8dSAndroid Build Coastguard Worker # path processing. Thus relative paths are not resolved and slash is not 135*cda5da8dSAndroid Build Coastguard Worker # translated to backslash. It has the native NT path limit of 32767 136*cda5da8dSAndroid Build Coastguard Worker # characters, but a bit less after resolving device symbolic links, 137*cda5da8dSAndroid Build Coastguard Worker # such as '\??\C:' => '\Device\HarddiskVolume2'. 138*cda5da8dSAndroid Build Coastguard Worker # * '\\?\c:/a' looks for a device named 'C:/a' because slash is a 139*cda5da8dSAndroid Build Coastguard Worker # regular name character in the object namespace. 140*cda5da8dSAndroid Build Coastguard Worker # * '\\?\c:\foo/bar' is invalid because '/' is illegal in NT filesystems. 141*cda5da8dSAndroid Build Coastguard Worker # The only path separator at the filesystem level is backslash. 142*cda5da8dSAndroid Build Coastguard Worker # * '//?/c:\a' and '//?/c:/a' are effectively equivalent to '\\.\c:\a' and 143*cda5da8dSAndroid Build Coastguard Worker # thus limited to MAX_PATH. 144*cda5da8dSAndroid Build Coastguard Worker # * Prior to Windows 8, ANSI API bytes paths are limited to MAX_PATH, 145*cda5da8dSAndroid Build Coastguard Worker # even with the '\\?\' prefix. 146*cda5da8dSAndroid Build Coastguard Worker 147*cda5da8dSAndroid Build Coastguard Worker def splitroot(self, part, sep=sep): 148*cda5da8dSAndroid Build Coastguard Worker first = part[0:1] 149*cda5da8dSAndroid Build Coastguard Worker second = part[1:2] 150*cda5da8dSAndroid Build Coastguard Worker if (second == sep and first == sep): 151*cda5da8dSAndroid Build Coastguard Worker # XXX extended paths should also disable the collapsing of "." 152*cda5da8dSAndroid Build Coastguard Worker # components (according to MSDN docs). 153*cda5da8dSAndroid Build Coastguard Worker prefix, part = self._split_extended_path(part) 154*cda5da8dSAndroid Build Coastguard Worker first = part[0:1] 155*cda5da8dSAndroid Build Coastguard Worker second = part[1:2] 156*cda5da8dSAndroid Build Coastguard Worker else: 157*cda5da8dSAndroid Build Coastguard Worker prefix = '' 158*cda5da8dSAndroid Build Coastguard Worker third = part[2:3] 159*cda5da8dSAndroid Build Coastguard Worker if (second == sep and first == sep and third != sep): 160*cda5da8dSAndroid Build Coastguard Worker # is a UNC path: 161*cda5da8dSAndroid Build Coastguard Worker # vvvvvvvvvvvvvvvvvvvvv root 162*cda5da8dSAndroid Build Coastguard Worker # \\machine\mountpoint\directory\etc\... 163*cda5da8dSAndroid Build Coastguard Worker # directory ^^^^^^^^^^^^^^ 164*cda5da8dSAndroid Build Coastguard Worker index = part.find(sep, 2) 165*cda5da8dSAndroid Build Coastguard Worker if index != -1: 166*cda5da8dSAndroid Build Coastguard Worker index2 = part.find(sep, index + 1) 167*cda5da8dSAndroid Build Coastguard Worker # a UNC path can't have two slashes in a row 168*cda5da8dSAndroid Build Coastguard Worker # (after the initial two) 169*cda5da8dSAndroid Build Coastguard Worker if index2 != index + 1: 170*cda5da8dSAndroid Build Coastguard Worker if index2 == -1: 171*cda5da8dSAndroid Build Coastguard Worker index2 = len(part) 172*cda5da8dSAndroid Build Coastguard Worker if prefix: 173*cda5da8dSAndroid Build Coastguard Worker return prefix + part[1:index2], sep, part[index2+1:] 174*cda5da8dSAndroid Build Coastguard Worker else: 175*cda5da8dSAndroid Build Coastguard Worker return part[:index2], sep, part[index2+1:] 176*cda5da8dSAndroid Build Coastguard Worker drv = root = '' 177*cda5da8dSAndroid Build Coastguard Worker if second == ':' and first in self.drive_letters: 178*cda5da8dSAndroid Build Coastguard Worker drv = part[:2] 179*cda5da8dSAndroid Build Coastguard Worker part = part[2:] 180*cda5da8dSAndroid Build Coastguard Worker first = third 181*cda5da8dSAndroid Build Coastguard Worker if first == sep: 182*cda5da8dSAndroid Build Coastguard Worker root = first 183*cda5da8dSAndroid Build Coastguard Worker part = part.lstrip(sep) 184*cda5da8dSAndroid Build Coastguard Worker return prefix + drv, root, part 185*cda5da8dSAndroid Build Coastguard Worker 186*cda5da8dSAndroid Build Coastguard Worker def casefold(self, s): 187*cda5da8dSAndroid Build Coastguard Worker return s.lower() 188*cda5da8dSAndroid Build Coastguard Worker 189*cda5da8dSAndroid Build Coastguard Worker def casefold_parts(self, parts): 190*cda5da8dSAndroid Build Coastguard Worker return [p.lower() for p in parts] 191*cda5da8dSAndroid Build Coastguard Worker 192*cda5da8dSAndroid Build Coastguard Worker def compile_pattern(self, pattern): 193*cda5da8dSAndroid Build Coastguard Worker return re.compile(fnmatch.translate(pattern), re.IGNORECASE).fullmatch 194*cda5da8dSAndroid Build Coastguard Worker 195*cda5da8dSAndroid Build Coastguard Worker def _split_extended_path(self, s, ext_prefix=ext_namespace_prefix): 196*cda5da8dSAndroid Build Coastguard Worker prefix = '' 197*cda5da8dSAndroid Build Coastguard Worker if s.startswith(ext_prefix): 198*cda5da8dSAndroid Build Coastguard Worker prefix = s[:4] 199*cda5da8dSAndroid Build Coastguard Worker s = s[4:] 200*cda5da8dSAndroid Build Coastguard Worker if s.startswith('UNC\\'): 201*cda5da8dSAndroid Build Coastguard Worker prefix += s[:3] 202*cda5da8dSAndroid Build Coastguard Worker s = '\\' + s[3:] 203*cda5da8dSAndroid Build Coastguard Worker return prefix, s 204*cda5da8dSAndroid Build Coastguard Worker 205*cda5da8dSAndroid Build Coastguard Worker def is_reserved(self, parts): 206*cda5da8dSAndroid Build Coastguard Worker # NOTE: the rules for reserved names seem somewhat complicated 207*cda5da8dSAndroid Build Coastguard Worker # (e.g. r"..\NUL" is reserved but not r"foo\NUL" if "foo" does not 208*cda5da8dSAndroid Build Coastguard Worker # exist). We err on the side of caution and return True for paths 209*cda5da8dSAndroid Build Coastguard Worker # which are not considered reserved by Windows. 210*cda5da8dSAndroid Build Coastguard Worker if not parts: 211*cda5da8dSAndroid Build Coastguard Worker return False 212*cda5da8dSAndroid Build Coastguard Worker if parts[0].startswith('\\\\'): 213*cda5da8dSAndroid Build Coastguard Worker # UNC paths are never reserved 214*cda5da8dSAndroid Build Coastguard Worker return False 215*cda5da8dSAndroid Build Coastguard Worker name = parts[-1].partition('.')[0].partition(':')[0].rstrip(' ') 216*cda5da8dSAndroid Build Coastguard Worker return name.upper() in self.reserved_names 217*cda5da8dSAndroid Build Coastguard Worker 218*cda5da8dSAndroid Build Coastguard Worker def make_uri(self, path): 219*cda5da8dSAndroid Build Coastguard Worker # Under Windows, file URIs use the UTF-8 encoding. 220*cda5da8dSAndroid Build Coastguard Worker drive = path.drive 221*cda5da8dSAndroid Build Coastguard Worker if len(drive) == 2 and drive[1] == ':': 222*cda5da8dSAndroid Build Coastguard Worker # It's a path on a local drive => 'file:///c:/a/b' 223*cda5da8dSAndroid Build Coastguard Worker rest = path.as_posix()[2:].lstrip('/') 224*cda5da8dSAndroid Build Coastguard Worker return 'file:///%s/%s' % ( 225*cda5da8dSAndroid Build Coastguard Worker drive, urlquote_from_bytes(rest.encode('utf-8'))) 226*cda5da8dSAndroid Build Coastguard Worker else: 227*cda5da8dSAndroid Build Coastguard Worker # It's a path on a network drive => 'file://host/share/a/b' 228*cda5da8dSAndroid Build Coastguard Worker return 'file:' + urlquote_from_bytes(path.as_posix().encode('utf-8')) 229*cda5da8dSAndroid Build Coastguard Worker 230*cda5da8dSAndroid Build Coastguard Worker 231*cda5da8dSAndroid Build Coastguard Workerclass _PosixFlavour(_Flavour): 232*cda5da8dSAndroid Build Coastguard Worker sep = '/' 233*cda5da8dSAndroid Build Coastguard Worker altsep = '' 234*cda5da8dSAndroid Build Coastguard Worker has_drv = False 235*cda5da8dSAndroid Build Coastguard Worker pathmod = posixpath 236*cda5da8dSAndroid Build Coastguard Worker 237*cda5da8dSAndroid Build Coastguard Worker is_supported = (os.name != 'nt') 238*cda5da8dSAndroid Build Coastguard Worker 239*cda5da8dSAndroid Build Coastguard Worker def splitroot(self, part, sep=sep): 240*cda5da8dSAndroid Build Coastguard Worker if part and part[0] == sep: 241*cda5da8dSAndroid Build Coastguard Worker stripped_part = part.lstrip(sep) 242*cda5da8dSAndroid Build Coastguard Worker # According to POSIX path resolution: 243*cda5da8dSAndroid Build Coastguard Worker # http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11 244*cda5da8dSAndroid Build Coastguard Worker # "A pathname that begins with two successive slashes may be 245*cda5da8dSAndroid Build Coastguard Worker # interpreted in an implementation-defined manner, although more 246*cda5da8dSAndroid Build Coastguard Worker # than two leading slashes shall be treated as a single slash". 247*cda5da8dSAndroid Build Coastguard Worker if len(part) - len(stripped_part) == 2: 248*cda5da8dSAndroid Build Coastguard Worker return '', sep * 2, stripped_part 249*cda5da8dSAndroid Build Coastguard Worker else: 250*cda5da8dSAndroid Build Coastguard Worker return '', sep, stripped_part 251*cda5da8dSAndroid Build Coastguard Worker else: 252*cda5da8dSAndroid Build Coastguard Worker return '', '', part 253*cda5da8dSAndroid Build Coastguard Worker 254*cda5da8dSAndroid Build Coastguard Worker def casefold(self, s): 255*cda5da8dSAndroid Build Coastguard Worker return s 256*cda5da8dSAndroid Build Coastguard Worker 257*cda5da8dSAndroid Build Coastguard Worker def casefold_parts(self, parts): 258*cda5da8dSAndroid Build Coastguard Worker return parts 259*cda5da8dSAndroid Build Coastguard Worker 260*cda5da8dSAndroid Build Coastguard Worker def compile_pattern(self, pattern): 261*cda5da8dSAndroid Build Coastguard Worker return re.compile(fnmatch.translate(pattern)).fullmatch 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Worker def is_reserved(self, parts): 264*cda5da8dSAndroid Build Coastguard Worker return False 265*cda5da8dSAndroid Build Coastguard Worker 266*cda5da8dSAndroid Build Coastguard Worker def make_uri(self, path): 267*cda5da8dSAndroid Build Coastguard Worker # We represent the path using the local filesystem encoding, 268*cda5da8dSAndroid Build Coastguard Worker # for portability to other applications. 269*cda5da8dSAndroid Build Coastguard Worker bpath = bytes(path) 270*cda5da8dSAndroid Build Coastguard Worker return 'file://' + urlquote_from_bytes(bpath) 271*cda5da8dSAndroid Build Coastguard Worker 272*cda5da8dSAndroid Build Coastguard Worker 273*cda5da8dSAndroid Build Coastguard Worker_windows_flavour = _WindowsFlavour() 274*cda5da8dSAndroid Build Coastguard Worker_posix_flavour = _PosixFlavour() 275*cda5da8dSAndroid Build Coastguard Worker 276*cda5da8dSAndroid Build Coastguard Worker 277*cda5da8dSAndroid Build Coastguard Worker# 278*cda5da8dSAndroid Build Coastguard Worker# Globbing helpers 279*cda5da8dSAndroid Build Coastguard Worker# 280*cda5da8dSAndroid Build Coastguard Worker 281*cda5da8dSAndroid Build Coastguard Workerdef _make_selector(pattern_parts, flavour): 282*cda5da8dSAndroid Build Coastguard Worker pat = pattern_parts[0] 283*cda5da8dSAndroid Build Coastguard Worker child_parts = pattern_parts[1:] 284*cda5da8dSAndroid Build Coastguard Worker if not pat: 285*cda5da8dSAndroid Build Coastguard Worker return _TerminatingSelector() 286*cda5da8dSAndroid Build Coastguard Worker if pat == '**': 287*cda5da8dSAndroid Build Coastguard Worker cls = _RecursiveWildcardSelector 288*cda5da8dSAndroid Build Coastguard Worker elif '**' in pat: 289*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid pattern: '**' can only be an entire path component") 290*cda5da8dSAndroid Build Coastguard Worker elif _is_wildcard_pattern(pat): 291*cda5da8dSAndroid Build Coastguard Worker cls = _WildcardSelector 292*cda5da8dSAndroid Build Coastguard Worker else: 293*cda5da8dSAndroid Build Coastguard Worker cls = _PreciseSelector 294*cda5da8dSAndroid Build Coastguard Worker return cls(pat, child_parts, flavour) 295*cda5da8dSAndroid Build Coastguard Worker 296*cda5da8dSAndroid Build Coastguard Workerif hasattr(functools, "lru_cache"): 297*cda5da8dSAndroid Build Coastguard Worker _make_selector = functools.lru_cache()(_make_selector) 298*cda5da8dSAndroid Build Coastguard Worker 299*cda5da8dSAndroid Build Coastguard Worker 300*cda5da8dSAndroid Build Coastguard Workerclass _Selector: 301*cda5da8dSAndroid Build Coastguard Worker """A selector matches a specific glob pattern part against the children 302*cda5da8dSAndroid Build Coastguard Worker of a given path.""" 303*cda5da8dSAndroid Build Coastguard Worker 304*cda5da8dSAndroid Build Coastguard Worker def __init__(self, child_parts, flavour): 305*cda5da8dSAndroid Build Coastguard Worker self.child_parts = child_parts 306*cda5da8dSAndroid Build Coastguard Worker if child_parts: 307*cda5da8dSAndroid Build Coastguard Worker self.successor = _make_selector(child_parts, flavour) 308*cda5da8dSAndroid Build Coastguard Worker self.dironly = True 309*cda5da8dSAndroid Build Coastguard Worker else: 310*cda5da8dSAndroid Build Coastguard Worker self.successor = _TerminatingSelector() 311*cda5da8dSAndroid Build Coastguard Worker self.dironly = False 312*cda5da8dSAndroid Build Coastguard Worker 313*cda5da8dSAndroid Build Coastguard Worker def select_from(self, parent_path): 314*cda5da8dSAndroid Build Coastguard Worker """Iterate over all child paths of `parent_path` matched by this 315*cda5da8dSAndroid Build Coastguard Worker selector. This can contain parent_path itself.""" 316*cda5da8dSAndroid Build Coastguard Worker path_cls = type(parent_path) 317*cda5da8dSAndroid Build Coastguard Worker is_dir = path_cls.is_dir 318*cda5da8dSAndroid Build Coastguard Worker exists = path_cls.exists 319*cda5da8dSAndroid Build Coastguard Worker scandir = path_cls._scandir 320*cda5da8dSAndroid Build Coastguard Worker if not is_dir(parent_path): 321*cda5da8dSAndroid Build Coastguard Worker return iter([]) 322*cda5da8dSAndroid Build Coastguard Worker return self._select_from(parent_path, is_dir, exists, scandir) 323*cda5da8dSAndroid Build Coastguard Worker 324*cda5da8dSAndroid Build Coastguard Worker 325*cda5da8dSAndroid Build Coastguard Workerclass _TerminatingSelector: 326*cda5da8dSAndroid Build Coastguard Worker 327*cda5da8dSAndroid Build Coastguard Worker def _select_from(self, parent_path, is_dir, exists, scandir): 328*cda5da8dSAndroid Build Coastguard Worker yield parent_path 329*cda5da8dSAndroid Build Coastguard Worker 330*cda5da8dSAndroid Build Coastguard Worker 331*cda5da8dSAndroid Build Coastguard Workerclass _PreciseSelector(_Selector): 332*cda5da8dSAndroid Build Coastguard Worker 333*cda5da8dSAndroid Build Coastguard Worker def __init__(self, name, child_parts, flavour): 334*cda5da8dSAndroid Build Coastguard Worker self.name = name 335*cda5da8dSAndroid Build Coastguard Worker _Selector.__init__(self, child_parts, flavour) 336*cda5da8dSAndroid Build Coastguard Worker 337*cda5da8dSAndroid Build Coastguard Worker def _select_from(self, parent_path, is_dir, exists, scandir): 338*cda5da8dSAndroid Build Coastguard Worker try: 339*cda5da8dSAndroid Build Coastguard Worker path = parent_path._make_child_relpath(self.name) 340*cda5da8dSAndroid Build Coastguard Worker if (is_dir if self.dironly else exists)(path): 341*cda5da8dSAndroid Build Coastguard Worker for p in self.successor._select_from(path, is_dir, exists, scandir): 342*cda5da8dSAndroid Build Coastguard Worker yield p 343*cda5da8dSAndroid Build Coastguard Worker except PermissionError: 344*cda5da8dSAndroid Build Coastguard Worker return 345*cda5da8dSAndroid Build Coastguard Worker 346*cda5da8dSAndroid Build Coastguard Worker 347*cda5da8dSAndroid Build Coastguard Workerclass _WildcardSelector(_Selector): 348*cda5da8dSAndroid Build Coastguard Worker 349*cda5da8dSAndroid Build Coastguard Worker def __init__(self, pat, child_parts, flavour): 350*cda5da8dSAndroid Build Coastguard Worker self.match = flavour.compile_pattern(pat) 351*cda5da8dSAndroid Build Coastguard Worker _Selector.__init__(self, child_parts, flavour) 352*cda5da8dSAndroid Build Coastguard Worker 353*cda5da8dSAndroid Build Coastguard Worker def _select_from(self, parent_path, is_dir, exists, scandir): 354*cda5da8dSAndroid Build Coastguard Worker try: 355*cda5da8dSAndroid Build Coastguard Worker with scandir(parent_path) as scandir_it: 356*cda5da8dSAndroid Build Coastguard Worker entries = list(scandir_it) 357*cda5da8dSAndroid Build Coastguard Worker for entry in entries: 358*cda5da8dSAndroid Build Coastguard Worker if self.dironly: 359*cda5da8dSAndroid Build Coastguard Worker try: 360*cda5da8dSAndroid Build Coastguard Worker # "entry.is_dir()" can raise PermissionError 361*cda5da8dSAndroid Build Coastguard Worker # in some cases (see bpo-38894), which is not 362*cda5da8dSAndroid Build Coastguard Worker # among the errors ignored by _ignore_error() 363*cda5da8dSAndroid Build Coastguard Worker if not entry.is_dir(): 364*cda5da8dSAndroid Build Coastguard Worker continue 365*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 366*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 367*cda5da8dSAndroid Build Coastguard Worker raise 368*cda5da8dSAndroid Build Coastguard Worker continue 369*cda5da8dSAndroid Build Coastguard Worker name = entry.name 370*cda5da8dSAndroid Build Coastguard Worker if self.match(name): 371*cda5da8dSAndroid Build Coastguard Worker path = parent_path._make_child_relpath(name) 372*cda5da8dSAndroid Build Coastguard Worker for p in self.successor._select_from(path, is_dir, exists, scandir): 373*cda5da8dSAndroid Build Coastguard Worker yield p 374*cda5da8dSAndroid Build Coastguard Worker except PermissionError: 375*cda5da8dSAndroid Build Coastguard Worker return 376*cda5da8dSAndroid Build Coastguard Worker 377*cda5da8dSAndroid Build Coastguard Worker 378*cda5da8dSAndroid Build Coastguard Workerclass _RecursiveWildcardSelector(_Selector): 379*cda5da8dSAndroid Build Coastguard Worker 380*cda5da8dSAndroid Build Coastguard Worker def __init__(self, pat, child_parts, flavour): 381*cda5da8dSAndroid Build Coastguard Worker _Selector.__init__(self, child_parts, flavour) 382*cda5da8dSAndroid Build Coastguard Worker 383*cda5da8dSAndroid Build Coastguard Worker def _iterate_directories(self, parent_path, is_dir, scandir): 384*cda5da8dSAndroid Build Coastguard Worker yield parent_path 385*cda5da8dSAndroid Build Coastguard Worker try: 386*cda5da8dSAndroid Build Coastguard Worker with scandir(parent_path) as scandir_it: 387*cda5da8dSAndroid Build Coastguard Worker entries = list(scandir_it) 388*cda5da8dSAndroid Build Coastguard Worker for entry in entries: 389*cda5da8dSAndroid Build Coastguard Worker entry_is_dir = False 390*cda5da8dSAndroid Build Coastguard Worker try: 391*cda5da8dSAndroid Build Coastguard Worker entry_is_dir = entry.is_dir(follow_symlinks=False) 392*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 393*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 394*cda5da8dSAndroid Build Coastguard Worker raise 395*cda5da8dSAndroid Build Coastguard Worker if entry_is_dir: 396*cda5da8dSAndroid Build Coastguard Worker path = parent_path._make_child_relpath(entry.name) 397*cda5da8dSAndroid Build Coastguard Worker for p in self._iterate_directories(path, is_dir, scandir): 398*cda5da8dSAndroid Build Coastguard Worker yield p 399*cda5da8dSAndroid Build Coastguard Worker except PermissionError: 400*cda5da8dSAndroid Build Coastguard Worker return 401*cda5da8dSAndroid Build Coastguard Worker 402*cda5da8dSAndroid Build Coastguard Worker def _select_from(self, parent_path, is_dir, exists, scandir): 403*cda5da8dSAndroid Build Coastguard Worker try: 404*cda5da8dSAndroid Build Coastguard Worker yielded = set() 405*cda5da8dSAndroid Build Coastguard Worker try: 406*cda5da8dSAndroid Build Coastguard Worker successor_select = self.successor._select_from 407*cda5da8dSAndroid Build Coastguard Worker for starting_point in self._iterate_directories(parent_path, is_dir, scandir): 408*cda5da8dSAndroid Build Coastguard Worker for p in successor_select(starting_point, is_dir, exists, scandir): 409*cda5da8dSAndroid Build Coastguard Worker if p not in yielded: 410*cda5da8dSAndroid Build Coastguard Worker yield p 411*cda5da8dSAndroid Build Coastguard Worker yielded.add(p) 412*cda5da8dSAndroid Build Coastguard Worker finally: 413*cda5da8dSAndroid Build Coastguard Worker yielded.clear() 414*cda5da8dSAndroid Build Coastguard Worker except PermissionError: 415*cda5da8dSAndroid Build Coastguard Worker return 416*cda5da8dSAndroid Build Coastguard Worker 417*cda5da8dSAndroid Build Coastguard Worker 418*cda5da8dSAndroid Build Coastguard Worker# 419*cda5da8dSAndroid Build Coastguard Worker# Public API 420*cda5da8dSAndroid Build Coastguard Worker# 421*cda5da8dSAndroid Build Coastguard Worker 422*cda5da8dSAndroid Build Coastguard Workerclass _PathParents(Sequence): 423*cda5da8dSAndroid Build Coastguard Worker """This object provides sequence-like access to the logical ancestors 424*cda5da8dSAndroid Build Coastguard Worker of a path. Don't try to construct it yourself.""" 425*cda5da8dSAndroid Build Coastguard Worker __slots__ = ('_pathcls', '_drv', '_root', '_parts') 426*cda5da8dSAndroid Build Coastguard Worker 427*cda5da8dSAndroid Build Coastguard Worker def __init__(self, path): 428*cda5da8dSAndroid Build Coastguard Worker # We don't store the instance to avoid reference cycles 429*cda5da8dSAndroid Build Coastguard Worker self._pathcls = type(path) 430*cda5da8dSAndroid Build Coastguard Worker self._drv = path._drv 431*cda5da8dSAndroid Build Coastguard Worker self._root = path._root 432*cda5da8dSAndroid Build Coastguard Worker self._parts = path._parts 433*cda5da8dSAndroid Build Coastguard Worker 434*cda5da8dSAndroid Build Coastguard Worker def __len__(self): 435*cda5da8dSAndroid Build Coastguard Worker if self._drv or self._root: 436*cda5da8dSAndroid Build Coastguard Worker return len(self._parts) - 1 437*cda5da8dSAndroid Build Coastguard Worker else: 438*cda5da8dSAndroid Build Coastguard Worker return len(self._parts) 439*cda5da8dSAndroid Build Coastguard Worker 440*cda5da8dSAndroid Build Coastguard Worker def __getitem__(self, idx): 441*cda5da8dSAndroid Build Coastguard Worker if isinstance(idx, slice): 442*cda5da8dSAndroid Build Coastguard Worker return tuple(self[i] for i in range(*idx.indices(len(self)))) 443*cda5da8dSAndroid Build Coastguard Worker 444*cda5da8dSAndroid Build Coastguard Worker if idx >= len(self) or idx < -len(self): 445*cda5da8dSAndroid Build Coastguard Worker raise IndexError(idx) 446*cda5da8dSAndroid Build Coastguard Worker if idx < 0: 447*cda5da8dSAndroid Build Coastguard Worker idx += len(self) 448*cda5da8dSAndroid Build Coastguard Worker return self._pathcls._from_parsed_parts(self._drv, self._root, 449*cda5da8dSAndroid Build Coastguard Worker self._parts[:-idx - 1]) 450*cda5da8dSAndroid Build Coastguard Worker 451*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 452*cda5da8dSAndroid Build Coastguard Worker return "<{}.parents>".format(self._pathcls.__name__) 453*cda5da8dSAndroid Build Coastguard Worker 454*cda5da8dSAndroid Build Coastguard Worker 455*cda5da8dSAndroid Build Coastguard Workerclass PurePath(object): 456*cda5da8dSAndroid Build Coastguard Worker """Base class for manipulating paths without I/O. 457*cda5da8dSAndroid Build Coastguard Worker 458*cda5da8dSAndroid Build Coastguard Worker PurePath represents a filesystem path and offers operations which 459*cda5da8dSAndroid Build Coastguard Worker don't imply any actual filesystem I/O. Depending on your system, 460*cda5da8dSAndroid Build Coastguard Worker instantiating a PurePath will return either a PurePosixPath or a 461*cda5da8dSAndroid Build Coastguard Worker PureWindowsPath object. You can also instantiate either of these classes 462*cda5da8dSAndroid Build Coastguard Worker directly, regardless of your system. 463*cda5da8dSAndroid Build Coastguard Worker """ 464*cda5da8dSAndroid Build Coastguard Worker __slots__ = ( 465*cda5da8dSAndroid Build Coastguard Worker '_drv', '_root', '_parts', 466*cda5da8dSAndroid Build Coastguard Worker '_str', '_hash', '_pparts', '_cached_cparts', 467*cda5da8dSAndroid Build Coastguard Worker ) 468*cda5da8dSAndroid Build Coastguard Worker 469*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, *args): 470*cda5da8dSAndroid Build Coastguard Worker """Construct a PurePath from one or several strings and or existing 471*cda5da8dSAndroid Build Coastguard Worker PurePath objects. The strings and path objects are combined so as 472*cda5da8dSAndroid Build Coastguard Worker to yield a canonicalized path, which is incorporated into the 473*cda5da8dSAndroid Build Coastguard Worker new PurePath object. 474*cda5da8dSAndroid Build Coastguard Worker """ 475*cda5da8dSAndroid Build Coastguard Worker if cls is PurePath: 476*cda5da8dSAndroid Build Coastguard Worker cls = PureWindowsPath if os.name == 'nt' else PurePosixPath 477*cda5da8dSAndroid Build Coastguard Worker return cls._from_parts(args) 478*cda5da8dSAndroid Build Coastguard Worker 479*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 480*cda5da8dSAndroid Build Coastguard Worker # Using the parts tuple helps share interned path parts 481*cda5da8dSAndroid Build Coastguard Worker # when pickling related paths. 482*cda5da8dSAndroid Build Coastguard Worker return (self.__class__, tuple(self._parts)) 483*cda5da8dSAndroid Build Coastguard Worker 484*cda5da8dSAndroid Build Coastguard Worker @classmethod 485*cda5da8dSAndroid Build Coastguard Worker def _parse_args(cls, args): 486*cda5da8dSAndroid Build Coastguard Worker # This is useful when you don't want to create an instance, just 487*cda5da8dSAndroid Build Coastguard Worker # canonicalize some constructor arguments. 488*cda5da8dSAndroid Build Coastguard Worker parts = [] 489*cda5da8dSAndroid Build Coastguard Worker for a in args: 490*cda5da8dSAndroid Build Coastguard Worker if isinstance(a, PurePath): 491*cda5da8dSAndroid Build Coastguard Worker parts += a._parts 492*cda5da8dSAndroid Build Coastguard Worker else: 493*cda5da8dSAndroid Build Coastguard Worker a = os.fspath(a) 494*cda5da8dSAndroid Build Coastguard Worker if isinstance(a, str): 495*cda5da8dSAndroid Build Coastguard Worker # Force-cast str subclasses to str (issue #21127) 496*cda5da8dSAndroid Build Coastguard Worker parts.append(str(a)) 497*cda5da8dSAndroid Build Coastguard Worker else: 498*cda5da8dSAndroid Build Coastguard Worker raise TypeError( 499*cda5da8dSAndroid Build Coastguard Worker "argument should be a str object or an os.PathLike " 500*cda5da8dSAndroid Build Coastguard Worker "object returning str, not %r" 501*cda5da8dSAndroid Build Coastguard Worker % type(a)) 502*cda5da8dSAndroid Build Coastguard Worker return cls._flavour.parse_parts(parts) 503*cda5da8dSAndroid Build Coastguard Worker 504*cda5da8dSAndroid Build Coastguard Worker @classmethod 505*cda5da8dSAndroid Build Coastguard Worker def _from_parts(cls, args): 506*cda5da8dSAndroid Build Coastguard Worker # We need to call _parse_args on the instance, so as to get the 507*cda5da8dSAndroid Build Coastguard Worker # right flavour. 508*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 509*cda5da8dSAndroid Build Coastguard Worker drv, root, parts = self._parse_args(args) 510*cda5da8dSAndroid Build Coastguard Worker self._drv = drv 511*cda5da8dSAndroid Build Coastguard Worker self._root = root 512*cda5da8dSAndroid Build Coastguard Worker self._parts = parts 513*cda5da8dSAndroid Build Coastguard Worker return self 514*cda5da8dSAndroid Build Coastguard Worker 515*cda5da8dSAndroid Build Coastguard Worker @classmethod 516*cda5da8dSAndroid Build Coastguard Worker def _from_parsed_parts(cls, drv, root, parts): 517*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 518*cda5da8dSAndroid Build Coastguard Worker self._drv = drv 519*cda5da8dSAndroid Build Coastguard Worker self._root = root 520*cda5da8dSAndroid Build Coastguard Worker self._parts = parts 521*cda5da8dSAndroid Build Coastguard Worker return self 522*cda5da8dSAndroid Build Coastguard Worker 523*cda5da8dSAndroid Build Coastguard Worker @classmethod 524*cda5da8dSAndroid Build Coastguard Worker def _format_parsed_parts(cls, drv, root, parts): 525*cda5da8dSAndroid Build Coastguard Worker if drv or root: 526*cda5da8dSAndroid Build Coastguard Worker return drv + root + cls._flavour.join(parts[1:]) 527*cda5da8dSAndroid Build Coastguard Worker else: 528*cda5da8dSAndroid Build Coastguard Worker return cls._flavour.join(parts) 529*cda5da8dSAndroid Build Coastguard Worker 530*cda5da8dSAndroid Build Coastguard Worker def _make_child(self, args): 531*cda5da8dSAndroid Build Coastguard Worker drv, root, parts = self._parse_args(args) 532*cda5da8dSAndroid Build Coastguard Worker drv, root, parts = self._flavour.join_parsed_parts( 533*cda5da8dSAndroid Build Coastguard Worker self._drv, self._root, self._parts, drv, root, parts) 534*cda5da8dSAndroid Build Coastguard Worker return self._from_parsed_parts(drv, root, parts) 535*cda5da8dSAndroid Build Coastguard Worker 536*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 537*cda5da8dSAndroid Build Coastguard Worker """Return the string representation of the path, suitable for 538*cda5da8dSAndroid Build Coastguard Worker passing to system calls.""" 539*cda5da8dSAndroid Build Coastguard Worker try: 540*cda5da8dSAndroid Build Coastguard Worker return self._str 541*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 542*cda5da8dSAndroid Build Coastguard Worker self._str = self._format_parsed_parts(self._drv, self._root, 543*cda5da8dSAndroid Build Coastguard Worker self._parts) or '.' 544*cda5da8dSAndroid Build Coastguard Worker return self._str 545*cda5da8dSAndroid Build Coastguard Worker 546*cda5da8dSAndroid Build Coastguard Worker def __fspath__(self): 547*cda5da8dSAndroid Build Coastguard Worker return str(self) 548*cda5da8dSAndroid Build Coastguard Worker 549*cda5da8dSAndroid Build Coastguard Worker def as_posix(self): 550*cda5da8dSAndroid Build Coastguard Worker """Return the string representation of the path with forward (/) 551*cda5da8dSAndroid Build Coastguard Worker slashes.""" 552*cda5da8dSAndroid Build Coastguard Worker f = self._flavour 553*cda5da8dSAndroid Build Coastguard Worker return str(self).replace(f.sep, '/') 554*cda5da8dSAndroid Build Coastguard Worker 555*cda5da8dSAndroid Build Coastguard Worker def __bytes__(self): 556*cda5da8dSAndroid Build Coastguard Worker """Return the bytes representation of the path. This is only 557*cda5da8dSAndroid Build Coastguard Worker recommended to use under Unix.""" 558*cda5da8dSAndroid Build Coastguard Worker return os.fsencode(self) 559*cda5da8dSAndroid Build Coastguard Worker 560*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 561*cda5da8dSAndroid Build Coastguard Worker return "{}({!r})".format(self.__class__.__name__, self.as_posix()) 562*cda5da8dSAndroid Build Coastguard Worker 563*cda5da8dSAndroid Build Coastguard Worker def as_uri(self): 564*cda5da8dSAndroid Build Coastguard Worker """Return the path as a 'file' URI.""" 565*cda5da8dSAndroid Build Coastguard Worker if not self.is_absolute(): 566*cda5da8dSAndroid Build Coastguard Worker raise ValueError("relative path can't be expressed as a file URI") 567*cda5da8dSAndroid Build Coastguard Worker return self._flavour.make_uri(self) 568*cda5da8dSAndroid Build Coastguard Worker 569*cda5da8dSAndroid Build Coastguard Worker @property 570*cda5da8dSAndroid Build Coastguard Worker def _cparts(self): 571*cda5da8dSAndroid Build Coastguard Worker # Cached casefolded parts, for hashing and comparison 572*cda5da8dSAndroid Build Coastguard Worker try: 573*cda5da8dSAndroid Build Coastguard Worker return self._cached_cparts 574*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 575*cda5da8dSAndroid Build Coastguard Worker self._cached_cparts = self._flavour.casefold_parts(self._parts) 576*cda5da8dSAndroid Build Coastguard Worker return self._cached_cparts 577*cda5da8dSAndroid Build Coastguard Worker 578*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 579*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, PurePath): 580*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 581*cda5da8dSAndroid Build Coastguard Worker return self._cparts == other._cparts and self._flavour is other._flavour 582*cda5da8dSAndroid Build Coastguard Worker 583*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 584*cda5da8dSAndroid Build Coastguard Worker try: 585*cda5da8dSAndroid Build Coastguard Worker return self._hash 586*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 587*cda5da8dSAndroid Build Coastguard Worker self._hash = hash(tuple(self._cparts)) 588*cda5da8dSAndroid Build Coastguard Worker return self._hash 589*cda5da8dSAndroid Build Coastguard Worker 590*cda5da8dSAndroid Build Coastguard Worker def __lt__(self, other): 591*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, PurePath) or self._flavour is not other._flavour: 592*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 593*cda5da8dSAndroid Build Coastguard Worker return self._cparts < other._cparts 594*cda5da8dSAndroid Build Coastguard Worker 595*cda5da8dSAndroid Build Coastguard Worker def __le__(self, other): 596*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, PurePath) or self._flavour is not other._flavour: 597*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 598*cda5da8dSAndroid Build Coastguard Worker return self._cparts <= other._cparts 599*cda5da8dSAndroid Build Coastguard Worker 600*cda5da8dSAndroid Build Coastguard Worker def __gt__(self, other): 601*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, PurePath) or self._flavour is not other._flavour: 602*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 603*cda5da8dSAndroid Build Coastguard Worker return self._cparts > other._cparts 604*cda5da8dSAndroid Build Coastguard Worker 605*cda5da8dSAndroid Build Coastguard Worker def __ge__(self, other): 606*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, PurePath) or self._flavour is not other._flavour: 607*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 608*cda5da8dSAndroid Build Coastguard Worker return self._cparts >= other._cparts 609*cda5da8dSAndroid Build Coastguard Worker 610*cda5da8dSAndroid Build Coastguard Worker drive = property(attrgetter('_drv'), 611*cda5da8dSAndroid Build Coastguard Worker doc="""The drive prefix (letter or UNC path), if any.""") 612*cda5da8dSAndroid Build Coastguard Worker 613*cda5da8dSAndroid Build Coastguard Worker root = property(attrgetter('_root'), 614*cda5da8dSAndroid Build Coastguard Worker doc="""The root of the path, if any.""") 615*cda5da8dSAndroid Build Coastguard Worker 616*cda5da8dSAndroid Build Coastguard Worker @property 617*cda5da8dSAndroid Build Coastguard Worker def anchor(self): 618*cda5da8dSAndroid Build Coastguard Worker """The concatenation of the drive and root, or ''.""" 619*cda5da8dSAndroid Build Coastguard Worker anchor = self._drv + self._root 620*cda5da8dSAndroid Build Coastguard Worker return anchor 621*cda5da8dSAndroid Build Coastguard Worker 622*cda5da8dSAndroid Build Coastguard Worker @property 623*cda5da8dSAndroid Build Coastguard Worker def name(self): 624*cda5da8dSAndroid Build Coastguard Worker """The final path component, if any.""" 625*cda5da8dSAndroid Build Coastguard Worker parts = self._parts 626*cda5da8dSAndroid Build Coastguard Worker if len(parts) == (1 if (self._drv or self._root) else 0): 627*cda5da8dSAndroid Build Coastguard Worker return '' 628*cda5da8dSAndroid Build Coastguard Worker return parts[-1] 629*cda5da8dSAndroid Build Coastguard Worker 630*cda5da8dSAndroid Build Coastguard Worker @property 631*cda5da8dSAndroid Build Coastguard Worker def suffix(self): 632*cda5da8dSAndroid Build Coastguard Worker """ 633*cda5da8dSAndroid Build Coastguard Worker The final component's last suffix, if any. 634*cda5da8dSAndroid Build Coastguard Worker 635*cda5da8dSAndroid Build Coastguard Worker This includes the leading period. For example: '.txt' 636*cda5da8dSAndroid Build Coastguard Worker """ 637*cda5da8dSAndroid Build Coastguard Worker name = self.name 638*cda5da8dSAndroid Build Coastguard Worker i = name.rfind('.') 639*cda5da8dSAndroid Build Coastguard Worker if 0 < i < len(name) - 1: 640*cda5da8dSAndroid Build Coastguard Worker return name[i:] 641*cda5da8dSAndroid Build Coastguard Worker else: 642*cda5da8dSAndroid Build Coastguard Worker return '' 643*cda5da8dSAndroid Build Coastguard Worker 644*cda5da8dSAndroid Build Coastguard Worker @property 645*cda5da8dSAndroid Build Coastguard Worker def suffixes(self): 646*cda5da8dSAndroid Build Coastguard Worker """ 647*cda5da8dSAndroid Build Coastguard Worker A list of the final component's suffixes, if any. 648*cda5da8dSAndroid Build Coastguard Worker 649*cda5da8dSAndroid Build Coastguard Worker These include the leading periods. For example: ['.tar', '.gz'] 650*cda5da8dSAndroid Build Coastguard Worker """ 651*cda5da8dSAndroid Build Coastguard Worker name = self.name 652*cda5da8dSAndroid Build Coastguard Worker if name.endswith('.'): 653*cda5da8dSAndroid Build Coastguard Worker return [] 654*cda5da8dSAndroid Build Coastguard Worker name = name.lstrip('.') 655*cda5da8dSAndroid Build Coastguard Worker return ['.' + suffix for suffix in name.split('.')[1:]] 656*cda5da8dSAndroid Build Coastguard Worker 657*cda5da8dSAndroid Build Coastguard Worker @property 658*cda5da8dSAndroid Build Coastguard Worker def stem(self): 659*cda5da8dSAndroid Build Coastguard Worker """The final path component, minus its last suffix.""" 660*cda5da8dSAndroid Build Coastguard Worker name = self.name 661*cda5da8dSAndroid Build Coastguard Worker i = name.rfind('.') 662*cda5da8dSAndroid Build Coastguard Worker if 0 < i < len(name) - 1: 663*cda5da8dSAndroid Build Coastguard Worker return name[:i] 664*cda5da8dSAndroid Build Coastguard Worker else: 665*cda5da8dSAndroid Build Coastguard Worker return name 666*cda5da8dSAndroid Build Coastguard Worker 667*cda5da8dSAndroid Build Coastguard Worker def with_name(self, name): 668*cda5da8dSAndroid Build Coastguard Worker """Return a new path with the file name changed.""" 669*cda5da8dSAndroid Build Coastguard Worker if not self.name: 670*cda5da8dSAndroid Build Coastguard Worker raise ValueError("%r has an empty name" % (self,)) 671*cda5da8dSAndroid Build Coastguard Worker drv, root, parts = self._flavour.parse_parts((name,)) 672*cda5da8dSAndroid Build Coastguard Worker if (not name or name[-1] in [self._flavour.sep, self._flavour.altsep] 673*cda5da8dSAndroid Build Coastguard Worker or drv or root or len(parts) != 1): 674*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid name %r" % (name)) 675*cda5da8dSAndroid Build Coastguard Worker return self._from_parsed_parts(self._drv, self._root, 676*cda5da8dSAndroid Build Coastguard Worker self._parts[:-1] + [name]) 677*cda5da8dSAndroid Build Coastguard Worker 678*cda5da8dSAndroid Build Coastguard Worker def with_stem(self, stem): 679*cda5da8dSAndroid Build Coastguard Worker """Return a new path with the stem changed.""" 680*cda5da8dSAndroid Build Coastguard Worker return self.with_name(stem + self.suffix) 681*cda5da8dSAndroid Build Coastguard Worker 682*cda5da8dSAndroid Build Coastguard Worker def with_suffix(self, suffix): 683*cda5da8dSAndroid Build Coastguard Worker """Return a new path with the file suffix changed. If the path 684*cda5da8dSAndroid Build Coastguard Worker has no suffix, add given suffix. If the given suffix is an empty 685*cda5da8dSAndroid Build Coastguard Worker string, remove the suffix from the path. 686*cda5da8dSAndroid Build Coastguard Worker """ 687*cda5da8dSAndroid Build Coastguard Worker f = self._flavour 688*cda5da8dSAndroid Build Coastguard Worker if f.sep in suffix or f.altsep and f.altsep in suffix: 689*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid suffix %r" % (suffix,)) 690*cda5da8dSAndroid Build Coastguard Worker if suffix and not suffix.startswith('.') or suffix == '.': 691*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid suffix %r" % (suffix)) 692*cda5da8dSAndroid Build Coastguard Worker name = self.name 693*cda5da8dSAndroid Build Coastguard Worker if not name: 694*cda5da8dSAndroid Build Coastguard Worker raise ValueError("%r has an empty name" % (self,)) 695*cda5da8dSAndroid Build Coastguard Worker old_suffix = self.suffix 696*cda5da8dSAndroid Build Coastguard Worker if not old_suffix: 697*cda5da8dSAndroid Build Coastguard Worker name = name + suffix 698*cda5da8dSAndroid Build Coastguard Worker else: 699*cda5da8dSAndroid Build Coastguard Worker name = name[:-len(old_suffix)] + suffix 700*cda5da8dSAndroid Build Coastguard Worker return self._from_parsed_parts(self._drv, self._root, 701*cda5da8dSAndroid Build Coastguard Worker self._parts[:-1] + [name]) 702*cda5da8dSAndroid Build Coastguard Worker 703*cda5da8dSAndroid Build Coastguard Worker def relative_to(self, *other): 704*cda5da8dSAndroid Build Coastguard Worker """Return the relative path to another path identified by the passed 705*cda5da8dSAndroid Build Coastguard Worker arguments. If the operation is not possible (because this is not 706*cda5da8dSAndroid Build Coastguard Worker a subpath of the other path), raise ValueError. 707*cda5da8dSAndroid Build Coastguard Worker """ 708*cda5da8dSAndroid Build Coastguard Worker # For the purpose of this method, drive and root are considered 709*cda5da8dSAndroid Build Coastguard Worker # separate parts, i.e.: 710*cda5da8dSAndroid Build Coastguard Worker # Path('c:/').relative_to('c:') gives Path('/') 711*cda5da8dSAndroid Build Coastguard Worker # Path('c:/').relative_to('/') raise ValueError 712*cda5da8dSAndroid Build Coastguard Worker if not other: 713*cda5da8dSAndroid Build Coastguard Worker raise TypeError("need at least one argument") 714*cda5da8dSAndroid Build Coastguard Worker parts = self._parts 715*cda5da8dSAndroid Build Coastguard Worker drv = self._drv 716*cda5da8dSAndroid Build Coastguard Worker root = self._root 717*cda5da8dSAndroid Build Coastguard Worker if root: 718*cda5da8dSAndroid Build Coastguard Worker abs_parts = [drv, root] + parts[1:] 719*cda5da8dSAndroid Build Coastguard Worker else: 720*cda5da8dSAndroid Build Coastguard Worker abs_parts = parts 721*cda5da8dSAndroid Build Coastguard Worker to_drv, to_root, to_parts = self._parse_args(other) 722*cda5da8dSAndroid Build Coastguard Worker if to_root: 723*cda5da8dSAndroid Build Coastguard Worker to_abs_parts = [to_drv, to_root] + to_parts[1:] 724*cda5da8dSAndroid Build Coastguard Worker else: 725*cda5da8dSAndroid Build Coastguard Worker to_abs_parts = to_parts 726*cda5da8dSAndroid Build Coastguard Worker n = len(to_abs_parts) 727*cda5da8dSAndroid Build Coastguard Worker cf = self._flavour.casefold_parts 728*cda5da8dSAndroid Build Coastguard Worker if (root or drv) if n == 0 else cf(abs_parts[:n]) != cf(to_abs_parts): 729*cda5da8dSAndroid Build Coastguard Worker formatted = self._format_parsed_parts(to_drv, to_root, to_parts) 730*cda5da8dSAndroid Build Coastguard Worker raise ValueError("{!r} is not in the subpath of {!r}" 731*cda5da8dSAndroid Build Coastguard Worker " OR one path is relative and the other is absolute." 732*cda5da8dSAndroid Build Coastguard Worker .format(str(self), str(formatted))) 733*cda5da8dSAndroid Build Coastguard Worker return self._from_parsed_parts('', root if n == 1 else '', 734*cda5da8dSAndroid Build Coastguard Worker abs_parts[n:]) 735*cda5da8dSAndroid Build Coastguard Worker 736*cda5da8dSAndroid Build Coastguard Worker def is_relative_to(self, *other): 737*cda5da8dSAndroid Build Coastguard Worker """Return True if the path is relative to another path or False. 738*cda5da8dSAndroid Build Coastguard Worker """ 739*cda5da8dSAndroid Build Coastguard Worker try: 740*cda5da8dSAndroid Build Coastguard Worker self.relative_to(*other) 741*cda5da8dSAndroid Build Coastguard Worker return True 742*cda5da8dSAndroid Build Coastguard Worker except ValueError: 743*cda5da8dSAndroid Build Coastguard Worker return False 744*cda5da8dSAndroid Build Coastguard Worker 745*cda5da8dSAndroid Build Coastguard Worker @property 746*cda5da8dSAndroid Build Coastguard Worker def parts(self): 747*cda5da8dSAndroid Build Coastguard Worker """An object providing sequence-like access to the 748*cda5da8dSAndroid Build Coastguard Worker components in the filesystem path.""" 749*cda5da8dSAndroid Build Coastguard Worker # We cache the tuple to avoid building a new one each time .parts 750*cda5da8dSAndroid Build Coastguard Worker # is accessed. XXX is this necessary? 751*cda5da8dSAndroid Build Coastguard Worker try: 752*cda5da8dSAndroid Build Coastguard Worker return self._pparts 753*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 754*cda5da8dSAndroid Build Coastguard Worker self._pparts = tuple(self._parts) 755*cda5da8dSAndroid Build Coastguard Worker return self._pparts 756*cda5da8dSAndroid Build Coastguard Worker 757*cda5da8dSAndroid Build Coastguard Worker def joinpath(self, *args): 758*cda5da8dSAndroid Build Coastguard Worker """Combine this path with one or several arguments, and return a 759*cda5da8dSAndroid Build Coastguard Worker new path representing either a subpath (if all arguments are relative 760*cda5da8dSAndroid Build Coastguard Worker paths) or a totally different path (if one of the arguments is 761*cda5da8dSAndroid Build Coastguard Worker anchored). 762*cda5da8dSAndroid Build Coastguard Worker """ 763*cda5da8dSAndroid Build Coastguard Worker return self._make_child(args) 764*cda5da8dSAndroid Build Coastguard Worker 765*cda5da8dSAndroid Build Coastguard Worker def __truediv__(self, key): 766*cda5da8dSAndroid Build Coastguard Worker try: 767*cda5da8dSAndroid Build Coastguard Worker return self._make_child((key,)) 768*cda5da8dSAndroid Build Coastguard Worker except TypeError: 769*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 770*cda5da8dSAndroid Build Coastguard Worker 771*cda5da8dSAndroid Build Coastguard Worker def __rtruediv__(self, key): 772*cda5da8dSAndroid Build Coastguard Worker try: 773*cda5da8dSAndroid Build Coastguard Worker return self._from_parts([key] + self._parts) 774*cda5da8dSAndroid Build Coastguard Worker except TypeError: 775*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 776*cda5da8dSAndroid Build Coastguard Worker 777*cda5da8dSAndroid Build Coastguard Worker @property 778*cda5da8dSAndroid Build Coastguard Worker def parent(self): 779*cda5da8dSAndroid Build Coastguard Worker """The logical parent of the path.""" 780*cda5da8dSAndroid Build Coastguard Worker drv = self._drv 781*cda5da8dSAndroid Build Coastguard Worker root = self._root 782*cda5da8dSAndroid Build Coastguard Worker parts = self._parts 783*cda5da8dSAndroid Build Coastguard Worker if len(parts) == 1 and (drv or root): 784*cda5da8dSAndroid Build Coastguard Worker return self 785*cda5da8dSAndroid Build Coastguard Worker return self._from_parsed_parts(drv, root, parts[:-1]) 786*cda5da8dSAndroid Build Coastguard Worker 787*cda5da8dSAndroid Build Coastguard Worker @property 788*cda5da8dSAndroid Build Coastguard Worker def parents(self): 789*cda5da8dSAndroid Build Coastguard Worker """A sequence of this path's logical parents.""" 790*cda5da8dSAndroid Build Coastguard Worker return _PathParents(self) 791*cda5da8dSAndroid Build Coastguard Worker 792*cda5da8dSAndroid Build Coastguard Worker def is_absolute(self): 793*cda5da8dSAndroid Build Coastguard Worker """True if the path is absolute (has both a root and, if applicable, 794*cda5da8dSAndroid Build Coastguard Worker a drive).""" 795*cda5da8dSAndroid Build Coastguard Worker if not self._root: 796*cda5da8dSAndroid Build Coastguard Worker return False 797*cda5da8dSAndroid Build Coastguard Worker return not self._flavour.has_drv or bool(self._drv) 798*cda5da8dSAndroid Build Coastguard Worker 799*cda5da8dSAndroid Build Coastguard Worker def is_reserved(self): 800*cda5da8dSAndroid Build Coastguard Worker """Return True if the path contains one of the special names reserved 801*cda5da8dSAndroid Build Coastguard Worker by the system, if any.""" 802*cda5da8dSAndroid Build Coastguard Worker return self._flavour.is_reserved(self._parts) 803*cda5da8dSAndroid Build Coastguard Worker 804*cda5da8dSAndroid Build Coastguard Worker def match(self, path_pattern): 805*cda5da8dSAndroid Build Coastguard Worker """ 806*cda5da8dSAndroid Build Coastguard Worker Return True if this path matches the given pattern. 807*cda5da8dSAndroid Build Coastguard Worker """ 808*cda5da8dSAndroid Build Coastguard Worker cf = self._flavour.casefold 809*cda5da8dSAndroid Build Coastguard Worker path_pattern = cf(path_pattern) 810*cda5da8dSAndroid Build Coastguard Worker drv, root, pat_parts = self._flavour.parse_parts((path_pattern,)) 811*cda5da8dSAndroid Build Coastguard Worker if not pat_parts: 812*cda5da8dSAndroid Build Coastguard Worker raise ValueError("empty pattern") 813*cda5da8dSAndroid Build Coastguard Worker if drv and drv != cf(self._drv): 814*cda5da8dSAndroid Build Coastguard Worker return False 815*cda5da8dSAndroid Build Coastguard Worker if root and root != cf(self._root): 816*cda5da8dSAndroid Build Coastguard Worker return False 817*cda5da8dSAndroid Build Coastguard Worker parts = self._cparts 818*cda5da8dSAndroid Build Coastguard Worker if drv or root: 819*cda5da8dSAndroid Build Coastguard Worker if len(pat_parts) != len(parts): 820*cda5da8dSAndroid Build Coastguard Worker return False 821*cda5da8dSAndroid Build Coastguard Worker pat_parts = pat_parts[1:] 822*cda5da8dSAndroid Build Coastguard Worker elif len(pat_parts) > len(parts): 823*cda5da8dSAndroid Build Coastguard Worker return False 824*cda5da8dSAndroid Build Coastguard Worker for part, pat in zip(reversed(parts), reversed(pat_parts)): 825*cda5da8dSAndroid Build Coastguard Worker if not fnmatch.fnmatchcase(part, pat): 826*cda5da8dSAndroid Build Coastguard Worker return False 827*cda5da8dSAndroid Build Coastguard Worker return True 828*cda5da8dSAndroid Build Coastguard Worker 829*cda5da8dSAndroid Build Coastguard Worker# Can't subclass os.PathLike from PurePath and keep the constructor 830*cda5da8dSAndroid Build Coastguard Worker# optimizations in PurePath._parse_args(). 831*cda5da8dSAndroid Build Coastguard Workeros.PathLike.register(PurePath) 832*cda5da8dSAndroid Build Coastguard Worker 833*cda5da8dSAndroid Build Coastguard Worker 834*cda5da8dSAndroid Build Coastguard Workerclass PurePosixPath(PurePath): 835*cda5da8dSAndroid Build Coastguard Worker """PurePath subclass for non-Windows systems. 836*cda5da8dSAndroid Build Coastguard Worker 837*cda5da8dSAndroid Build Coastguard Worker On a POSIX system, instantiating a PurePath should return this object. 838*cda5da8dSAndroid Build Coastguard Worker However, you can also instantiate it directly on any system. 839*cda5da8dSAndroid Build Coastguard Worker """ 840*cda5da8dSAndroid Build Coastguard Worker _flavour = _posix_flavour 841*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 842*cda5da8dSAndroid Build Coastguard Worker 843*cda5da8dSAndroid Build Coastguard Worker 844*cda5da8dSAndroid Build Coastguard Workerclass PureWindowsPath(PurePath): 845*cda5da8dSAndroid Build Coastguard Worker """PurePath subclass for Windows systems. 846*cda5da8dSAndroid Build Coastguard Worker 847*cda5da8dSAndroid Build Coastguard Worker On a Windows system, instantiating a PurePath should return this object. 848*cda5da8dSAndroid Build Coastguard Worker However, you can also instantiate it directly on any system. 849*cda5da8dSAndroid Build Coastguard Worker """ 850*cda5da8dSAndroid Build Coastguard Worker _flavour = _windows_flavour 851*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 852*cda5da8dSAndroid Build Coastguard Worker 853*cda5da8dSAndroid Build Coastguard Worker 854*cda5da8dSAndroid Build Coastguard Worker# Filesystem-accessing classes 855*cda5da8dSAndroid Build Coastguard Worker 856*cda5da8dSAndroid Build Coastguard Worker 857*cda5da8dSAndroid Build Coastguard Workerclass Path(PurePath): 858*cda5da8dSAndroid Build Coastguard Worker """PurePath subclass that can make system calls. 859*cda5da8dSAndroid Build Coastguard Worker 860*cda5da8dSAndroid Build Coastguard Worker Path represents a filesystem path but unlike PurePath, also offers 861*cda5da8dSAndroid Build Coastguard Worker methods to do system calls on path objects. Depending on your system, 862*cda5da8dSAndroid Build Coastguard Worker instantiating a Path will return either a PosixPath or a WindowsPath 863*cda5da8dSAndroid Build Coastguard Worker object. You can also instantiate a PosixPath or WindowsPath directly, 864*cda5da8dSAndroid Build Coastguard Worker but cannot instantiate a WindowsPath on a POSIX system or vice versa. 865*cda5da8dSAndroid Build Coastguard Worker """ 866*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 867*cda5da8dSAndroid Build Coastguard Worker 868*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, *args, **kwargs): 869*cda5da8dSAndroid Build Coastguard Worker if cls is Path: 870*cda5da8dSAndroid Build Coastguard Worker cls = WindowsPath if os.name == 'nt' else PosixPath 871*cda5da8dSAndroid Build Coastguard Worker self = cls._from_parts(args) 872*cda5da8dSAndroid Build Coastguard Worker if not self._flavour.is_supported: 873*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("cannot instantiate %r on your system" 874*cda5da8dSAndroid Build Coastguard Worker % (cls.__name__,)) 875*cda5da8dSAndroid Build Coastguard Worker return self 876*cda5da8dSAndroid Build Coastguard Worker 877*cda5da8dSAndroid Build Coastguard Worker def _make_child_relpath(self, part): 878*cda5da8dSAndroid Build Coastguard Worker # This is an optimization used for dir walking. `part` must be 879*cda5da8dSAndroid Build Coastguard Worker # a single part relative to this path. 880*cda5da8dSAndroid Build Coastguard Worker parts = self._parts + [part] 881*cda5da8dSAndroid Build Coastguard Worker return self._from_parsed_parts(self._drv, self._root, parts) 882*cda5da8dSAndroid Build Coastguard Worker 883*cda5da8dSAndroid Build Coastguard Worker def __enter__(self): 884*cda5da8dSAndroid Build Coastguard Worker # In previous versions of pathlib, __exit__() marked this path as 885*cda5da8dSAndroid Build Coastguard Worker # closed; subsequent attempts to perform I/O would raise an IOError. 886*cda5da8dSAndroid Build Coastguard Worker # This functionality was never documented, and had the effect of 887*cda5da8dSAndroid Build Coastguard Worker # making Path objects mutable, contrary to PEP 428. 888*cda5da8dSAndroid Build Coastguard Worker # In Python 3.9 __exit__() was made a no-op. 889*cda5da8dSAndroid Build Coastguard Worker # In Python 3.11 __enter__() began emitting DeprecationWarning. 890*cda5da8dSAndroid Build Coastguard Worker # In Python 3.13 __enter__() and __exit__() should be removed. 891*cda5da8dSAndroid Build Coastguard Worker warnings.warn("pathlib.Path.__enter__() is deprecated and scheduled " 892*cda5da8dSAndroid Build Coastguard Worker "for removal in Python 3.13; Path objects as a context " 893*cda5da8dSAndroid Build Coastguard Worker "manager is a no-op", 894*cda5da8dSAndroid Build Coastguard Worker DeprecationWarning, stacklevel=2) 895*cda5da8dSAndroid Build Coastguard Worker return self 896*cda5da8dSAndroid Build Coastguard Worker 897*cda5da8dSAndroid Build Coastguard Worker def __exit__(self, t, v, tb): 898*cda5da8dSAndroid Build Coastguard Worker pass 899*cda5da8dSAndroid Build Coastguard Worker 900*cda5da8dSAndroid Build Coastguard Worker # Public API 901*cda5da8dSAndroid Build Coastguard Worker 902*cda5da8dSAndroid Build Coastguard Worker @classmethod 903*cda5da8dSAndroid Build Coastguard Worker def cwd(cls): 904*cda5da8dSAndroid Build Coastguard Worker """Return a new path pointing to the current working directory 905*cda5da8dSAndroid Build Coastguard Worker (as returned by os.getcwd()). 906*cda5da8dSAndroid Build Coastguard Worker """ 907*cda5da8dSAndroid Build Coastguard Worker return cls(os.getcwd()) 908*cda5da8dSAndroid Build Coastguard Worker 909*cda5da8dSAndroid Build Coastguard Worker @classmethod 910*cda5da8dSAndroid Build Coastguard Worker def home(cls): 911*cda5da8dSAndroid Build Coastguard Worker """Return a new path pointing to the user's home directory (as 912*cda5da8dSAndroid Build Coastguard Worker returned by os.path.expanduser('~')). 913*cda5da8dSAndroid Build Coastguard Worker """ 914*cda5da8dSAndroid Build Coastguard Worker return cls("~").expanduser() 915*cda5da8dSAndroid Build Coastguard Worker 916*cda5da8dSAndroid Build Coastguard Worker def samefile(self, other_path): 917*cda5da8dSAndroid Build Coastguard Worker """Return whether other_path is the same or not as this file 918*cda5da8dSAndroid Build Coastguard Worker (as returned by os.path.samefile()). 919*cda5da8dSAndroid Build Coastguard Worker """ 920*cda5da8dSAndroid Build Coastguard Worker st = self.stat() 921*cda5da8dSAndroid Build Coastguard Worker try: 922*cda5da8dSAndroid Build Coastguard Worker other_st = other_path.stat() 923*cda5da8dSAndroid Build Coastguard Worker except AttributeError: 924*cda5da8dSAndroid Build Coastguard Worker other_st = self.__class__(other_path).stat() 925*cda5da8dSAndroid Build Coastguard Worker return os.path.samestat(st, other_st) 926*cda5da8dSAndroid Build Coastguard Worker 927*cda5da8dSAndroid Build Coastguard Worker def iterdir(self): 928*cda5da8dSAndroid Build Coastguard Worker """Iterate over the files in this directory. Does not yield any 929*cda5da8dSAndroid Build Coastguard Worker result for the special paths '.' and '..'. 930*cda5da8dSAndroid Build Coastguard Worker """ 931*cda5da8dSAndroid Build Coastguard Worker for name in os.listdir(self): 932*cda5da8dSAndroid Build Coastguard Worker yield self._make_child_relpath(name) 933*cda5da8dSAndroid Build Coastguard Worker 934*cda5da8dSAndroid Build Coastguard Worker def _scandir(self): 935*cda5da8dSAndroid Build Coastguard Worker # bpo-24132: a future version of pathlib will support subclassing of 936*cda5da8dSAndroid Build Coastguard Worker # pathlib.Path to customize how the filesystem is accessed. This 937*cda5da8dSAndroid Build Coastguard Worker # includes scandir(), which is used to implement glob(). 938*cda5da8dSAndroid Build Coastguard Worker return os.scandir(self) 939*cda5da8dSAndroid Build Coastguard Worker 940*cda5da8dSAndroid Build Coastguard Worker def glob(self, pattern): 941*cda5da8dSAndroid Build Coastguard Worker """Iterate over this subtree and yield all existing files (of any 942*cda5da8dSAndroid Build Coastguard Worker kind, including directories) matching the given relative pattern. 943*cda5da8dSAndroid Build Coastguard Worker """ 944*cda5da8dSAndroid Build Coastguard Worker sys.audit("pathlib.Path.glob", self, pattern) 945*cda5da8dSAndroid Build Coastguard Worker if not pattern: 946*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Unacceptable pattern: {!r}".format(pattern)) 947*cda5da8dSAndroid Build Coastguard Worker drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) 948*cda5da8dSAndroid Build Coastguard Worker if drv or root: 949*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("Non-relative patterns are unsupported") 950*cda5da8dSAndroid Build Coastguard Worker if pattern[-1] in (self._flavour.sep, self._flavour.altsep): 951*cda5da8dSAndroid Build Coastguard Worker pattern_parts.append('') 952*cda5da8dSAndroid Build Coastguard Worker selector = _make_selector(tuple(pattern_parts), self._flavour) 953*cda5da8dSAndroid Build Coastguard Worker for p in selector.select_from(self): 954*cda5da8dSAndroid Build Coastguard Worker yield p 955*cda5da8dSAndroid Build Coastguard Worker 956*cda5da8dSAndroid Build Coastguard Worker def rglob(self, pattern): 957*cda5da8dSAndroid Build Coastguard Worker """Recursively yield all existing files (of any kind, including 958*cda5da8dSAndroid Build Coastguard Worker directories) matching the given relative pattern, anywhere in 959*cda5da8dSAndroid Build Coastguard Worker this subtree. 960*cda5da8dSAndroid Build Coastguard Worker """ 961*cda5da8dSAndroid Build Coastguard Worker sys.audit("pathlib.Path.rglob", self, pattern) 962*cda5da8dSAndroid Build Coastguard Worker drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) 963*cda5da8dSAndroid Build Coastguard Worker if drv or root: 964*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("Non-relative patterns are unsupported") 965*cda5da8dSAndroid Build Coastguard Worker if pattern and pattern[-1] in (self._flavour.sep, self._flavour.altsep): 966*cda5da8dSAndroid Build Coastguard Worker pattern_parts.append('') 967*cda5da8dSAndroid Build Coastguard Worker selector = _make_selector(("**",) + tuple(pattern_parts), self._flavour) 968*cda5da8dSAndroid Build Coastguard Worker for p in selector.select_from(self): 969*cda5da8dSAndroid Build Coastguard Worker yield p 970*cda5da8dSAndroid Build Coastguard Worker 971*cda5da8dSAndroid Build Coastguard Worker def absolute(self): 972*cda5da8dSAndroid Build Coastguard Worker """Return an absolute version of this path by prepending the current 973*cda5da8dSAndroid Build Coastguard Worker working directory. No normalization or symlink resolution is performed. 974*cda5da8dSAndroid Build Coastguard Worker 975*cda5da8dSAndroid Build Coastguard Worker Use resolve() to get the canonical path to a file. 976*cda5da8dSAndroid Build Coastguard Worker """ 977*cda5da8dSAndroid Build Coastguard Worker if self.is_absolute(): 978*cda5da8dSAndroid Build Coastguard Worker return self 979*cda5da8dSAndroid Build Coastguard Worker return self._from_parts([self.cwd()] + self._parts) 980*cda5da8dSAndroid Build Coastguard Worker 981*cda5da8dSAndroid Build Coastguard Worker def resolve(self, strict=False): 982*cda5da8dSAndroid Build Coastguard Worker """ 983*cda5da8dSAndroid Build Coastguard Worker Make the path absolute, resolving all symlinks on the way and also 984*cda5da8dSAndroid Build Coastguard Worker normalizing it. 985*cda5da8dSAndroid Build Coastguard Worker """ 986*cda5da8dSAndroid Build Coastguard Worker 987*cda5da8dSAndroid Build Coastguard Worker def check_eloop(e): 988*cda5da8dSAndroid Build Coastguard Worker winerror = getattr(e, 'winerror', 0) 989*cda5da8dSAndroid Build Coastguard Worker if e.errno == ELOOP or winerror == _WINERROR_CANT_RESOLVE_FILENAME: 990*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError("Symlink loop from %r" % e.filename) 991*cda5da8dSAndroid Build Coastguard Worker 992*cda5da8dSAndroid Build Coastguard Worker try: 993*cda5da8dSAndroid Build Coastguard Worker s = os.path.realpath(self, strict=strict) 994*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 995*cda5da8dSAndroid Build Coastguard Worker check_eloop(e) 996*cda5da8dSAndroid Build Coastguard Worker raise 997*cda5da8dSAndroid Build Coastguard Worker p = self._from_parts((s,)) 998*cda5da8dSAndroid Build Coastguard Worker 999*cda5da8dSAndroid Build Coastguard Worker # In non-strict mode, realpath() doesn't raise on symlink loops. 1000*cda5da8dSAndroid Build Coastguard Worker # Ensure we get an exception by calling stat() 1001*cda5da8dSAndroid Build Coastguard Worker if not strict: 1002*cda5da8dSAndroid Build Coastguard Worker try: 1003*cda5da8dSAndroid Build Coastguard Worker p.stat() 1004*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1005*cda5da8dSAndroid Build Coastguard Worker check_eloop(e) 1006*cda5da8dSAndroid Build Coastguard Worker return p 1007*cda5da8dSAndroid Build Coastguard Worker 1008*cda5da8dSAndroid Build Coastguard Worker def stat(self, *, follow_symlinks=True): 1009*cda5da8dSAndroid Build Coastguard Worker """ 1010*cda5da8dSAndroid Build Coastguard Worker Return the result of the stat() system call on this path, like 1011*cda5da8dSAndroid Build Coastguard Worker os.stat() does. 1012*cda5da8dSAndroid Build Coastguard Worker """ 1013*cda5da8dSAndroid Build Coastguard Worker return os.stat(self, follow_symlinks=follow_symlinks) 1014*cda5da8dSAndroid Build Coastguard Worker 1015*cda5da8dSAndroid Build Coastguard Worker def owner(self): 1016*cda5da8dSAndroid Build Coastguard Worker """ 1017*cda5da8dSAndroid Build Coastguard Worker Return the login name of the file owner. 1018*cda5da8dSAndroid Build Coastguard Worker """ 1019*cda5da8dSAndroid Build Coastguard Worker try: 1020*cda5da8dSAndroid Build Coastguard Worker import pwd 1021*cda5da8dSAndroid Build Coastguard Worker return pwd.getpwuid(self.stat().st_uid).pw_name 1022*cda5da8dSAndroid Build Coastguard Worker except ImportError: 1023*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("Path.owner() is unsupported on this system") 1024*cda5da8dSAndroid Build Coastguard Worker 1025*cda5da8dSAndroid Build Coastguard Worker def group(self): 1026*cda5da8dSAndroid Build Coastguard Worker """ 1027*cda5da8dSAndroid Build Coastguard Worker Return the group name of the file gid. 1028*cda5da8dSAndroid Build Coastguard Worker """ 1029*cda5da8dSAndroid Build Coastguard Worker 1030*cda5da8dSAndroid Build Coastguard Worker try: 1031*cda5da8dSAndroid Build Coastguard Worker import grp 1032*cda5da8dSAndroid Build Coastguard Worker return grp.getgrgid(self.stat().st_gid).gr_name 1033*cda5da8dSAndroid Build Coastguard Worker except ImportError: 1034*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("Path.group() is unsupported on this system") 1035*cda5da8dSAndroid Build Coastguard Worker 1036*cda5da8dSAndroid Build Coastguard Worker def open(self, mode='r', buffering=-1, encoding=None, 1037*cda5da8dSAndroid Build Coastguard Worker errors=None, newline=None): 1038*cda5da8dSAndroid Build Coastguard Worker """ 1039*cda5da8dSAndroid Build Coastguard Worker Open the file pointed by this path and return a file object, as 1040*cda5da8dSAndroid Build Coastguard Worker the built-in open() function does. 1041*cda5da8dSAndroid Build Coastguard Worker """ 1042*cda5da8dSAndroid Build Coastguard Worker if "b" not in mode: 1043*cda5da8dSAndroid Build Coastguard Worker encoding = io.text_encoding(encoding) 1044*cda5da8dSAndroid Build Coastguard Worker return io.open(self, mode, buffering, encoding, errors, newline) 1045*cda5da8dSAndroid Build Coastguard Worker 1046*cda5da8dSAndroid Build Coastguard Worker def read_bytes(self): 1047*cda5da8dSAndroid Build Coastguard Worker """ 1048*cda5da8dSAndroid Build Coastguard Worker Open the file in bytes mode, read it, and close the file. 1049*cda5da8dSAndroid Build Coastguard Worker """ 1050*cda5da8dSAndroid Build Coastguard Worker with self.open(mode='rb') as f: 1051*cda5da8dSAndroid Build Coastguard Worker return f.read() 1052*cda5da8dSAndroid Build Coastguard Worker 1053*cda5da8dSAndroid Build Coastguard Worker def read_text(self, encoding=None, errors=None): 1054*cda5da8dSAndroid Build Coastguard Worker """ 1055*cda5da8dSAndroid Build Coastguard Worker Open the file in text mode, read it, and close the file. 1056*cda5da8dSAndroid Build Coastguard Worker """ 1057*cda5da8dSAndroid Build Coastguard Worker encoding = io.text_encoding(encoding) 1058*cda5da8dSAndroid Build Coastguard Worker with self.open(mode='r', encoding=encoding, errors=errors) as f: 1059*cda5da8dSAndroid Build Coastguard Worker return f.read() 1060*cda5da8dSAndroid Build Coastguard Worker 1061*cda5da8dSAndroid Build Coastguard Worker def write_bytes(self, data): 1062*cda5da8dSAndroid Build Coastguard Worker """ 1063*cda5da8dSAndroid Build Coastguard Worker Open the file in bytes mode, write to it, and close the file. 1064*cda5da8dSAndroid Build Coastguard Worker """ 1065*cda5da8dSAndroid Build Coastguard Worker # type-check for the buffer interface before truncating the file 1066*cda5da8dSAndroid Build Coastguard Worker view = memoryview(data) 1067*cda5da8dSAndroid Build Coastguard Worker with self.open(mode='wb') as f: 1068*cda5da8dSAndroid Build Coastguard Worker return f.write(view) 1069*cda5da8dSAndroid Build Coastguard Worker 1070*cda5da8dSAndroid Build Coastguard Worker def write_text(self, data, encoding=None, errors=None, newline=None): 1071*cda5da8dSAndroid Build Coastguard Worker """ 1072*cda5da8dSAndroid Build Coastguard Worker Open the file in text mode, write to it, and close the file. 1073*cda5da8dSAndroid Build Coastguard Worker """ 1074*cda5da8dSAndroid Build Coastguard Worker if not isinstance(data, str): 1075*cda5da8dSAndroid Build Coastguard Worker raise TypeError('data must be str, not %s' % 1076*cda5da8dSAndroid Build Coastguard Worker data.__class__.__name__) 1077*cda5da8dSAndroid Build Coastguard Worker encoding = io.text_encoding(encoding) 1078*cda5da8dSAndroid Build Coastguard Worker with self.open(mode='w', encoding=encoding, errors=errors, newline=newline) as f: 1079*cda5da8dSAndroid Build Coastguard Worker return f.write(data) 1080*cda5da8dSAndroid Build Coastguard Worker 1081*cda5da8dSAndroid Build Coastguard Worker def readlink(self): 1082*cda5da8dSAndroid Build Coastguard Worker """ 1083*cda5da8dSAndroid Build Coastguard Worker Return the path to which the symbolic link points. 1084*cda5da8dSAndroid Build Coastguard Worker """ 1085*cda5da8dSAndroid Build Coastguard Worker if not hasattr(os, "readlink"): 1086*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("os.readlink() not available on this system") 1087*cda5da8dSAndroid Build Coastguard Worker return self._from_parts((os.readlink(self),)) 1088*cda5da8dSAndroid Build Coastguard Worker 1089*cda5da8dSAndroid Build Coastguard Worker def touch(self, mode=0o666, exist_ok=True): 1090*cda5da8dSAndroid Build Coastguard Worker """ 1091*cda5da8dSAndroid Build Coastguard Worker Create this file with the given access mode, if it doesn't exist. 1092*cda5da8dSAndroid Build Coastguard Worker """ 1093*cda5da8dSAndroid Build Coastguard Worker 1094*cda5da8dSAndroid Build Coastguard Worker if exist_ok: 1095*cda5da8dSAndroid Build Coastguard Worker # First try to bump modification time 1096*cda5da8dSAndroid Build Coastguard Worker # Implementation note: GNU touch uses the UTIME_NOW option of 1097*cda5da8dSAndroid Build Coastguard Worker # the utimensat() / futimens() functions. 1098*cda5da8dSAndroid Build Coastguard Worker try: 1099*cda5da8dSAndroid Build Coastguard Worker os.utime(self, None) 1100*cda5da8dSAndroid Build Coastguard Worker except OSError: 1101*cda5da8dSAndroid Build Coastguard Worker # Avoid exception chaining 1102*cda5da8dSAndroid Build Coastguard Worker pass 1103*cda5da8dSAndroid Build Coastguard Worker else: 1104*cda5da8dSAndroid Build Coastguard Worker return 1105*cda5da8dSAndroid Build Coastguard Worker flags = os.O_CREAT | os.O_WRONLY 1106*cda5da8dSAndroid Build Coastguard Worker if not exist_ok: 1107*cda5da8dSAndroid Build Coastguard Worker flags |= os.O_EXCL 1108*cda5da8dSAndroid Build Coastguard Worker fd = os.open(self, flags, mode) 1109*cda5da8dSAndroid Build Coastguard Worker os.close(fd) 1110*cda5da8dSAndroid Build Coastguard Worker 1111*cda5da8dSAndroid Build Coastguard Worker def mkdir(self, mode=0o777, parents=False, exist_ok=False): 1112*cda5da8dSAndroid Build Coastguard Worker """ 1113*cda5da8dSAndroid Build Coastguard Worker Create a new directory at this given path. 1114*cda5da8dSAndroid Build Coastguard Worker """ 1115*cda5da8dSAndroid Build Coastguard Worker try: 1116*cda5da8dSAndroid Build Coastguard Worker os.mkdir(self, mode) 1117*cda5da8dSAndroid Build Coastguard Worker except FileNotFoundError: 1118*cda5da8dSAndroid Build Coastguard Worker if not parents or self.parent == self: 1119*cda5da8dSAndroid Build Coastguard Worker raise 1120*cda5da8dSAndroid Build Coastguard Worker self.parent.mkdir(parents=True, exist_ok=True) 1121*cda5da8dSAndroid Build Coastguard Worker self.mkdir(mode, parents=False, exist_ok=exist_ok) 1122*cda5da8dSAndroid Build Coastguard Worker except OSError: 1123*cda5da8dSAndroid Build Coastguard Worker # Cannot rely on checking for EEXIST, since the operating system 1124*cda5da8dSAndroid Build Coastguard Worker # could give priority to other errors like EACCES or EROFS 1125*cda5da8dSAndroid Build Coastguard Worker if not exist_ok or not self.is_dir(): 1126*cda5da8dSAndroid Build Coastguard Worker raise 1127*cda5da8dSAndroid Build Coastguard Worker 1128*cda5da8dSAndroid Build Coastguard Worker def chmod(self, mode, *, follow_symlinks=True): 1129*cda5da8dSAndroid Build Coastguard Worker """ 1130*cda5da8dSAndroid Build Coastguard Worker Change the permissions of the path, like os.chmod(). 1131*cda5da8dSAndroid Build Coastguard Worker """ 1132*cda5da8dSAndroid Build Coastguard Worker os.chmod(self, mode, follow_symlinks=follow_symlinks) 1133*cda5da8dSAndroid Build Coastguard Worker 1134*cda5da8dSAndroid Build Coastguard Worker def lchmod(self, mode): 1135*cda5da8dSAndroid Build Coastguard Worker """ 1136*cda5da8dSAndroid Build Coastguard Worker Like chmod(), except if the path points to a symlink, the symlink's 1137*cda5da8dSAndroid Build Coastguard Worker permissions are changed, rather than its target's. 1138*cda5da8dSAndroid Build Coastguard Worker """ 1139*cda5da8dSAndroid Build Coastguard Worker self.chmod(mode, follow_symlinks=False) 1140*cda5da8dSAndroid Build Coastguard Worker 1141*cda5da8dSAndroid Build Coastguard Worker def unlink(self, missing_ok=False): 1142*cda5da8dSAndroid Build Coastguard Worker """ 1143*cda5da8dSAndroid Build Coastguard Worker Remove this file or link. 1144*cda5da8dSAndroid Build Coastguard Worker If the path is a directory, use rmdir() instead. 1145*cda5da8dSAndroid Build Coastguard Worker """ 1146*cda5da8dSAndroid Build Coastguard Worker try: 1147*cda5da8dSAndroid Build Coastguard Worker os.unlink(self) 1148*cda5da8dSAndroid Build Coastguard Worker except FileNotFoundError: 1149*cda5da8dSAndroid Build Coastguard Worker if not missing_ok: 1150*cda5da8dSAndroid Build Coastguard Worker raise 1151*cda5da8dSAndroid Build Coastguard Worker 1152*cda5da8dSAndroid Build Coastguard Worker def rmdir(self): 1153*cda5da8dSAndroid Build Coastguard Worker """ 1154*cda5da8dSAndroid Build Coastguard Worker Remove this directory. The directory must be empty. 1155*cda5da8dSAndroid Build Coastguard Worker """ 1156*cda5da8dSAndroid Build Coastguard Worker os.rmdir(self) 1157*cda5da8dSAndroid Build Coastguard Worker 1158*cda5da8dSAndroid Build Coastguard Worker def lstat(self): 1159*cda5da8dSAndroid Build Coastguard Worker """ 1160*cda5da8dSAndroid Build Coastguard Worker Like stat(), except if the path points to a symlink, the symlink's 1161*cda5da8dSAndroid Build Coastguard Worker status information is returned, rather than its target's. 1162*cda5da8dSAndroid Build Coastguard Worker """ 1163*cda5da8dSAndroid Build Coastguard Worker return self.stat(follow_symlinks=False) 1164*cda5da8dSAndroid Build Coastguard Worker 1165*cda5da8dSAndroid Build Coastguard Worker def rename(self, target): 1166*cda5da8dSAndroid Build Coastguard Worker """ 1167*cda5da8dSAndroid Build Coastguard Worker Rename this path to the target path. 1168*cda5da8dSAndroid Build Coastguard Worker 1169*cda5da8dSAndroid Build Coastguard Worker The target path may be absolute or relative. Relative paths are 1170*cda5da8dSAndroid Build Coastguard Worker interpreted relative to the current working directory, *not* the 1171*cda5da8dSAndroid Build Coastguard Worker directory of the Path object. 1172*cda5da8dSAndroid Build Coastguard Worker 1173*cda5da8dSAndroid Build Coastguard Worker Returns the new Path instance pointing to the target path. 1174*cda5da8dSAndroid Build Coastguard Worker """ 1175*cda5da8dSAndroid Build Coastguard Worker os.rename(self, target) 1176*cda5da8dSAndroid Build Coastguard Worker return self.__class__(target) 1177*cda5da8dSAndroid Build Coastguard Worker 1178*cda5da8dSAndroid Build Coastguard Worker def replace(self, target): 1179*cda5da8dSAndroid Build Coastguard Worker """ 1180*cda5da8dSAndroid Build Coastguard Worker Rename this path to the target path, overwriting if that path exists. 1181*cda5da8dSAndroid Build Coastguard Worker 1182*cda5da8dSAndroid Build Coastguard Worker The target path may be absolute or relative. Relative paths are 1183*cda5da8dSAndroid Build Coastguard Worker interpreted relative to the current working directory, *not* the 1184*cda5da8dSAndroid Build Coastguard Worker directory of the Path object. 1185*cda5da8dSAndroid Build Coastguard Worker 1186*cda5da8dSAndroid Build Coastguard Worker Returns the new Path instance pointing to the target path. 1187*cda5da8dSAndroid Build Coastguard Worker """ 1188*cda5da8dSAndroid Build Coastguard Worker os.replace(self, target) 1189*cda5da8dSAndroid Build Coastguard Worker return self.__class__(target) 1190*cda5da8dSAndroid Build Coastguard Worker 1191*cda5da8dSAndroid Build Coastguard Worker def symlink_to(self, target, target_is_directory=False): 1192*cda5da8dSAndroid Build Coastguard Worker """ 1193*cda5da8dSAndroid Build Coastguard Worker Make this path a symlink pointing to the target path. 1194*cda5da8dSAndroid Build Coastguard Worker Note the order of arguments (link, target) is the reverse of os.symlink. 1195*cda5da8dSAndroid Build Coastguard Worker """ 1196*cda5da8dSAndroid Build Coastguard Worker if not hasattr(os, "symlink"): 1197*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("os.symlink() not available on this system") 1198*cda5da8dSAndroid Build Coastguard Worker os.symlink(target, self, target_is_directory) 1199*cda5da8dSAndroid Build Coastguard Worker 1200*cda5da8dSAndroid Build Coastguard Worker def hardlink_to(self, target): 1201*cda5da8dSAndroid Build Coastguard Worker """ 1202*cda5da8dSAndroid Build Coastguard Worker Make this path a hard link pointing to the same file as *target*. 1203*cda5da8dSAndroid Build Coastguard Worker 1204*cda5da8dSAndroid Build Coastguard Worker Note the order of arguments (self, target) is the reverse of os.link's. 1205*cda5da8dSAndroid Build Coastguard Worker """ 1206*cda5da8dSAndroid Build Coastguard Worker if not hasattr(os, "link"): 1207*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("os.link() not available on this system") 1208*cda5da8dSAndroid Build Coastguard Worker os.link(target, self) 1209*cda5da8dSAndroid Build Coastguard Worker 1210*cda5da8dSAndroid Build Coastguard Worker def link_to(self, target): 1211*cda5da8dSAndroid Build Coastguard Worker """ 1212*cda5da8dSAndroid Build Coastguard Worker Make the target path a hard link pointing to this path. 1213*cda5da8dSAndroid Build Coastguard Worker 1214*cda5da8dSAndroid Build Coastguard Worker Note this function does not make this path a hard link to *target*, 1215*cda5da8dSAndroid Build Coastguard Worker despite the implication of the function and argument names. The order 1216*cda5da8dSAndroid Build Coastguard Worker of arguments (target, link) is the reverse of Path.symlink_to, but 1217*cda5da8dSAndroid Build Coastguard Worker matches that of os.link. 1218*cda5da8dSAndroid Build Coastguard Worker 1219*cda5da8dSAndroid Build Coastguard Worker Deprecated since Python 3.10 and scheduled for removal in Python 3.12. 1220*cda5da8dSAndroid Build Coastguard Worker Use `hardlink_to()` instead. 1221*cda5da8dSAndroid Build Coastguard Worker """ 1222*cda5da8dSAndroid Build Coastguard Worker warnings.warn("pathlib.Path.link_to() is deprecated and is scheduled " 1223*cda5da8dSAndroid Build Coastguard Worker "for removal in Python 3.12. " 1224*cda5da8dSAndroid Build Coastguard Worker "Use pathlib.Path.hardlink_to() instead.", 1225*cda5da8dSAndroid Build Coastguard Worker DeprecationWarning, stacklevel=2) 1226*cda5da8dSAndroid Build Coastguard Worker self.__class__(target).hardlink_to(self) 1227*cda5da8dSAndroid Build Coastguard Worker 1228*cda5da8dSAndroid Build Coastguard Worker # Convenience functions for querying the stat results 1229*cda5da8dSAndroid Build Coastguard Worker 1230*cda5da8dSAndroid Build Coastguard Worker def exists(self): 1231*cda5da8dSAndroid Build Coastguard Worker """ 1232*cda5da8dSAndroid Build Coastguard Worker Whether this path exists. 1233*cda5da8dSAndroid Build Coastguard Worker """ 1234*cda5da8dSAndroid Build Coastguard Worker try: 1235*cda5da8dSAndroid Build Coastguard Worker self.stat() 1236*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1237*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1238*cda5da8dSAndroid Build Coastguard Worker raise 1239*cda5da8dSAndroid Build Coastguard Worker return False 1240*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1241*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1242*cda5da8dSAndroid Build Coastguard Worker return False 1243*cda5da8dSAndroid Build Coastguard Worker return True 1244*cda5da8dSAndroid Build Coastguard Worker 1245*cda5da8dSAndroid Build Coastguard Worker def is_dir(self): 1246*cda5da8dSAndroid Build Coastguard Worker """ 1247*cda5da8dSAndroid Build Coastguard Worker Whether this path is a directory. 1248*cda5da8dSAndroid Build Coastguard Worker """ 1249*cda5da8dSAndroid Build Coastguard Worker try: 1250*cda5da8dSAndroid Build Coastguard Worker return S_ISDIR(self.stat().st_mode) 1251*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1252*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1253*cda5da8dSAndroid Build Coastguard Worker raise 1254*cda5da8dSAndroid Build Coastguard Worker # Path doesn't exist or is a broken symlink 1255*cda5da8dSAndroid Build Coastguard Worker # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) 1256*cda5da8dSAndroid Build Coastguard Worker return False 1257*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1258*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1259*cda5da8dSAndroid Build Coastguard Worker return False 1260*cda5da8dSAndroid Build Coastguard Worker 1261*cda5da8dSAndroid Build Coastguard Worker def is_file(self): 1262*cda5da8dSAndroid Build Coastguard Worker """ 1263*cda5da8dSAndroid Build Coastguard Worker Whether this path is a regular file (also True for symlinks pointing 1264*cda5da8dSAndroid Build Coastguard Worker to regular files). 1265*cda5da8dSAndroid Build Coastguard Worker """ 1266*cda5da8dSAndroid Build Coastguard Worker try: 1267*cda5da8dSAndroid Build Coastguard Worker return S_ISREG(self.stat().st_mode) 1268*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1269*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1270*cda5da8dSAndroid Build Coastguard Worker raise 1271*cda5da8dSAndroid Build Coastguard Worker # Path doesn't exist or is a broken symlink 1272*cda5da8dSAndroid Build Coastguard Worker # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) 1273*cda5da8dSAndroid Build Coastguard Worker return False 1274*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1275*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1276*cda5da8dSAndroid Build Coastguard Worker return False 1277*cda5da8dSAndroid Build Coastguard Worker 1278*cda5da8dSAndroid Build Coastguard Worker def is_mount(self): 1279*cda5da8dSAndroid Build Coastguard Worker """ 1280*cda5da8dSAndroid Build Coastguard Worker Check if this path is a POSIX mount point 1281*cda5da8dSAndroid Build Coastguard Worker """ 1282*cda5da8dSAndroid Build Coastguard Worker # Need to exist and be a dir 1283*cda5da8dSAndroid Build Coastguard Worker if not self.exists() or not self.is_dir(): 1284*cda5da8dSAndroid Build Coastguard Worker return False 1285*cda5da8dSAndroid Build Coastguard Worker 1286*cda5da8dSAndroid Build Coastguard Worker try: 1287*cda5da8dSAndroid Build Coastguard Worker parent_dev = self.parent.stat().st_dev 1288*cda5da8dSAndroid Build Coastguard Worker except OSError: 1289*cda5da8dSAndroid Build Coastguard Worker return False 1290*cda5da8dSAndroid Build Coastguard Worker 1291*cda5da8dSAndroid Build Coastguard Worker dev = self.stat().st_dev 1292*cda5da8dSAndroid Build Coastguard Worker if dev != parent_dev: 1293*cda5da8dSAndroid Build Coastguard Worker return True 1294*cda5da8dSAndroid Build Coastguard Worker ino = self.stat().st_ino 1295*cda5da8dSAndroid Build Coastguard Worker parent_ino = self.parent.stat().st_ino 1296*cda5da8dSAndroid Build Coastguard Worker return ino == parent_ino 1297*cda5da8dSAndroid Build Coastguard Worker 1298*cda5da8dSAndroid Build Coastguard Worker def is_symlink(self): 1299*cda5da8dSAndroid Build Coastguard Worker """ 1300*cda5da8dSAndroid Build Coastguard Worker Whether this path is a symbolic link. 1301*cda5da8dSAndroid Build Coastguard Worker """ 1302*cda5da8dSAndroid Build Coastguard Worker try: 1303*cda5da8dSAndroid Build Coastguard Worker return S_ISLNK(self.lstat().st_mode) 1304*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1305*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1306*cda5da8dSAndroid Build Coastguard Worker raise 1307*cda5da8dSAndroid Build Coastguard Worker # Path doesn't exist 1308*cda5da8dSAndroid Build Coastguard Worker return False 1309*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1310*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1311*cda5da8dSAndroid Build Coastguard Worker return False 1312*cda5da8dSAndroid Build Coastguard Worker 1313*cda5da8dSAndroid Build Coastguard Worker def is_block_device(self): 1314*cda5da8dSAndroid Build Coastguard Worker """ 1315*cda5da8dSAndroid Build Coastguard Worker Whether this path is a block device. 1316*cda5da8dSAndroid Build Coastguard Worker """ 1317*cda5da8dSAndroid Build Coastguard Worker try: 1318*cda5da8dSAndroid Build Coastguard Worker return S_ISBLK(self.stat().st_mode) 1319*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1320*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1321*cda5da8dSAndroid Build Coastguard Worker raise 1322*cda5da8dSAndroid Build Coastguard Worker # Path doesn't exist or is a broken symlink 1323*cda5da8dSAndroid Build Coastguard Worker # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) 1324*cda5da8dSAndroid Build Coastguard Worker return False 1325*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1326*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1327*cda5da8dSAndroid Build Coastguard Worker return False 1328*cda5da8dSAndroid Build Coastguard Worker 1329*cda5da8dSAndroid Build Coastguard Worker def is_char_device(self): 1330*cda5da8dSAndroid Build Coastguard Worker """ 1331*cda5da8dSAndroid Build Coastguard Worker Whether this path is a character device. 1332*cda5da8dSAndroid Build Coastguard Worker """ 1333*cda5da8dSAndroid Build Coastguard Worker try: 1334*cda5da8dSAndroid Build Coastguard Worker return S_ISCHR(self.stat().st_mode) 1335*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1336*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1337*cda5da8dSAndroid Build Coastguard Worker raise 1338*cda5da8dSAndroid Build Coastguard Worker # Path doesn't exist or is a broken symlink 1339*cda5da8dSAndroid Build Coastguard Worker # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) 1340*cda5da8dSAndroid Build Coastguard Worker return False 1341*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1342*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1343*cda5da8dSAndroid Build Coastguard Worker return False 1344*cda5da8dSAndroid Build Coastguard Worker 1345*cda5da8dSAndroid Build Coastguard Worker def is_fifo(self): 1346*cda5da8dSAndroid Build Coastguard Worker """ 1347*cda5da8dSAndroid Build Coastguard Worker Whether this path is a FIFO. 1348*cda5da8dSAndroid Build Coastguard Worker """ 1349*cda5da8dSAndroid Build Coastguard Worker try: 1350*cda5da8dSAndroid Build Coastguard Worker return S_ISFIFO(self.stat().st_mode) 1351*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1352*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1353*cda5da8dSAndroid Build Coastguard Worker raise 1354*cda5da8dSAndroid Build Coastguard Worker # Path doesn't exist or is a broken symlink 1355*cda5da8dSAndroid Build Coastguard Worker # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) 1356*cda5da8dSAndroid Build Coastguard Worker return False 1357*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1358*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1359*cda5da8dSAndroid Build Coastguard Worker return False 1360*cda5da8dSAndroid Build Coastguard Worker 1361*cda5da8dSAndroid Build Coastguard Worker def is_socket(self): 1362*cda5da8dSAndroid Build Coastguard Worker """ 1363*cda5da8dSAndroid Build Coastguard Worker Whether this path is a socket. 1364*cda5da8dSAndroid Build Coastguard Worker """ 1365*cda5da8dSAndroid Build Coastguard Worker try: 1366*cda5da8dSAndroid Build Coastguard Worker return S_ISSOCK(self.stat().st_mode) 1367*cda5da8dSAndroid Build Coastguard Worker except OSError as e: 1368*cda5da8dSAndroid Build Coastguard Worker if not _ignore_error(e): 1369*cda5da8dSAndroid Build Coastguard Worker raise 1370*cda5da8dSAndroid Build Coastguard Worker # Path doesn't exist or is a broken symlink 1371*cda5da8dSAndroid Build Coastguard Worker # (see http://web.archive.org/web/20200623061726/https://bitbucket.org/pitrou/pathlib/issues/12/ ) 1372*cda5da8dSAndroid Build Coastguard Worker return False 1373*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1374*cda5da8dSAndroid Build Coastguard Worker # Non-encodable path 1375*cda5da8dSAndroid Build Coastguard Worker return False 1376*cda5da8dSAndroid Build Coastguard Worker 1377*cda5da8dSAndroid Build Coastguard Worker def expanduser(self): 1378*cda5da8dSAndroid Build Coastguard Worker """ Return a new path with expanded ~ and ~user constructs 1379*cda5da8dSAndroid Build Coastguard Worker (as returned by os.path.expanduser) 1380*cda5da8dSAndroid Build Coastguard Worker """ 1381*cda5da8dSAndroid Build Coastguard Worker if (not (self._drv or self._root) and 1382*cda5da8dSAndroid Build Coastguard Worker self._parts and self._parts[0][:1] == '~'): 1383*cda5da8dSAndroid Build Coastguard Worker homedir = os.path.expanduser(self._parts[0]) 1384*cda5da8dSAndroid Build Coastguard Worker if homedir[:1] == "~": 1385*cda5da8dSAndroid Build Coastguard Worker raise RuntimeError("Could not determine home directory.") 1386*cda5da8dSAndroid Build Coastguard Worker return self._from_parts([homedir] + self._parts[1:]) 1387*cda5da8dSAndroid Build Coastguard Worker 1388*cda5da8dSAndroid Build Coastguard Worker return self 1389*cda5da8dSAndroid Build Coastguard Worker 1390*cda5da8dSAndroid Build Coastguard Worker 1391*cda5da8dSAndroid Build Coastguard Workerclass PosixPath(Path, PurePosixPath): 1392*cda5da8dSAndroid Build Coastguard Worker """Path subclass for non-Windows systems. 1393*cda5da8dSAndroid Build Coastguard Worker 1394*cda5da8dSAndroid Build Coastguard Worker On a POSIX system, instantiating a Path should return this object. 1395*cda5da8dSAndroid Build Coastguard Worker """ 1396*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 1397*cda5da8dSAndroid Build Coastguard Worker 1398*cda5da8dSAndroid Build Coastguard Workerclass WindowsPath(Path, PureWindowsPath): 1399*cda5da8dSAndroid Build Coastguard Worker """Path subclass for Windows systems. 1400*cda5da8dSAndroid Build Coastguard Worker 1401*cda5da8dSAndroid Build Coastguard Worker On a Windows system, instantiating a Path should return this object. 1402*cda5da8dSAndroid Build Coastguard Worker """ 1403*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 1404*cda5da8dSAndroid Build Coastguard Worker 1405*cda5da8dSAndroid Build Coastguard Worker def is_mount(self): 1406*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("Path.is_mount() is unsupported on this system") 1407