xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/pathlib.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
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